From 15ac35135190388268a05bdc9f87b0ea4780e786 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Mon, 16 Oct 2023 08:23:12 -0700 Subject: [PATCH 01/87] [DOCS] Add preconfigured AWS Bedrock connector (#168663) --- docs/action-type-template.asciidoc | 35 +------------------ docs/management/action-types.asciidoc | 4 +-- .../connectors/action-types/bedrock.asciidoc | 24 ++++++------- .../pre-configured-connectors.asciidoc | 32 ++++++++++++++++- docs/settings/alert-action-settings.asciidoc | 14 +++++++- 5 files changed, 59 insertions(+), 50 deletions(-) diff --git a/docs/action-type-template.asciidoc b/docs/action-type-template.asciidoc index 8ff643c883a40c..9bd61039712b3a 100644 --- a/docs/action-type-template.asciidoc +++ b/docs/action-type-template.asciidoc @@ -28,42 +28,9 @@ List of user-facing connector configurations. This should align with the fields Property1:: A short description of this property. Property2:: A short description of this property with format hints. This can be specified in `this specific format`. -[float] -[[preconfigured--configuration]] -=== Create preconfigured connectors - -If you are running {kib} on-prem, you can define connectors by -adding `xpack.actions.preconfigured` settings to your `kibana.yml` file. -For example: - -//// -Example preconfigured format for this connector type -//// - -[source,text] --- -xpack.actions.preconfigured: - my-: - name: preconfigured--connector-type - actionTypeId: . - config: - property1: value1 - property2: value2 - secrets: - property3: value3 --- - //// -List of properties from the ConfigSchema and SecretsSchema for this action type. +Add preconfigured settings for this connector type in alert-action-settings.asciidoc and an example in pre-configured-connectors.asciidoc. //// -Config defines information for the connector type. - -`property1`:: A short description of this property. -`property2`:: A short descriptionn of this property. - -Secrets defines sensitive information for the connector type. - -`property3`:: A short descriptionn of this property. [float] [[-action-configuration]] diff --git a/docs/management/action-types.asciidoc b/docs/management/action-types.asciidoc index 357d0e5de50ea8..a8a6409ec49ba0 100644 --- a/docs/management/action-types.asciidoc +++ b/docs/management/action-types.asciidoc @@ -7,9 +7,9 @@ Connectors provide a central place to store connection information for services [cols="2"] |=== -a| <> +a| <> -| Send a request to AWS Bedrock. +| Send a request to {bedrock}. a| <> diff --git a/docs/management/connectors/action-types/bedrock.asciidoc b/docs/management/connectors/action-types/bedrock.asciidoc index afefc5914435f1..a01a750ae77aa3 100644 --- a/docs/management/connectors/action-types/bedrock.asciidoc +++ b/docs/management/connectors/action-types/bedrock.asciidoc @@ -1,15 +1,15 @@ [[bedrock-action-type]] -== AWS Bedrock connector and action +== {bedrock} connector and action ++++ -AWS Bedrock +{bedrock} ++++ -:frontmatter-description: Add a connector that can send requests to AWS Bedrock. +:frontmatter-description: Add a connector that can send requests to {bedrock}. :frontmatter-tags-products: [kibana] :frontmatter-tags-content-type: [how-to] :frontmatter-tags-user-goals: [configure] -The AWS Bedrock connector uses https://github.com/axios/axios[axios] to send a POST request to AWS Bedrock. The connector uses the <> to send the request. +The {bedrock} connector uses https://github.com/axios/axios[axios] to send a POST request to {bedrock}. The connector uses the <> to send the request. [float] [[define-bedrock-ui]] @@ -19,18 +19,18 @@ You can create connectors in *{stack-manage-app} > {connectors-ui}*. For exampl [role="screenshot"] // TODO: need logo before screenshot -image::management/connectors/images/bedrock-connector.png[AWS Bedrock connector] +image::management/connectors/images/bedrock-connector.png[{bedrock} connector] [float] [[bedrock-connector-configuration]] ==== Connector configuration -AWS Bedrock connectors have the following configuration properties: +{bedrock} connectors have the following configuration properties: Name:: The name of the connector. -API URL:: The AWS Bedrock request URL. -Default model:: The GAI model for AWS Bedrock to use. Current support is for the Anthropic Claude models, defaulting to Claude 2. The model can be set on a per request basis by including a "model" parameter alongside the request body. -Region:: The AWS Bedrock request URL. +API URL:: The {bedrock} request URL. +Default model:: The GAI model for {bedrock} to use. Current support is for the Anthropic Claude models, defaulting to Claude 2. The model can be set on a per request basis by including a "model" parameter alongside the request body. +Region:: The {bedrock} request URL. Access Key:: The AWS access key for authentication. Secret:: The secret for authentication. @@ -43,11 +43,11 @@ as you're creating or editing the connector in {kib}. For example: [role="screenshot"] // TODO: need logo before screenshot -image::management/connectors/images/bedrock-params.png[AWS Bedrock params test] +image::management/connectors/images/bedrock-params.png[{bedrock} params test] -The AWS Bedrock actions have the following configuration properties. +The {bedrock} actions have the following configuration properties. -Body:: A stringified JSON payload sent to the AWS Bedrock Invoke Model API URL. For example: +Body:: A stringified JSON payload sent to the {bedrock} Invoke Model API URL. For example: + [source,text] -- diff --git a/docs/management/connectors/pre-configured-connectors.asciidoc b/docs/management/connectors/pre-configured-connectors.asciidoc index 6e6694e8a839db..3b0a5e3004f83e 100644 --- a/docs/management/connectors/pre-configured-connectors.asciidoc +++ b/docs/management/connectors/pre-configured-connectors.asciidoc @@ -1,5 +1,9 @@ [[pre-configured-connectors]] == Preconfigured connectors +:frontmatter-description: Define connectors in the {kib} configuration file. +:frontmatter-tags-products: [kibana] +:frontmatter-tags-content-type: [how-to] +:frontmatter-tags-user-goals: [configure] If you are running {kib} on-prem, you can preconfigure a connector to have all the information it needs prior to startup by adding it to the `kibana.yml` file. @@ -20,6 +24,7 @@ predefined, including the connector name and ID. Add `xpack.actions.preconfigured` settings to your `kibana.yml` file. The settings vary depending on which type of connector you're adding. +Refer to <>. This example shows a valid configuration for a Slack connector and a Webhook connector: @@ -107,6 +112,7 @@ Index names must start with `kibana-alert-history-` to take advantage of the pre [[preconfigured-connector-examples]] === Examples +* <> * <> * <> * <> @@ -128,6 +134,30 @@ Index names must start with `kibana-alert-history-` to take advantage of the pre * <> * <> +[float] +[[preconfigured-bedrock-configuration]] +==== {bedrock} connectors + +The following example creates an <>: + +[source,text] +-- +xpack.actions.preconfigured: + my-bedrock: + name: preconfigured-bedrock-connector-type + actionTypeId: .bedrock + config: + apiUrl: https://bedrock.us-east-1.amazonaws.com <1> + defaultModel: anthropic.claude-v2 <2> + secrets: + accessKey: key-value <3> + secret: secret-value <4> +-- +<1> The {bedrock} request URL. +<2> The default model to use for requests. Current support is for the Anthropic Claude models, defaulting to Claude 2. +<3> The AWS access key for authentication. +<4> The AWS secret for authentication. + [float] [[preconfigured-d3security-configuration]] ==== D3 Security connectors @@ -302,7 +332,7 @@ xpack.actions.preconfigured: secrets: apiKey: superlongapikey <4> -- -<1> The OpenAI request URL +<1> The OpenAI request URL. <2> The OpenAI API provider, either `OpenAI` or `Azure OpenAI`. <3> The default model to use for requests. This setting is optional and applicable only when `apiProvider` is `OpenAI`. <4> The OpenAI or Azure OpenAI API key for authentication. diff --git a/docs/settings/alert-action-settings.asciidoc b/docs/settings/alert-action-settings.asciidoc index 4312d2825a9d49..5130fad9abad48 100644 --- a/docs/settings/alert-action-settings.asciidoc +++ b/docs/settings/alert-action-settings.asciidoc @@ -267,6 +267,7 @@ For a <>, specifies the OpenAI API provider A configuration URL that varies by connector: + -- +* For an <>, specifies the {bedrock} request URL. * For a <>, specifies the OpenAI request URL. * For a <>, specifies the {ibm-r} instance URL. * For a <>, specifies the Jira instance URL. @@ -327,7 +328,12 @@ NOTE: If you are using the `xpack.actions.allowedHosts` setting, make sure the h For a <>, specifies a string from the response body of the create case method that corresponds to the external service identifier. `xpack.actions.preconfigured..config.defaultModel`:: -For a <>, specifies the default model to use for requests. It is optional and applicable only when `xpack.actions.preconfigured..config.apiProvider` is `OpenAI`. +The default model to use for requests, which varies by connector: ++ +-- +* For an <>, current support is for the Anthropic Claude models. Defaults to `anthropic.claude-v2`. +* For a <>, it is optional and applicable only when `xpack.actions.preconfigured..config.apiProvider` is `OpenAI`. +-- `xpack.actions.preconfigured..config.executionTimeField`:: For an <>, a field that indicates when the document was indexed. @@ -463,6 +469,9 @@ Sensitive configuration details, such as username, password, and keys, which are + TIP: Sensitive properties, such as passwords, should be stored in the <>. +`xpack.actions.preconfigured..secrets.accessKey`:: +For an <>, specifies the AWS access key for authentication. + `xpack.actions.preconfigured..secrets.apikey`:: An API key secret that varies by connector: + @@ -517,6 +526,9 @@ For a <>, <.secrets.routingKey`:: For a <>, specifies the 32 character PagerDuty Integration Key for an integration on a service, also referred to as the routing key. +`xpack.actions.preconfigured..secrets.secret`:: +For an <>, specifies the AWS secret for authentication. + `xpack.actions.preconfigured..secrets.secretsUrl`:: For an <> with URL authentication, specifies the request URL for the Elastic Alerts trigger in xMatters with the API key included in the URL. It is used only when `xpack.actions.preconfigured..config.usesBasic` is `false`. From b2e3ce3ec58f53a0e5fe273f3960df483f3feac6 Mon Sep 17 00:00:00 2001 From: Tomasz Ciecierski Date: Mon, 16 Oct 2023 17:34:51 +0200 Subject: [PATCH 02/87] [EDR Workflows] Skip flaky osquery test (#168961) --- .../all/alerts_response_actions_form.cy.ts | 314 +++++++++--------- 1 file changed, 159 insertions(+), 155 deletions(-) diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts index 4a49d85d0ffa94..6b8f314ba8d589 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts @@ -41,172 +41,176 @@ interface ITestRuleBody { } ]; } +// flaky +describe.skip( + 'Alert Event Details - Response Actions Form', + { tags: ['@ess', '@serverless'] }, + () => { + let multiQueryPackId: string; + let multiQueryPackName: string; + let ruleId: string; + let ruleName: string; + let packId: string; + let packName: string; + const packData = packFixture(); + const multiQueryPackData = multiQueryPackFixture(); -describe('Alert Event Details - Response Actions Form', { tags: ['@ess', '@serverless'] }, () => { - let multiQueryPackId: string; - let multiQueryPackName: string; - let ruleId: string; - let ruleName: string; - let packId: string; - let packName: string; - const packData = packFixture(); - const multiQueryPackData = multiQueryPackFixture(); - - beforeEach(() => { - loadPack(packData).then((data) => { - packId = data.saved_object_id; - packName = data.name; - }); - loadPack(multiQueryPackData).then((data) => { - multiQueryPackId = data.saved_object_id; - multiQueryPackName = data.name; + beforeEach(() => { + loadPack(packData).then((data) => { + packId = data.saved_object_id; + packName = data.name; + }); + loadPack(multiQueryPackData).then((data) => { + multiQueryPackId = data.saved_object_id; + multiQueryPackName = data.name; + }); + loadRule().then((data) => { + ruleId = data.id; + ruleName = data.name; + }); }); - loadRule().then((data) => { - ruleId = data.id; - ruleName = data.name; + afterEach(() => { + cleanupPack(packId); + cleanupPack(multiQueryPackId); + cleanupRule(ruleId); }); - }); - afterEach(() => { - cleanupPack(packId); - cleanupPack(multiQueryPackId); - cleanupRule(ruleId); - }); - it('adds response actions with osquery with proper validation and form values', () => { - cy.visit('/app/security/rules'); - clickRuleName(ruleName); - cy.getBySel('editRuleSettingsLink').click(); - cy.getBySel('globalLoadingIndicator').should('not.exist'); - closeDateTabIfVisible(); - cy.getBySel('edit-rule-actions-tab').click(); - cy.contains('Response actions are run on each rule execution.'); - cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click(); - cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { - cy.contains('Query is a required field'); - inputQuery('select * from uptime1'); - }); - cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click(); - cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { - cy.contains('Run a set of queries in a pack').click(); - }); - cy.getBySel('response-actions-error') - .within(() => { + it('adds response actions with osquery with proper validation and form values', () => { + cy.visit('/app/security/rules'); + clickRuleName(ruleName); + cy.getBySel('editRuleSettingsLink').click(); + cy.getBySel('globalLoadingIndicator').should('not.exist'); + closeDateTabIfVisible(); + cy.getBySel('edit-rule-actions-tab').click(); + cy.contains('Response actions are run on each rule execution.'); + cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click(); + cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { + cy.contains('Query is a required field'); + inputQuery('select * from uptime1'); + }); + cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click(); + cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { + cy.contains('Run a set of queries in a pack').click(); + }); + cy.getBySel('response-actions-error') + .within(() => { + cy.contains('Pack is a required field'); + }) + .should('exist'); + cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { cy.contains('Pack is a required field'); - }) - .should('exist'); - cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { - cy.contains('Pack is a required field'); - cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`); - }); + cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`); + }); - cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click(); + cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click(); - cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => { - cy.contains('Query is a required field'); - inputQuery('select * from uptime'); - cy.contains('Advanced').click(); - typeInECSFieldInput('message{downArrow}{enter}'); - cy.getBySel('osqueryColumnValueSelect').type('days{downArrow}{enter}'); - cy.wait(1000); // wait for the validation to trigger - cypress is way faster than users ;) - }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => { + cy.contains('Query is a required field'); + inputQuery('select * from uptime'); + cy.contains('Advanced').click(); + typeInECSFieldInput('message{downArrow}{enter}'); + cy.getBySel('osqueryColumnValueSelect').type('days{downArrow}{enter}'); + cy.wait(1000); // wait for the validation to trigger - cypress is way faster than users ;) + }); - cy.getBySel('ruleEditSubmitButton').click(); - cy.contains(`${ruleName} was saved`).should('exist'); - closeToastIfVisible(); + cy.getBySel('ruleEditSubmitButton').click(); + cy.contains(`${ruleName} was saved`).should('exist'); + closeToastIfVisible(); - cy.getBySel('editRuleSettingsLink').click(); - cy.getBySel('globalLoadingIndicator').should('not.exist'); - cy.getBySel('edit-rule-actions-tab').click(); - cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { - cy.contains('select * from uptime1'); - }); - cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => { - cy.contains('select * from uptime'); - cy.contains('Log message optimized for viewing in a log viewer'); - cy.contains('Days of uptime'); - }); - cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { - cy.contains(packName); - cy.getBySel('comboBoxInput').type('{backspace}{enter}'); - }); - cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { - cy.contains('select * from uptime1'); - cy.getBySel('remove-response-action').click(); - }); - cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { - cy.contains('Search for a pack to run'); - cy.contains('Pack is a required field'); - cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`); - }); - cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { - cy.contains('select * from uptime'); - cy.contains('Log message optimized for viewing in a log viewer'); - cy.contains('Days of uptime'); - }); - cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleChangesOne'); - cy.getBySel('ruleEditSubmitButton').click(); + cy.getBySel('editRuleSettingsLink').click(); + cy.getBySel('globalLoadingIndicator').should('not.exist'); + cy.getBySel('edit-rule-actions-tab').click(); + cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { + cy.contains('select * from uptime1'); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => { + cy.contains('select * from uptime'); + cy.contains('Log message optimized for viewing in a log viewer'); + cy.contains('Days of uptime'); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { + cy.contains(packName); + cy.getBySel('comboBoxInput').type('{backspace}{enter}'); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { + cy.contains('select * from uptime1'); + cy.getBySel('remove-response-action').click(); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { + cy.contains('Search for a pack to run'); + cy.contains('Pack is a required field'); + cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { + cy.contains('select * from uptime'); + cy.contains('Log message optimized for viewing in a log viewer'); + cy.contains('Days of uptime'); + }); + cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleChangesOne'); + cy.getBySel('ruleEditSubmitButton').click(); - cy.wait('@saveRuleChangesOne'); - cy.get<{ request: { url: string; body: ITestRuleBody } }>('@saveRuleChangesOne').should( - ({ request }) => { - const oneQuery = [ - { - interval: 3600, - query: 'select * from uptime;', - id: Object.keys(packData.queries)[0], - }, - ]; - expect(request.body.response_actions[0].params.queries).to.deep.equal(oneQuery); - } - ); + cy.wait('@saveRuleChangesOne'); + cy.get<{ request: { url: string; body: ITestRuleBody } }>('@saveRuleChangesOne').should( + ({ request }) => { + const oneQuery = [ + { + interval: 3600, + query: 'select * from uptime;', + id: Object.keys(packData.queries)[0], + }, + ]; + expect(request.body.response_actions[0].params.queries).to.deep.equal(oneQuery); + } + ); - cy.contains(`${ruleName} was saved`).should('exist'); - closeToastIfVisible(); + cy.contains(`${ruleName} was saved`).should('exist'); + closeToastIfVisible(); - cy.getBySel('editRuleSettingsLink').click(); - cy.getBySel('globalLoadingIndicator').should('not.exist'); - cy.getBySel('edit-rule-actions-tab').click(); - cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { - cy.contains(packName); - cy.getBySel('comboBoxInput').type(`${multiQueryPackName}{downArrow}{enter}`); - checkActionItemsInResults({ - cases: false, - lens: false, - discover: false, - timeline: false, + cy.getBySel('editRuleSettingsLink').click(); + cy.getBySel('globalLoadingIndicator').should('not.exist'); + cy.getBySel('edit-rule-actions-tab').click(); + cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { + cy.contains(packName); + cy.getBySel('comboBoxInput').type(`${multiQueryPackName}{downArrow}{enter}`); + checkActionItemsInResults({ + cases: false, + lens: false, + discover: false, + timeline: false, + }); }); - }); - cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { - cy.contains('select * from uptime'); - cy.contains('Log message optimized for viewing in a log viewer'); - cy.contains('Days of uptime'); - }); - cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleChangesTwo'); + cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { + cy.contains('select * from uptime'); + cy.contains('Log message optimized for viewing in a log viewer'); + cy.contains('Days of uptime'); + }); + cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleChangesTwo'); - cy.contains('Save changes').click(); - cy.wait('@saveRuleChangesTwo'); - cy.get<{ request: { url: string; body: ITestRuleBody } }>('@saveRuleChangesTwo').should( - ({ request }) => { - const threeQueries = [ - { - interval: 3600, - query: 'SELECT * FROM memory_info;', - platform: 'linux', - id: Object.keys(multiQueryPackData.queries)[0], - }, - { - interval: 3600, - query: 'SELECT * FROM system_info;', - id: Object.keys(multiQueryPackData.queries)[1], - }, - { - interval: 10, - query: 'select opera_extensions.* from users join opera_extensions using (uid);', - id: Object.keys(multiQueryPackData.queries)[2], - }, - ]; - expect(request.body.response_actions[0].params.queries).to.deep.equal(threeQueries); - } - ); - }); -}); + cy.contains('Save changes').click(); + cy.wait('@saveRuleChangesTwo'); + cy.get<{ request: { url: string; body: ITestRuleBody } }>('@saveRuleChangesTwo').should( + ({ request }) => { + const threeQueries = [ + { + interval: 3600, + query: 'SELECT * FROM memory_info;', + platform: 'linux', + id: Object.keys(multiQueryPackData.queries)[0], + }, + { + interval: 3600, + query: 'SELECT * FROM system_info;', + id: Object.keys(multiQueryPackData.queries)[1], + }, + { + interval: 10, + query: 'select opera_extensions.* from users join opera_extensions using (uid);', + id: Object.keys(multiQueryPackData.queries)[2], + }, + ]; + expect(request.body.response_actions[0].params.queries).to.deep.equal(threeQueries); + } + ); + }); + } +); From e6a389f4c3040b67438ce655825ba0a5e8bab560 Mon Sep 17 00:00:00 2001 From: Jason Rhodes Date: Mon, 16 Oct 2023 11:47:13 -0400 Subject: [PATCH 03/87] Introducing "tiered dependencies" in observability plugins (#166524) Note: please see this last comment in the PR for important context: https://github.com/elastic/kibana/pull/166524#issuecomment-1764774318 This document explains the convention of "tiered dependencies" so we can begin to enforce it in code reviews by referencing a single document. Please take a look [at the Markdown document being introduced in this PR](https://github.com/elastic/kibana/blob/1c09d5039e4b542946ad6497c69f7a4a3b8c0952/x-pack/plugins/observability_shared/dev_docs/tiered-dependencies.md) and put any questions or concerns in the comments of the PR. ## Open Questions * **Why is this important?** I've seen new plugin-to-plugin dependencies being added casually in PRs recently, which will make this problem harder and harder to solve, the further we double down on it. It's happening because we're all sharing things more, which is great! Let's make sure sharing doesn't create more feature blockages, and enable as much safe, hassle-free sharing between our teams as possible! * **How will we enforce this?** To start with, it will be a manual convention enforced by code review. This is better than what we have today, and a document like this allows us to explain the reasoning in a code review without having to discuss everything from the start each time. However, if we find this system works, we should look into how to codify and enforce it via linting, build, etc. * **What if we need more than 3 tiers?** I don't want to get too bogged down in this question, but it's fair. I contemplated numbering the tiers "10", "20", "30" to allow for space in between, but I don't think it's necessary. If we need more tiers, we'll adjust the guidance. For now, this should be plenty to get us started. * **What other information does this documentation need?** Perhaps a "where should my shared code go?" flow chart type section, to clarify as much as possible where newly shared/extracted code should go? --- .../dev_docs/how-we-manage-dependencies.md | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 x-pack/plugins/observability_shared/dev_docs/how-we-manage-dependencies.md diff --git a/x-pack/plugins/observability_shared/dev_docs/how-we-manage-dependencies.md b/x-pack/plugins/observability_shared/dev_docs/how-we-manage-dependencies.md new file mode 100644 index 00000000000000..5cd525e97954f9 --- /dev/null +++ b/x-pack/plugins/observability_shared/dev_docs/how-we-manage-dependencies.md @@ -0,0 +1,70 @@ +# Dependency Management in Observability Kibana + +Our goal in observability is to provide as seamless of an experience as possible for our observability users, especially when it comes to navigating between areas owned by different teams. In Kibana, these different teams each own their own experiences inside of a Kibana plugin that provides a public UI interface and, optionally, a back-end server interface. As these plugins begin to share more components, utilities, data clients, and more, the Kibana architecture requires them to depend on each other using runtime dependencies. These dependencies can only be single-direction, which severely limits the types of sharing our plugins can do with one another. + +## Problem summary + +For years, the APM plugin has declared a single-direction runtime dependency on the Infra plugin, allowing APM to make use of components and utilities made available by Infra. Because of this existing dependency, the infra plugin can never make use of similar shared items that could be made available from APM. As Logs+ grows and evolves, Synthetics and Profiling both continue to grow beyond GA, and Elastic begins to fully embrace a unified Observability user experience, we expect this problem to multiply quickly. + +To solve this problem, we need a clear approach for how to organize plugins, packages, and the dependencies between them. + +## Plan summary + +This is the plan we aim to follow, summarized. More details about this plan are found below. + +1. **Resist over-abstraction, but abstract when needed.** If something doesn't need to be shared yet, it's not necessarily good to break it out into its own plugin _or_ package. That said, we will need to break items out of our end user plugins and/or rearrange them, and we shouldn't be scared of doing this because of longtime technical limitations. + - TODO: Add information about possible Kibana event system to consider as a first sharing step, prior to abstraction. +1. **Prefer packages to plugins.** A stateless package is easier to bootstrap, test, and maintain in most cases. If you don't need access to stateful dependencies from core or other plugins, or if you can accept a reasonable number of injected dependencies, make a package. + - TODO: Add link to docs/examples of how to make a Kibana package + - TODO: Add more clarity on the trade-offs between plugin vs package +1. **If you need to make a new plugin, be sure to carefully consider the plugin tiers and how your new plugin will fit.**. In most cases, we should avoid new plugins (with the exception of data access plugins which should only depend on Kibana core.) +1. **Never introduce or add to existing dependencies between plugins in the same tier.** This is the main problem we need to avoid, especially between end user plugins. + +## Plugin tier system + +The system we'll embrace revolves around a "tier system" to help us organize different types of plugins. The plugin tiers look like this: + +Screenshot 2023-09-14 at 3 27 56 PM + +Within this system, a plugin in any tier may ONLY introduce dependencies on other plugins that are in a tier below theirs. They may NOT depend on plugins in the same tier or in tiers above their own. Packages, on the other hand, may be depended on from _any_ plugin, as well as from _any other_ package. + +**Note:** Tiers are NOT currently enforced by any lint rule or other rule. Tiers are a convention that allow us to structure our code in such a way as to avoid the circular dependency problem, but they require manual enforcement via code review. In the near future, we should explore simple ways to codify and enforce this system, either in linting rules, Kibana bundling enforcement, precommit hooks, etc. + +### Tier 1: End user tier + +End user plugins are the plugins that provide visible sections of the Observability UI in Kibana. Each of these plugins may provide one or more navigational areas inside of the Observability product, and they each may provide one or more Kibana server APIs as well. + +These plugins should stop introducing dependencies on each other immediately, and should also stop introducing new functionality that relies on existing dependencies immediately, as well. As soon as possible, existing dependencies between these plugins should be removed and replaced with extracted functionality. + +Screenshot 2023-09-14 at 3 32 17 PM + +### Tier 2: Share tier + +"Share plugins" provide shared functionality (UI components, utility functions, shared logic, etc.) that can be used by multiple end user plugins. Being plugins, they still take advantage of the Kibana runtime lifecycle (setup, start, stop) and have access to Kibana's core functionality and core plugin system. + +This tier is where we would move any shared items, business logic, and stateful dependencies that need access to the plugin lifecycle and, for whatever reason, can't or don't want to accept runtime dependencies as injected parameters. These share plugins can make use of the core-only plugins that typically provide encapsulated access to observability data of other kinds. + +Screenshot 2023-09-14 at 3 32 25 PM + +### Tier 3: Core-only tier (aka data access tier) + +This tier is for plugins that ONLY depend on Kibana core functionality such as scoped ES clients, saved object clients, etc. The main examples of these for now are the new "data access client" plugins which encapsulate the logic for accessing our various types of signal data in observability. By keeping this tier isolated from the other code and only allowing for it to depend on Kibana core, we make data access safely available to any other plugin in the end user or share tiers. + +Screenshot 2023-09-14 at 3 32 30 PM + +### Core: Kibana core + +Anything made available by Kibana core, either in the CoreSetup, CoreStart, or one of the core-maintained plugins such as saved objects, etc. is fair game as a dependency of any observability plugin in any tier. + +### Packages + +Kibana packages are stateless and therefore can be imported into any plugin in any tier. If your shareable item is stateless, or if it can be simply built to accept strongly-typed items using dependency injection, using a package is almost always the best choice. + +## Putting it all together + +Screenshot 2023-09-14 at 3 37 35 PM + +With the exception of package dependencies, all plugin-to-plugin dependencies may only flow _downward_ in the tier diagram. + +Screenshot 2023-09-14 at 3 37 42 PM + From d1299c341d4954c296f7e692b5028833626375b1 Mon Sep 17 00:00:00 2001 From: Matthew Kime Date: Mon, 16 Oct 2023 10:48:36 -0500 Subject: [PATCH 04/87] Revert "[data views] Allow data views created on hidden and system indices" (#168855) Reverts elastic/kibana#168174 Reverting the previous PR - tests passed and the PR appeared to work because ES is doesn't always enforce 'allowHidden' on hidden indices. --- .../data_view_editor_flyout_content.tsx | 1 - .../__snapshots__/data_views.test.ts.snap | 1 - .../data_views/common/data_views/data_view.ts | 5 ---- .../common/data_views/data_views.ts | 4 --- src/plugins/data_views/common/types.ts | 9 ------ .../server/fetcher/index_patterns_fetcher.ts | 14 +--------- .../data_views/server/fetcher/lib/es_api.ts | 2 -- .../field_capabilities.test.js | 1 - .../field_capabilities/field_capabilities.ts | 4 --- .../rest_api_routes/internal/fields_for.ts | 4 --- .../data_views/_data_view_create_delete.ts | 28 ------------------- test/functional/page_objects/settings_page.ts | 13 +-------- .../log_views/log_views_client.test.ts | 2 -- 13 files changed, 2 insertions(+), 86 deletions(-) diff --git a/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx b/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx index c889f2e0dcd063..ad344d482c0cf4 100644 --- a/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx +++ b/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx @@ -124,7 +124,6 @@ const IndexPatternEditorFlyoutContentComponent = ({ timeFieldName: formData.timestampField?.value, id: formData.id, name: formData.name, - allowHidden: formData.allowHidden, }; if (type === INDEX_PATTERN_TYPE.ROLLUP && rollupIndex) { diff --git a/src/plugins/data_views/common/data_views/__snapshots__/data_views.test.ts.snap b/src/plugins/data_views/common/data_views/__snapshots__/data_views.test.ts.snap index 53b77e28a416c3..0d646f4afc28d1 100644 --- a/src/plugins/data_views/common/data_views/__snapshots__/data_views.test.ts.snap +++ b/src/plugins/data_views/common/data_views/__snapshots__/data_views.test.ts.snap @@ -28,7 +28,6 @@ exports[`IndexPatterns delete will throw if insufficient access 1`] = `[DataView exports[`IndexPatterns savedObjectToSpec 1`] = ` Object { - "allowHidden": undefined, "allowNoIndex": undefined, "fieldAttrs": Object { "aRuntimeField": Object { diff --git a/src/plugins/data_views/common/data_views/data_view.ts b/src/plugins/data_views/common/data_views/data_view.ts index 3cea4505b572c3..ffda65af2a8950 100644 --- a/src/plugins/data_views/common/data_views/data_view.ts +++ b/src/plugins/data_views/common/data_views/data_view.ts @@ -152,8 +152,6 @@ export class DataView implements DataViewBase { */ public matchedIndices: string[] = []; - private allowHidden: boolean = false; - /** * constructor * @param config - config data and dependencies @@ -189,7 +187,6 @@ export class DataView implements DataViewBase { this.runtimeFieldMap = cloneDeep(spec.runtimeFieldMap) || {}; this.namespaces = spec.namespaces || []; this.name = spec.name || ''; - this.allowHidden = spec.allowHidden || false; } /** @@ -204,8 +201,6 @@ export class DataView implements DataViewBase { getIndexPattern = () => this.title; - getAllowHidden = () => this.allowHidden; - /** * Set index pattern * @param string index pattern string diff --git a/src/plugins/data_views/common/data_views/data_views.ts b/src/plugins/data_views/common/data_views/data_views.ts index d5509f03db580f..8bac81f19ef628 100644 --- a/src/plugins/data_views/common/data_views/data_views.ts +++ b/src/plugins/data_views/common/data_views/data_views.ts @@ -584,7 +584,6 @@ export class DataViewsService { allowNoIndex: true, pattern: dataView.getIndexPattern(), metaFields, - allowHidden: dataView.getAllowHidden(), }); }; @@ -597,7 +596,6 @@ export class DataViewsService { rollupIndex: options.rollupIndex, allowNoIndex: true, indexFilter: options.indexFilter, - allowHidden: options.allowHidden, }); }; @@ -749,7 +747,6 @@ export class DataViewsService { fieldAttrs, allowNoIndex, name, - allowHidden, }, } = savedObject; @@ -777,7 +774,6 @@ export class DataViewsService { allowNoIndex, runtimeFieldMap: parsedRuntimeFieldMap, name, - allowHidden, }; }; diff --git a/src/plugins/data_views/common/types.ts b/src/plugins/data_views/common/types.ts index 522bec8873534e..9061c4643dce9d 100644 --- a/src/plugins/data_views/common/types.ts +++ b/src/plugins/data_views/common/types.ts @@ -157,10 +157,6 @@ export interface DataViewAttributes { * Name of the data view. Human readable name used to differentiate data view. */ name?: string; - /** - * Allow hidden and system indices when loading field list - */ - allowHidden?: boolean; } /** @@ -313,7 +309,6 @@ export interface GetFieldsOptions { indexFilter?: QueryDslQueryContainer; includeUnmapped?: boolean; fields?: string[]; - allowHidden?: boolean; } /** @@ -517,10 +512,6 @@ export type DataViewSpec = { * Name of the data view. Human readable name used to differentiate data view. */ name?: string; - /** - * Whether the data view is hidden from the user - */ - allowHidden?: boolean; }; // eslint-disable-next-line @typescript-eslint/consistent-type-definitions diff --git a/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts index f23933bc5775ee..b1d22dc5523c8d 100644 --- a/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts +++ b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts @@ -69,23 +69,12 @@ export class IndexPatternsFetcher { rollupIndex?: string; indexFilter?: QueryDslQueryContainer; fields?: string[]; - allowHidden?: boolean; }): Promise<{ fields: FieldDescriptor[]; indices: string[] }> { - const { - pattern, - metaFields = [], - fieldCapsOptions, - type, - rollupIndex, - indexFilter, - allowHidden, - } = options; + const { pattern, metaFields = [], fieldCapsOptions, type, rollupIndex, indexFilter } = options; const allowNoIndices = fieldCapsOptions ? fieldCapsOptions.allow_no_indices : this.allowNoIndices; - const expandWildcards = allowHidden ? 'all' : 'open'; - const fieldCapsResponse = await getFieldCapabilities({ callCluster: this.elasticsearchClient, indices: pattern, @@ -96,7 +85,6 @@ export class IndexPatternsFetcher { }, indexFilter, fields: options.fields || ['*'], - expandWildcards, }); if (this.rollupsEnabled && type === 'rollup' && rollupIndex) { diff --git a/src/plugins/data_views/server/fetcher/lib/es_api.ts b/src/plugins/data_views/server/fetcher/lib/es_api.ts index 2128e52da537ba..988e4a4ec28c8a 100644 --- a/src/plugins/data_views/server/fetcher/lib/es_api.ts +++ b/src/plugins/data_views/server/fetcher/lib/es_api.ts @@ -7,7 +7,6 @@ */ import { ElasticsearchClient } from '@kbn/core/server'; -import { ExpandWildcard } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { QueryDslQueryContainer } from '../../../common/types'; import { convertEsError } from './errors'; @@ -46,7 +45,6 @@ interface FieldCapsApiParams { fieldCapsOptions?: { allow_no_indices: boolean; include_unmapped?: boolean }; indexFilter?: QueryDslQueryContainer; fields?: string[]; - expandWildcard?: ExpandWildcard; } /** diff --git a/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.test.js b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.test.js index f41c71498e81e9..1b3be374bbd7c2 100644 --- a/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.test.js +++ b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.test.js @@ -34,7 +34,6 @@ describe('index_patterns/field_capabilities/field_capabilities', () => { const fillUndefinedParams = (args) => ({ callCluster: undefined, indices: undefined, - expandWildcard: undefined, fieldCapsOptions: undefined, indexFilter: undefined, fields: undefined, diff --git a/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.ts b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.ts index 6bef117151609b..73e550ebd68cee 100644 --- a/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.ts +++ b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_capabilities.ts @@ -9,7 +9,6 @@ import { defaults, keyBy, sortBy } from 'lodash'; import { ElasticsearchClient } from '@kbn/core/server'; -import { ExpandWildcard } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { callFieldCapsApi } from '../es_api'; import { readFieldCapsResponse } from './field_caps_response'; import { mergeOverrides } from './overrides'; @@ -23,7 +22,6 @@ interface FieldCapabilitiesParams { fieldCapsOptions?: { allow_no_indices: boolean; include_unmapped?: boolean }; indexFilter?: QueryDslQueryContainer; fields?: string[]; - expandWildcards?: ExpandWildcard; } /** @@ -44,7 +42,6 @@ export async function getFieldCapabilities(params: FieldCapabilitiesParams) { indexFilter, metaFields = [], fields, - expandWildcards, } = params; const esFieldCaps = await callFieldCapsApi({ callCluster, @@ -52,7 +49,6 @@ export async function getFieldCapabilities(params: FieldCapabilitiesParams) { fieldCapsOptions, indexFilter, fields, - expandWildcard: expandWildcards, }); const fieldCapsArr = readFieldCapsResponse(esFieldCaps.body); const fieldsFromFieldCapsByName = keyBy(fieldCapsArr, 'name'); diff --git a/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts b/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts index 7d39b41d5caee9..15d761935c0a73 100644 --- a/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts +++ b/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts @@ -50,7 +50,6 @@ interface IQuery { allow_no_index?: boolean; include_unmapped?: boolean; fields?: string[]; - allow_hidden?: boolean; } const querySchema = schema.object({ @@ -63,7 +62,6 @@ const querySchema = schema.object({ allow_no_index: schema.maybe(schema.boolean()), include_unmapped: schema.maybe(schema.boolean()), fields: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), - allow_hidden: schema.maybe(schema.boolean()), }); const fieldSubTypeSchema = schema.object({ @@ -124,7 +122,6 @@ const handler: (isRollupsEnabled: () => boolean) => RequestHandler<{}, IQuery, I rollup_index: rollupIndex, allow_no_index: allowNoIndex, include_unmapped: includeUnmapped, - allow_hidden: allowHidden, } = request.query; // not available to get request @@ -150,7 +147,6 @@ const handler: (isRollupsEnabled: () => boolean) => RequestHandler<{}, IQuery, I includeUnmapped, }, indexFilter, - allowHidden, ...(parsedFields.length > 0 ? { fields: parsedFields } : {}), }); diff --git a/test/functional/apps/management/data_views/_data_view_create_delete.ts b/test/functional/apps/management/data_views/_data_view_create_delete.ts index e55afd799a9b8a..edf2f000fcb273 100644 --- a/test/functional/apps/management/data_views/_data_view_create_delete.ts +++ b/test/functional/apps/management/data_views/_data_view_create_delete.ts @@ -17,7 +17,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const testSubjects = getService('testSubjects'); const find = getService('find'); - const es = getService('es'); const PageObjects = getPageObjects(['settings', 'common', 'header']); describe('creating and deleting default data view', function describeIndexTests() { @@ -251,32 +250,5 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); }); - - describe('hidden index support', () => { - it('can create data view against hidden index', async () => { - const pattern = 'logstash-2015.09.21'; - - await es.transport.request({ - path: '/logstash-2015.09.21/_settings', - method: 'PUT', - body: { - index: { - hidden: true, - }, - }, - }); - - await PageObjects.settings.createIndexPattern( - pattern, - undefined, - undefined, - undefined, - undefined, - true - ); - const patternName = await PageObjects.settings.getIndexPageHeading(); - expect(patternName).to.be(pattern); - }); - }); }); } diff --git a/test/functional/page_objects/settings_page.ts b/test/functional/page_objects/settings_page.ts index 568c45beb0dfbc..d2fba8e6201537 100644 --- a/test/functional/page_objects/settings_page.ts +++ b/test/functional/page_objects/settings_page.ts @@ -470,19 +470,13 @@ export class SettingsPageObject extends FtrService { await customDataViewIdInput.type(value); } - async allowHiddenClick() { - await this.testSubjects.click('toggleAdvancedSetting'); - await this.testSubjects.click('allowHiddenField'); - } - async createIndexPattern( indexPatternName: string, // null to bypass default value timefield: string | null = '@timestamp', isStandardIndexPattern = true, customDataViewId?: string, - dataViewName?: string, - allowHidden?: boolean + dataViewName?: string ) { await this.retry.try(async () => { await this.header.waitUntilLoadingHasFinished(); @@ -495,11 +489,6 @@ export class SettingsPageObject extends FtrService { } else { await this.clickAddNewIndexPatternButton(); } - - if (allowHidden) { - await this.allowHiddenClick(); - } - await this.header.waitUntilLoadingHasFinished(); if (!isStandardIndexPattern) { await this.selectRollupIndexPatternType(); diff --git a/x-pack/plugins/logs_shared/server/services/log_views/log_views_client.test.ts b/x-pack/plugins/logs_shared/server/services/log_views/log_views_client.test.ts index b9f5037ced6b11..5efdf9e125deb0 100644 --- a/x-pack/plugins/logs_shared/server/services/log_views/log_views_client.test.ts +++ b/x-pack/plugins/logs_shared/server/services/log_views/log_views_client.test.ts @@ -249,7 +249,6 @@ describe('LogViewsClient class', () => { }, ], "dataViewReference": DataView { - "allowHidden": false, "allowNoIndex": false, "deleteFieldFormat": [Function], "fieldAttrs": Object {}, @@ -274,7 +273,6 @@ describe('LogViewsClient class', () => { }, "fields": FldList [], "flattenHit": [Function], - "getAllowHidden": [Function], "getFieldAttrs": [Function], "getIndexPattern": [Function], "getName": [Function], From cb3ed24993f3df4eaafea7f44ab57012638170d4 Mon Sep 17 00:00:00 2001 From: Abdul Wahab Zahid Date: Mon, 16 Oct 2023 18:12:10 +0200 Subject: [PATCH 05/87] [Synthetics] Fix Monitor Status chart tooltip hover. (#168714) Fixes #168711 ## Summary The PR fixes the issue with Monitor Status chart tooltip. New implementation in EUI doesn't render the tooltip in parent Context's scope, which was causing the redux selector to break. This PR moves the selector call up one level, into the parent scope. --- .../monitor_status/monitor_status_cell_tooltip.tsx | 11 +++++++---- .../monitor_status/monitor_status_panel.tsx | 8 +++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/monitor_status_cell_tooltip.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/monitor_status_cell_tooltip.tsx index a6dc7956280cef..a8d027889dbb00 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/monitor_status_cell_tooltip.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/monitor_status_cell_tooltip.tsx @@ -11,13 +11,16 @@ import { EuiProgress } from '@elastic/eui'; import { TooltipTable, TooltipHeader, TooltipValue, TooltipContainer } from '@elastic/charts'; -import { usePingStatusesIsLoading } from '../hooks/use_ping_statuses'; import { MonitorStatusTimeBin, SUCCESS_VIZ_COLOR, DANGER_VIZ_COLOR } from './monitor_status_data'; import * as labels from './labels'; -export const MonitorStatusCellTooltip = ({ timeBin }: { timeBin?: MonitorStatusTimeBin }) => { - const isLoading = usePingStatusesIsLoading(); - +export const MonitorStatusCellTooltip = ({ + timeBin, + isLoading, +}: { + timeBin?: MonitorStatusTimeBin; + isLoading: boolean; +}) => { if (!timeBin) { return <>{''}; } diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/monitor_status_panel.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/monitor_status_panel.tsx index 4f67b8621104ce..cbbdae88c02750 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/monitor_status_panel.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_status/monitor_status_panel.tsx @@ -10,6 +10,8 @@ import React, { useMemo } from 'react'; import { EuiPanel, useEuiTheme, EuiResizeObserver, EuiSpacer } from '@elastic/eui'; import { Chart, Settings, Heatmap, ScaleType, Tooltip } from '@elastic/charts'; +import { usePingStatusesIsLoading } from '../hooks/use_ping_statuses'; + import { MonitorStatusHeader } from './monitor_status_header'; import { MonitorStatusCellTooltip } from './monitor_status_cell_tooltip'; import { MonitorStatusLegend } from './monitor_status_legend'; @@ -33,6 +35,7 @@ export const MonitorStatusPanel = ({ const { euiTheme, colorMode } = useEuiTheme(); const { timeBins, handleResize, getTimeBinByXValue, xDomain, intervalByWidth } = useMonitorStatusData({ from, to }); + const isPingStatusesLoading = usePingStatusesIsLoading(); const heatmap = useMemo(() => { return getMonitorStatusChartTheme(euiTheme, brushable); @@ -61,7 +64,10 @@ export const MonitorStatusPanel = ({ > ( - + )} /> Date: Mon, 16 Oct 2023 12:18:19 -0400 Subject: [PATCH 06/87] Fixes conflict checks for sharing saved objects (#168655) Closes #168049 ## Summary This PR adjusts the KQL filters when collecting references to saved objects for the purpose of updating their spaces (i.e. sharing saved objects to spaces). An additional filter is added to specifically exclude ID -> ID matches - an ID match would mean the object has already been shared to the destination space and there is no conflict. Filters to match the shared object's ID or origin ID to the destination space's objects' origin ID, and to match the shared object's origin ID to the destination space's objects' IDs remain in place to properly check for conflicts with potential copies. ### Manual Testing - Create 2 spaces: A and B - Add a sample data set (e.g. flight) to space A - In Discover, create a saved query called "s1" with a filter pill that uses the sample data logs data view - Create another saved query called "s2" with a filter pill that uses the sample data logs data view - Go to `Stack Management->Saved` Objects and share the "s1" query to space B - Now share the "s2" query to space B. From the main branch you will see that there is a conflict that disallows sharing the second query. This is because it is also attempting to share the referenced data view, which is already in space B. However, this should not be a conflict - from this PR you will be able to successfully share both queries. ### Automated Testing - packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/find_shared_origin_objects.test.ts - packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/collect_multi_namespace_references.test.ts - x-pack/test/spaces_api_integration/common/suites/get_shareable_references.ts --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- ...collect_multi_namespace_references.test.ts | 33 ++- .../collect_multi_namespace_references.ts | 6 +- .../utils/find_shared_origin_objects.test.ts | 224 +++++++++++++++++- .../apis/utils/find_shared_origin_objects.ts | 67 +++++- .../apis/collect_multinamespace_references.ts | 9 +- .../src/apis/index.ts | 1 + .../common/suites/get_shareable_references.ts | 16 +- 7 files changed, 325 insertions(+), 31 deletions(-) diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/collect_multi_namespace_references.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/collect_multi_namespace_references.test.ts index 5450f0c739ce3c..a82c18d42876bd 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/collect_multi_namespace_references.test.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/collect_multi_namespace_references.test.ts @@ -411,11 +411,12 @@ describe('collectMultiNamespaceReferences', () => { expect(mockFindSharedOriginObjects).toHaveBeenCalledWith( expect.anything(), [ - { type: obj1.type, origin: obj1.id }, - { type: obj2.type, origin: obj2.originId }, // If the found object has an `originId`, that is used instead of the object's `id`. - { type: obj3.type, origin: obj3.id }, + { type: obj1.type, id: obj1.id }, + { type: obj2.type, id: obj2.id, origin: obj2.originId }, + { type: obj3.type, id: obj3.id }, ], - ALIAS_OR_SHARED_ORIGIN_SEARCH_PER_PAGE + ALIAS_OR_SHARED_ORIGIN_SEARCH_PER_PAGE, + undefined ); expect(result.objects).toEqual([ // Note: in a realistic scenario, `spacesWithMatchingOrigins` would be a superset of `spaces`. But for the purposes of this unit @@ -441,8 +442,9 @@ describe('collectMultiNamespaceReferences', () => { expect(mockFindSharedOriginObjects).toHaveBeenCalledTimes(1); expect(mockFindSharedOriginObjects).toHaveBeenCalledWith( expect.anything(), - [{ type: obj1.type, origin: obj1.id }], - ALIAS_OR_SHARED_ORIGIN_SEARCH_PER_PAGE + [{ type: obj1.type, id: obj1.id }], + ALIAS_OR_SHARED_ORIGIN_SEARCH_PER_PAGE, + undefined ); }); @@ -458,6 +460,25 @@ describe('collectMultiNamespaceReferences', () => { 'Failed to retrieve shared origin objects: Oh no!' ); }); + + it('passes options to findSharedOriginObjects', async () => { + const obj1 = { type: MULTI_NAMESPACE_OBJ_TYPE_1, id: 'id-1' }; + const obj2 = { type: MULTI_NAMESPACE_OBJ_TYPE_1, id: 'id-2' }; + const params = setup([obj1, obj2]); + mockMgetResults({ found: true }, { found: false }); // results for obj1 and obj2 + + await collectMultiNamespaceReferences({ + ...params, + options: { purpose: 'updateObjectsSpaces' }, + }); + expect(mockFindSharedOriginObjects).toHaveBeenCalledTimes(1); + expect(mockFindSharedOriginObjects).toHaveBeenCalledWith( + expect.anything(), + [{ type: obj1.type, id: obj1.id }], + ALIAS_OR_SHARED_ORIGIN_SEARCH_PER_PAGE, + 'updateObjectsSpaces' + ); + }); }); describe('with security enabled', () => { diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/collect_multi_namespace_references.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/collect_multi_namespace_references.ts index 87254d1608515f..ab11f76d9e9671 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/collect_multi_namespace_references.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/internals/collect_multi_namespace_references.ts @@ -108,12 +108,14 @@ export async function collectMultiNamespaceReferences( ); const objectOriginsToSearchFor = foundObjects.map(({ type, id, originId }) => ({ type, - origin: originId || id, + id, + origin: originId, })); const originsMap = await findSharedOriginObjects( createPointInTimeFinder, objectOriginsToSearchFor, - ALIAS_OR_SHARED_ORIGIN_SEARCH_PER_PAGE + ALIAS_OR_SHARED_ORIGIN_SEARCH_PER_PAGE, + options?.purpose ); const results = objectsWithContext.map((obj) => { const aliasesVal = aliasesMap.get(getObjectKey(obj)); diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/find_shared_origin_objects.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/find_shared_origin_objects.test.ts index c9f90073da24f7..1622d953d7a361 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/find_shared_origin_objects.test.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/find_shared_origin_objects.test.ts @@ -59,10 +59,10 @@ describe('findSharedOriginObjects', () => { }); } - const obj1 = { type: 'type-1', origin: 'id-1' }; - const obj2 = { type: 'type-2', origin: 'id-2' }; - const obj3 = { type: 'type-3', origin: 'id-3' }; - const obj4 = { type: 'type-4', origin: 'id-4' }; + const obj1 = { type: 'type-1', id: 'id-1', origin: 'origin-1' }; + const obj2 = { type: 'type-2', id: 'id-2', origin: 'origin-2' }; + const obj3 = { type: 'type-3', id: 'id-3', origin: 'origin-3' }; + const obj4 = { type: 'type-4', id: 'id-4', origin: 'origin-4' }; it('uses the PointInTimeFinder to search for legacy URL aliases', async () => { mockFindResults( @@ -156,4 +156,220 @@ describe('findSharedOriginObjects', () => { expect(pointInTimeFinder.find).toHaveBeenCalledTimes(1); expect(pointInTimeFinder.close).toHaveBeenCalledTimes(2); }); + + describe(`when options.purpose is 'updateObjectsSpaces'`, () => { + it('calls createPointInTimeFinder with filter to ignore direct ID matches', async () => { + const objects = [obj1, obj2, obj3]; + await findSharedOriginObjects(createPointInTimeFinder, objects, 999, 'updateObjectsSpaces'); + expect(createPointInTimeFinder).toHaveBeenCalledTimes(1); + expect(createPointInTimeFinder).toHaveBeenCalledWith( + expect.objectContaining({ + filter: expect.objectContaining({ + arguments: expect.arrayContaining([ + expect.objectContaining({ + arguments: expect.arrayContaining([ + expect.objectContaining({ + arguments: [ + { + arguments: [ + { + isQuoted: false, + type: 'literal', + value: 'type-1.id', + }, + { + isQuoted: false, + type: 'literal', + value: 'type-1:id-1', + }, + ], + function: 'is', + type: 'function', + }, + ], + function: 'not', + type: 'function', + }), + ]), + }), + expect.objectContaining({ + arguments: expect.arrayContaining([ + expect.objectContaining({ + arguments: [ + { + arguments: [ + { + isQuoted: false, + type: 'literal', + value: 'type-2.id', + }, + { + isQuoted: false, + type: 'literal', + value: 'type-2:id-2', + }, + ], + function: 'is', + type: 'function', + }, + ], + function: 'not', + type: 'function', + }), + ]), + }), + expect.objectContaining({ + arguments: expect.arrayContaining([ + expect.objectContaining({ + arguments: [ + { + arguments: [ + { + isQuoted: false, + type: 'literal', + value: 'type-3.id', + }, + { + isQuoted: false, + type: 'literal', + value: 'type-3:id-3', + }, + ], + function: 'is', + type: 'function', + }, + ], + function: 'not', + type: 'function', + }), + ]), + }), + ]), + }), + }), + undefined, + { disableExtensions: true } + ); + }); + + it('calls createPointInTimeFinder without redundant filter when object does not have an origin ID', async () => { + const objects = [obj1, { ...obj2, origin: undefined }, obj3]; + await findSharedOriginObjects(createPointInTimeFinder, objects, 999, 'updateObjectsSpaces'); + expect(createPointInTimeFinder).toHaveBeenCalledTimes(1); + expect(createPointInTimeFinder).toHaveBeenCalledWith( + expect.objectContaining({ + filter: expect.objectContaining({ + arguments: expect.arrayContaining([ + expect.objectContaining({ + arguments: expect.arrayContaining([ + expect.objectContaining({ + arguments: [ + { + arguments: [ + { + isQuoted: false, + type: 'literal', + value: 'type-1.id', + }, + { + isQuoted: false, + type: 'literal', + value: 'type-1:origin-1', + }, + ], + function: 'is', + type: 'function', + }, + { + arguments: [ + { + isQuoted: false, + type: 'literal', + value: 'type-1.originId', + }, + { + isQuoted: false, + type: 'literal', + value: 'origin-1', + }, + ], + function: 'is', + type: 'function', + }, + ], + function: 'or', + type: 'function', + }), + ]), + }), + expect.objectContaining({ + arguments: expect.arrayContaining([ + expect.objectContaining({ + arguments: [ + { + isQuoted: false, + type: 'literal', + value: 'type-2.originId', + }, + { + isQuoted: false, + type: 'literal', + value: 'id-2', + }, + ], + function: 'is', + type: 'function', + }), + ]), + }), + expect.objectContaining({ + arguments: expect.arrayContaining([ + expect.objectContaining({ + arguments: [ + { + arguments: [ + { + isQuoted: false, + type: 'literal', + value: 'type-3.id', + }, + { + isQuoted: false, + type: 'literal', + value: 'type-3:origin-3', + }, + ], + function: 'is', + type: 'function', + }, + { + arguments: [ + { + isQuoted: false, + type: 'literal', + value: 'type-3.originId', + }, + { + isQuoted: false, + type: 'literal', + value: 'origin-3', + }, + ], + function: 'is', + type: 'function', + }, + ], + function: 'or', + type: 'function', + }), + ]), + }), + ]), + }), + }), + undefined, + { disableExtensions: true } + ); + }); + }); }); diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/find_shared_origin_objects.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/find_shared_origin_objects.ts index 8ed1f0a3c965af..bdf1a113757633 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/find_shared_origin_objects.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/find_shared_origin_objects.ts @@ -9,13 +9,22 @@ import * as esKuery from '@kbn/es-query'; import { ALL_NAMESPACES_STRING } from '@kbn/core-saved-objects-utils-server'; import { getObjectKey } from '@kbn/core-saved-objects-base-server-internal'; +import { SavedObjectsCollectMultiNamespaceReferencesPurpose } from '@kbn/core-saved-objects-api-server/src/apis'; +import { + KQL_FUNCTION_AND, + KQL_FUNCTION_IS, + KQL_FUNCTION_NOT, + KQL_FUNCTION_OR, +} from '@kbn/es-query/src/kuery/functions'; import type { CreatePointInTimeFinderFn } from '../../point_in_time_finder'; interface ObjectOrigin { /** The object's type. */ type: string; - /** The object's origin is its `originId` field, or its `id` field if that is unavailable. */ - origin: string; + /** The object's ID. */ + id: string; + /** The object's origin is its `originId` field */ + origin: string | undefined; } /** @@ -26,14 +35,15 @@ interface ObjectOrigin { export async function findSharedOriginObjects( createPointInTimeFinder: CreatePointInTimeFinderFn, objects: ObjectOrigin[], - perPage?: number + perPage?: number, + purpose?: SavedObjectsCollectMultiNamespaceReferencesPurpose ) { if (!objects.length) { return new Map>(); } const uniqueObjectTypes = objects.reduce((acc, { type }) => acc.add(type), new Set()); - const filter = createAliasKueryFilter(objects); + const filter = createOriginKueryFilter(objects, purpose); const finder = createPointInTimeFinder( { type: [...uniqueObjectTypes], @@ -80,17 +90,54 @@ export async function findSharedOriginObjects( return objectsMap; } -function createAliasKueryFilter(objects: Array<{ type: string; origin: string }>) { +function createOriginKueryFilter( + objects: ObjectOrigin[], + purpose?: SavedObjectsCollectMultiNamespaceReferencesPurpose +) { const { buildNode } = esKuery.nodeTypes.function; // Note: these nodes include '.attributes' for type-level fields because these are eventually passed to `validateConvertFilterToKueryNode`, which requires it const kueryNodes = objects - .reduce((acc, { type, origin }) => { + .reduce((acc, { type, id, origin }) => { // Escape Kuery values to prevent parsing errors and unintended behavior (object types/IDs can contain KQL special characters/operators) - const match1 = buildNode('is', `${type}.id`, esKuery.escapeKuery(`${type}:${origin}`)); // here we are looking for the raw document `_id` field, which has a `type:` prefix - const match2 = buildNode('is', `${type}.originId`, esKuery.escapeKuery(origin)); // here we are looking for the saved object's `originId` field, which does not have a `type:` prefix - acc.push([match1, match2]); + + // Look for objects with an ID that matches the origin or ID (has a `type:` prefix) + const idMatchesOrigin = buildNode( + KQL_FUNCTION_IS, + `${type}.id`, + esKuery.escapeKuery(`${type}:${origin || id}`) + ); + + // Look for objects with an `originId` that matches the origin or ID (does not have a `type:` prefix) + const originMatch = buildNode( + KQL_FUNCTION_IS, + `${type}.originId`, + esKuery.escapeKuery(origin || id) + ); + + // If we are updating an object's spaces (as opposed to copying)... + if (purpose === 'updateObjectsSpaces') { + // we never want to match on the raw document `_id` fields. + // If they are equal, this just means that the object already exists in that space and it's ok. + const notIdMatch = buildNode( + KQL_FUNCTION_NOT, + buildNode(KQL_FUNCTION_IS, `${type}.id`, esKuery.escapeKuery(`${type}:${id}`)) + ); + + // If this object has an origin ID, then we do still want to match if another object's ID matches the + // object's origin (idMatchesOrigin), or if another object's origin matches the object's origin (originMatch). + // But if this object does not have an origin ID, we can skip the idMatchesOrigin part altogether + // and just check if another object's origin ID matches this object's ID (originMatch). + // (maybe slightly more efficient?) + acc.push( + buildNode(KQL_FUNCTION_AND, [ + notIdMatch, + origin ? buildNode(KQL_FUNCTION_OR, [idMatchesOrigin, originMatch]) : originMatch, + ]) + ); + } else acc.push([idMatchesOrigin, originMatch]); // If we are copying, things are much simpler + return acc; }, []) .flat(); - return buildNode('or', kueryNodes); + return buildNode(KQL_FUNCTION_OR, kueryNodes); } diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/collect_multinamespace_references.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/collect_multinamespace_references.ts index fcd0d079961bd7..f13d2f72613294 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/collect_multinamespace_references.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/collect_multinamespace_references.ts @@ -24,6 +24,13 @@ export interface SavedObjectsCollectMultiNamespaceReferencesObject { type: string; } +/** + * Purpose for collecting references. + */ +export type SavedObjectsCollectMultiNamespaceReferencesPurpose = + | 'collectMultiNamespaceReferences' + | 'updateObjectsSpaces'; + /** * Options for collecting references. * @@ -32,7 +39,7 @@ export interface SavedObjectsCollectMultiNamespaceReferencesObject { export interface SavedObjectsCollectMultiNamespaceReferencesOptions extends SavedObjectsBaseOptions { /** Optional purpose used to determine filtering and authorization checks; default is 'collectMultiNamespaceReferences' */ - purpose?: 'collectMultiNamespaceReferences' | 'updateObjectsSpaces'; + purpose?: SavedObjectsCollectMultiNamespaceReferencesPurpose; } /** 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 ab3c3ca12f5724..d343e1472b86db 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 @@ -35,6 +35,7 @@ export type { SavedObjectReferenceWithContext, SavedObjectsCollectMultiNamespaceReferencesResponse, SavedObjectsCollectMultiNamespaceReferencesOptions, + SavedObjectsCollectMultiNamespaceReferencesPurpose, } from './collect_multinamespace_references'; export type { SavedObjectsCreateOptions } from './create'; export type { diff --git a/x-pack/test/spaces_api_integration/common/suites/get_shareable_references.ts b/x-pack/test/spaces_api_integration/common/suites/get_shareable_references.ts index fb6c22a761f1e8..bedc8a52409b6c 100644 --- a/x-pack/test/spaces_api_integration/common/suites/get_shareable_references.ts +++ b/x-pack/test/spaces_api_integration/common/suites/get_shareable_references.ts @@ -51,7 +51,7 @@ export const EXPECTED_RESULTS: Record { ...TEST_CASE_OBJECTS.SHAREABLE_TYPE, spaces: [DEFAULT_SPACE_ID, SPACE_1_ID, SPACE_2_ID], - spacesWithMatchingOrigins: [DEFAULT_SPACE_ID, SPACE_1_ID, SPACE_2_ID], + // No matching origins because there are no copies of the object in another space (we no longer consider a raw ID match to be an origin match) inboundReferences: [{ type: 'sharedtype', id: CASES.DEFAULT_ONLY.id, name: 'refname' }], // only reflects inbound reference that exist in the default space }, { @@ -65,7 +65,7 @@ export const EXPECTED_RESULTS: Record type: 'sharedtype', id: CASES.DEFAULT_ONLY.id, spaces: [DEFAULT_SPACE_ID], - spacesWithMatchingOrigins: [DEFAULT_SPACE_ID], // The first test assertion for spacesWithMatchingOrigins is an object that doesn't have any matching origins in other spaces + // No matching origins because there are no copies of the object in another space (we no longer consider a raw ID match to be an origin match) inboundReferences: [{ ...TEST_CASE_OBJECTS.SHAREABLE_TYPE, name: 'refname' }], }, { @@ -86,7 +86,7 @@ export const EXPECTED_RESULTS: Record type: 'sharedtype', id: CASES.ALL_SPACES.id, spaces: ['*'], - spacesWithMatchingOrigins: ['*'], + // No matching origins because there are no copies of the object in another space (we no longer consider a raw ID match to be an origin match) inboundReferences: [{ ...TEST_CASE_OBJECTS.SHAREABLE_TYPE, name: 'refname' }], }, ], @@ -94,7 +94,7 @@ export const EXPECTED_RESULTS: Record { ...TEST_CASE_OBJECTS.SHAREABLE_TYPE, spaces: [DEFAULT_SPACE_ID, SPACE_1_ID, SPACE_2_ID], - spacesWithMatchingOrigins: [DEFAULT_SPACE_ID, SPACE_1_ID, SPACE_2_ID], + // No matching origins because there are no copies of the object in another space (we no longer consider a raw ID match to be an origin match) inboundReferences: [{ type: 'sharedtype', id: CASES.SPACE_1_ONLY.id, name: 'refname' }], // only reflects inbound reference that exist in space 1 }, { @@ -116,7 +116,7 @@ export const EXPECTED_RESULTS: Record id: CASES.SPACE_1_ONLY.id, spaces: [SPACE_1_ID], spacesWithMatchingAliases: [DEFAULT_SPACE_ID, SPACE_2_ID], // aliases with a matching targetType and sourceId exist in two other spaces - spacesWithMatchingOrigins: ['other_space', SPACE_1_ID], // The second test assertion for spacesWithMatchingOrigins is an object that has a matching origin in one other space + spacesWithMatchingOrigins: ['other_space'], // The second test assertion for spacesWithMatchingOrigins is an object that has a matching origin in one other space inboundReferences: [{ ...TEST_CASE_OBJECTS.SHAREABLE_TYPE, name: 'refname' }], }, { @@ -130,7 +130,7 @@ export const EXPECTED_RESULTS: Record type: 'sharedtype', id: CASES.ALL_SPACES.id, spaces: ['*'], - spacesWithMatchingOrigins: ['*'], + // No matching origins because there are no copies of the object in another space (we no longer consider a raw ID match to be an origin match) inboundReferences: [{ ...TEST_CASE_OBJECTS.SHAREABLE_TYPE, name: 'refname' }], }, ], @@ -138,7 +138,7 @@ export const EXPECTED_RESULTS: Record { ...TEST_CASE_OBJECTS.SHAREABLE_TYPE, spaces: [DEFAULT_SPACE_ID, SPACE_1_ID, SPACE_2_ID], - spacesWithMatchingOrigins: [DEFAULT_SPACE_ID, SPACE_1_ID, SPACE_2_ID], + // No matching origins because there are no copies of the object in another space (we no longer consider a raw ID match to be an origin match) inboundReferences: [{ type: 'sharedtype', id: CASES.SPACE_2_ONLY.id, name: 'refname' }], // only reflects inbound reference that exist in space 2 }, { @@ -173,7 +173,7 @@ export const EXPECTED_RESULTS: Record type: 'sharedtype', id: CASES.ALL_SPACES.id, spaces: ['*'], - spacesWithMatchingOrigins: ['*'], + // No matching origins because there are no copies of the object in another space (we no longer consider a raw ID match to be an origin match) inboundReferences: [{ ...TEST_CASE_OBJECTS.SHAREABLE_TYPE, name: 'refname' }], }, ], From 36cd0c6045231098bfffa7245f380a9ed0a31a75 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 16 Oct 2023 18:24:58 +0200 Subject: [PATCH 07/87] [Synthetics] Sumary query backward compatability (#168817) ## Summary Summary query backward compatibility !! ### Testing Easiest way to test this is to test this SNAPSHOT version against synthetics service prod locations --- .../common/constants/client_defaults.ts | 47 ++++++++++++- .../components/error_duration.tsx | 2 +- .../components/error_started_at.tsx | 2 +- .../components/failed_tests_list.tsx | 2 + .../hooks/use_error_failed_tests.tsx | 8 +-- .../hooks/use_last_error_state.tsx | 68 ------------------- .../hooks/use_monitor_errors.tsx | 4 +- .../server/common/pings/query_pings.ts | 48 +------------ 8 files changed, 57 insertions(+), 124 deletions(-) delete mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_last_error_state.tsx diff --git a/x-pack/plugins/synthetics/common/constants/client_defaults.ts b/x-pack/plugins/synthetics/common/constants/client_defaults.ts index c330a928d8f934..07d17554e83fcc 100644 --- a/x-pack/plugins/synthetics/common/constants/client_defaults.ts +++ b/x-pack/plugins/synthetics/common/constants/client_defaults.ts @@ -46,11 +46,54 @@ export const CLIENT_DEFAULTS = { export const EXCLUDE_RUN_ONCE_FILTER = { bool: { must_not: { exists: { field: 'run_once' } } } }; export const FINAL_SUMMARY_FILTER = { - term: { - 'summary.final_attempt': true, + bool: { + filter: [ + { + exists: { + field: 'summary', + }, + }, + { + bool: { + should: [ + { + bool: { + should: [ + { + match: { + 'summary.final_attempt': true, + }, + }, + ], + minimum_should_match: 1, + }, + }, + { + bool: { + must_not: { + bool: { + should: [ + { + exists: { + field: 'summary.final_attempt', + }, + }, + ], + minimum_should_match: 1, + }, + }, + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], }, }; +export const SUMMARY_FILTER = { exists: { field: 'summary' } }; + export const getLocationFilter = ({ locationName, locationId, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_duration.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_duration.tsx index bac7b09ecbf843..fb423aff733c4a 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_duration.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_duration.tsx @@ -9,8 +9,8 @@ import { EuiDescriptionList } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import moment, { Moment } from 'moment'; +import { useErrorFailedTests } from '../hooks/use_error_failed_tests'; import { useFindMyKillerState } from '../hooks/use_find_my_killer_state'; -import { useErrorFailedTests } from '../hooks/use_last_error_state'; export const ErrorDuration: React.FC = () => { const { failedTests } = useErrorFailedTests(); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_started_at.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_started_at.tsx index 69331b8ebdb08d..24eb3b2afd5e4d 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_started_at.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_started_at.tsx @@ -8,7 +8,7 @@ import React, { ReactElement } from 'react'; import { EuiDescriptionList, EuiSkeletonText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { useErrorFailedTests } from '../hooks/use_last_error_state'; +import { useErrorFailedTests } from '../hooks/use_error_failed_tests'; import { useDateFormat } from '../../../../../hooks/use_date_format'; export const ErrorStartedAt: React.FC = () => { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/failed_tests_list.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/failed_tests_list.tsx index db59766c4c585e..4376680335e811 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/failed_tests_list.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/failed_tests_list.tsx @@ -39,6 +39,8 @@ export const FailedTestsList = ({ const formatter = useDateFormat(); + // TODO: this is broken for ping monitors + const columns = [ { field: '@timestamp', diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_failed_tests.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_failed_tests.tsx index eb5268c5060891..18d4ae204dfbf0 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_failed_tests.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_failed_tests.tsx @@ -5,13 +5,13 @@ * 2.0. */ -import { useEsSearch } from '@kbn/observability-shared-plugin/public'; import { useParams } from 'react-router-dom'; import { useMemo } from 'react'; +import { useReduxEsSearch } from '../../../hooks/use_redux_es_search'; import { Ping } from '../../../../../../common/runtime_types'; import { EXCLUDE_RUN_ONCE_FILTER, - FINAL_SUMMARY_FILTER, + SUMMARY_FILTER, } from '../../../../../../common/constants/client_defaults'; import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants'; import { useSyntheticsRefreshContext } from '../../../contexts'; @@ -24,7 +24,7 @@ export function useErrorFailedTests() { const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); - const { data, loading } = useEsSearch( + const { data, loading } = useReduxEsSearch( { index: SYNTHETICS_INDEX_PATTERN, body: { @@ -32,7 +32,7 @@ export function useErrorFailedTests() { query: { bool: { filter: [ - FINAL_SUMMARY_FILTER, + SUMMARY_FILTER, EXCLUDE_RUN_ONCE_FILTER, { term: { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_last_error_state.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_last_error_state.tsx deleted file mode 100644 index d86b41f08f5bbf..00000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_last_error_state.tsx +++ /dev/null @@ -1,68 +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 { useParams } from 'react-router-dom'; -import { useMemo } from 'react'; -import { useReduxEsSearch } from '../../../hooks/use_redux_es_search'; -import { Ping } from '../../../../../../common/runtime_types'; -import { - EXCLUDE_RUN_ONCE_FILTER, - FINAL_SUMMARY_FILTER, -} from '../../../../../../common/constants/client_defaults'; -import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants'; -import { useSyntheticsRefreshContext } from '../../../contexts'; -import { useGetUrlParams } from '../../../hooks'; - -export function useErrorFailedTests() { - const { lastRefresh } = useSyntheticsRefreshContext(); - - const { errorStateId, monitorId } = useParams<{ errorStateId: string; monitorId: string }>(); - - const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); - - const { data, loading } = useReduxEsSearch( - { - index: SYNTHETICS_INDEX_PATTERN, - body: { - size: 1000, - query: { - bool: { - filter: [ - FINAL_SUMMARY_FILTER, - EXCLUDE_RUN_ONCE_FILTER, - { - term: { - 'state.id': errorStateId, - }, - }, - { - term: { - config_id: monitorId, - }, - }, - ], - }, - }, - sort: [{ '@timestamp': 'desc' }], - }, - }, - [lastRefresh, monitorId, dateRangeStart, dateRangeEnd], - { name: 'getMonitorErrorFailedTests' } - ); - - return useMemo(() => { - const failedTests = - data?.hits.hits?.map((doc) => { - return doc._source as Ping; - }) ?? []; - - return { - failedTests, - loading, - }; - }, [data, loading]); -} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_errors.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_errors.tsx index 69871de54c7afb..969e98a21c36c1 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_errors.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_errors.tsx @@ -11,7 +11,7 @@ import { useSelectedLocation } from './use_selected_location'; import { Ping, PingState } from '../../../../../../common/runtime_types'; import { EXCLUDE_RUN_ONCE_FILTER, - FINAL_SUMMARY_FILTER, + SUMMARY_FILTER, } from '../../../../../../common/constants/client_defaults'; import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants'; import { useSyntheticsRefreshContext } from '../../../contexts'; @@ -37,7 +37,7 @@ export function useMonitorErrors(monitorIdArg?: string) { query: { bool: { filter: [ - FINAL_SUMMARY_FILTER, + SUMMARY_FILTER, EXCLUDE_RUN_ONCE_FILTER, { range: { diff --git a/x-pack/plugins/synthetics/server/common/pings/query_pings.ts b/x-pack/plugins/synthetics/server/common/pings/query_pings.ts index 762233103e871b..1bc8e58c1b46d0 100644 --- a/x-pack/plugins/synthetics/server/common/pings/query_pings.ts +++ b/x-pack/plugins/synthetics/server/common/pings/query_pings.ts @@ -10,6 +10,7 @@ import { QueryDslFieldAndFormat, QueryDslQueryContainer, } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SUMMARY_FILTER } from '../../../common/constants/client_defaults'; import { UptimeEsClient } from '../../lib'; import { GetPingsParams, @@ -20,43 +21,6 @@ import { const DEFAULT_PAGE_SIZE = 25; -/** - * This branch of filtering is used for monitors of type `browser`. This monitor - * type represents an unbounded set of steps, with each `check_group` representing - * a distinct journey. The document containing the `summary` field is indexed last, and - * contains the data necessary for querying a journey. - * - * Because of this, when querying for "pings", it is important that we treat `browser` summary - * checks as the "ping" we want. Without this filtering, we will receive >= N pings for a journey - * of N steps, because an individual step may also contain multiple documents. - */ -const REMOVE_NON_SUMMARY_BROWSER_CHECKS = { - must_not: [ - { - bool: { - filter: [ - { - term: { - 'monitor.type': 'browser', - }, - }, - { - bool: { - must_not: [ - { - exists: { - field: 'summary', - }, - }, - ], - }, - }, - ], - }, - }, - ], -}; - function isStringArray(value: unknown): value is string[] { if (!Array.isArray(value)) return false; // are all array items strings @@ -72,14 +36,6 @@ type GetParamsWithFields = GetPingsParams & { type GetParamsWithoutFields = GetPingsParams; -export function queryPings( - params: GetPingsParams & { uptimeEsClient: UptimeEsClient } -): Promise; - -export function queryPings( - params: GetParamsWithFields & { uptimeEsClient: UptimeEsClient } -): Promise<{ total: number; pings: F[] }>; - export async function queryPings( params: (GetParamsWithFields | GetParamsWithoutFields) & { uptimeEsClient: UptimeEsClient } ): Promise { @@ -105,12 +61,12 @@ export async function queryPings( query: { bool: { filter: [ + SUMMARY_FILTER, { range: { '@timestamp': { gte: from, lte: to } } }, ...(monitorId ? [{ term: { 'monitor.id': monitorId } }] : []), ...(status ? [{ term: { 'monitor.status': status } }] : []), ...(finalAttempt ? [{ term: { 'summary.final_attempt': finalAttempt } }] : []), ] as QueryDslQueryContainer[], - ...REMOVE_NON_SUMMARY_BROWSER_CHECKS, }, }, sort: [{ '@timestamp': { order: (sort ?? 'desc') as 'asc' | 'desc' } }], From a1f360eac5d538cebd13af795dfdc6e14e944f2a Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Mon, 16 Oct 2023 18:28:43 +0200 Subject: [PATCH 08/87] update canvas a11y test to import SO not re-create index (#168944) ## Summary Related to https://github.com/elastic/kibana/issues/161882 There is no need to re-create `.kibana` index, changing to imported saved objects. --- x-pack/test/accessibility/apps/canvas.ts | 10 +- .../es_archives/canvas/default/data.json.gz | Bin 1326 -> 0 bytes .../es_archives/canvas/default/mappings.json | 314 ------------------ 3 files changed, 8 insertions(+), 316 deletions(-) delete mode 100644 x-pack/test/functional/es_archives/canvas/default/data.json.gz delete mode 100644 x-pack/test/functional/es_archives/canvas/default/mappings.json diff --git a/x-pack/test/accessibility/apps/canvas.ts b/x-pack/test/accessibility/apps/canvas.ts index 231bd1c161fde5..f3dfa9305fb95f 100644 --- a/x-pack/test/accessibility/apps/canvas.ts +++ b/x-pack/test/accessibility/apps/canvas.ts @@ -10,16 +10,22 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const a11y = getService('a11y'); const testSubjects = getService('testSubjects'); - const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); const retry = getService('retry'); const { canvas } = getPageObjects(['canvas']); describe('Canvas Accessibility', () => { before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/canvas/default'); + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/canvas/default' + ); await canvas.goToListingPage(); }); + after(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + }); + it('loads workpads', async function () { await retry.waitFor( 'canvas workpads visible', diff --git a/x-pack/test/functional/es_archives/canvas/default/data.json.gz b/x-pack/test/functional/es_archives/canvas/default/data.json.gz deleted file mode 100644 index ff26856f3d7046d2764ffaab1ba8ff3cf8943f0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1326 zcmV+}1=0E+iwFP!000026SY@sZ`(E${hnXJDqq^cGWe268VFD{Yli|&+bzKgbS?@$ z9W}P(N^%~^{NG2~j$_eolBSDb!{)h{m*TyLhvfAh07-i_waEY^rqW3-0OxW%3&^!^ z_-0{(wV6t72gW)%8@CI;U@DEh4A%Zxp=2q)q8m$7&1!uc1grvV03P~U+s4-CHVn|# zGuyj0>1tfnA@V+i$|;g;*o?jQzKhzzRETjF+@B?D24e6;sXo^IPWt^J}<+~_riC+w|D*U#OkVa z#c06#un!-T*Jb~1V%4k|oA$yaN4Ul51Th0K;CDV{>r>%c`lpu zqN>lP(hOF=DPk~loYOSNn5L8&n<_~~s-1A6?Y}3lgbh`)12blM%5S<>fX>8kcMxDoO59WW?m`C>s6P%lkI04j1 zii^~ z#1Y7IgRR*bT}cs-4i``S@{1>)=HiLKSBobC-z=UkSdWx^jY@b05`bZ{zrPPY*|DxB7PJ*OT*%9?9G0)kZ`IXu zGx8E~^(ZQJxLJ z;ql)+a9B+yRoStAsAW0wy-&O}jXkyO6s#wUCl~!7_`fyt0gx~<{grCsItm`%3V$+f-;53 zk(5e?Qkip{W-7-_D@zTuyP{01rdVzJ+w}@ETaLyNEjFxc7GuJ9I*hFgWb5C8h zwgGSc`fvn>!(lS6MxKVv>2IL{-n~6~djb$#lA#T2@3E|)5i4My?dHW&bsxkFLzEN9 z;*?pgQyRoXP;65}tv|=)(mE)fkQanzckzM}@e8!b*%Q!0H|Ji9!hyIqtqbjoSz7~K z(VX@Wgu_yKMOij6gg>hQJ8HSyYki&X;lTrHjWKZ+E0Q{={B{8uOr_0HN-WG3hZ&Yi zJz=d8!FSaf-=zRV++Ax7+0#luyAt`e3iNIBd~q5+Sg-fq_k*=448BcAFMO4X(ns*8 z@gU+yzU}I2;{W>-Eb~(AKOSqV8wBB$pbez}Q(J%Zo9sd0(k+vIo<++e*P~cNw18PI z@|5F@r(PCxDwY4og+GPo961)9rv7Jz5bRFYoJcukD#cnE<`*(0C>GPC2_@T+qvW=Vi%Yq4F4?<-&PnT!BR|Oa<^<+D kkDE8?;1vG&y4t Date: Mon, 16 Oct 2023 18:33:52 +0200 Subject: [PATCH 09/87] [Fleet] Add Integrations configs tab to display input templates (#168827) Closes https://github.com/elastic/kibana/issues/167327 ## Summary Add Integrations configs tab to display input templates for standalone agent users. This uses the yml endpoint added in https://github.com/elastic/kibana/pull/168015. - The configs tab is shown for all integrations ( installed and not) - Added a link to the docs that explains what those configs are and - Integrations not yet installed also have a warning to remind the user to install them first. ## Testing Navigate to any Integrations, all the integrations will now have a new `Configs` tab that shows the yml input templates. ## Screenshots ### Integration already installed Screenshot 2023-10-13 at 11 45 58 ### Integration note yet installed Screenshot 2023-10-13 at 11 46 31 ### Checklist - [ ] 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 --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- packages/kbn-doc-links/src/get_doc_links.ts | 1 + packages/kbn-doc-links/src/types.ts | 1 + .../plugins/fleet/common/services/routes.ts | 6 + .../fleet/common/types/rest_spec/epm.ts | 16 +++ .../epm/screens/detail/configs/index.tsx | 107 ++++++++++++++++++ .../sections/epm/screens/detail/index.tsx | 25 +++- .../fleet/public/constants/page_paths.ts | 6 + .../fleet/public/hooks/use_request/epm.ts | 18 +++ x-pack/plugins/fleet/public/types/index.ts | 2 + 9 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/configs/index.tsx diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index aeaf3d5c112585..65183620e756d7 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -764,6 +764,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { api: `${FLEET_DOCS}fleet-api-docs.html`, uninstallAgent: `${SECURITY_SOLUTION_DOCS}uninstall-agent.html`, installAndUninstallIntegrationAssets: `${FLEET_DOCS}install-uninstall-integration-assets.html`, + elasticAgentInputConfiguration: `${FLEET_DOCS}elastic-agent-input-configuration.html`, }, ecs: { guide: `${ELASTIC_WEBSITE_URL}guide/en/ecs/current/index.html`, diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index 9bf00917980046..6d4245b769a272 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -522,6 +522,7 @@ export interface DocLinks { api: string; uninstallAgent: string; installAndUninstallIntegrationAssets: string; + elasticAgentInputConfiguration: string; }>; readonly ecs: { readonly guide: string; diff --git a/x-pack/plugins/fleet/common/services/routes.ts b/x-pack/plugins/fleet/common/services/routes.ts index d39fcf1dfa5de9..5aeb25c0e90bf1 100644 --- a/x-pack/plugins/fleet/common/services/routes.ts +++ b/x-pack/plugins/fleet/common/services/routes.ts @@ -93,6 +93,12 @@ export const epmRouteService = { getBulkAssetsPath: () => { return EPM_API_ROUTES.BULK_ASSETS_PATTERN; }, + getInputsTemplatesPath: (pkgName: string, pkgVersion: string) => { + return EPM_API_ROUTES.INPUTS_PATTERN.replace('{pkgName}', pkgName).replace( + '{pkgVersion}', + pkgVersion + ); + }, }; export const packagePolicyRouteService = { diff --git a/x-pack/plugins/fleet/common/types/rest_spec/epm.ts b/x-pack/plugins/fleet/common/types/rest_spec/epm.ts index fcec6fc0f8fa5b..a71f3a4b695cf2 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/epm.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/epm.ts @@ -209,3 +209,19 @@ export interface GetBulkAssetsRequest { export interface GetBulkAssetsResponse { items: SimpleSOAssetType[]; } + +export interface GetInputsTemplatesRequest { + params: { + pkgName: string; + pkgVersion: string; + }; + query: { + format: 'json' | 'yml' | 'yaml'; + }; +} + +export type GetInputsTemplatesResponse = + | string + | { + inputs: any; + }; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/configs/index.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/configs/index.tsx new file mode 100644 index 00000000000000..5fb838637ade47 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/configs/index.tsx @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiText, + EuiCodeBlock, + EuiSpacer, + EuiSkeletonText, + EuiCallOut, + EuiLink, + EuiCode, +} from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import type { PackageInfo } from '../../../../../types'; + +import { useGetInputsTemplatesQuery, useStartServices } from '../../../../../hooks'; + +interface ConfigsProps { + packageInfo: PackageInfo; +} + +export const Configs: React.FC = ({ packageInfo }) => { + const { notifications, docLinks } = useStartServices(); + const { name: pkgName, version: pkgVersion, title: pkgTitle } = packageInfo; + const notInstalled = packageInfo.status !== 'installing'; + + const { + data: configs, + error, + isLoading, + } = useGetInputsTemplatesQuery({ pkgName, pkgVersion }, { format: 'yaml' }); + + if (error) { + notifications.toasts.addError(error, { + title: i18n.translate('xpack.fleet.epm.InputTemplates.loadingErro', { + defaultMessage: 'Error input templates', + }), + }); + } + + return ( + + + + {isLoading && !configs ? ( + + ) : ( + <> + +

+ elastic-agent.yml, + inputsDir: inputs.d, + userGuideLink: ( + + + + ), + }} + /> +

+
+ {notInstalled && ( + <> + + + } + color="warning" + iconType="warning" + /> + + )} + + + {configs} + + + )} +
+
+ ); +}; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx index b803e463d22fe5..463dd453f8f865 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx @@ -83,6 +83,7 @@ import { PackagePoliciesPage } from './policies'; import { SettingsPage } from './settings'; import { CustomViewPage } from './custom'; import { DocumentationPage } from './documentation'; +import { Configs } from './configs'; import './index.scss'; @@ -92,7 +93,8 @@ export type DetailViewPanelName = | 'assets' | 'settings' | 'custom' - | 'api-reference'; + | 'api-reference' + | 'configs'; export interface DetailParams { pkgkey: string; @@ -625,6 +627,24 @@ export function Detail() { }); } + if (canReadPackageSettings) { + tabs.push({ + id: 'configs', + name: ( + + ), + isSelected: panel === 'configs', + 'data-test-subj': `tab-configs`, + href: getHref('integration_details_configs', { + pkgkey: packageInfoKey, + ...(integration ? { integration } : {}), + }), + }); + } + if (canReadPackageSettings && showCustomTab) { tabs.push({ id: 'custom', @@ -746,6 +766,9 @@ export function Detail() { + + + diff --git a/x-pack/plugins/fleet/public/constants/page_paths.ts b/x-pack/plugins/fleet/public/constants/page_paths.ts index cfcd2355e6a3da..9601198112ab3e 100644 --- a/x-pack/plugins/fleet/public/constants/page_paths.ts +++ b/x-pack/plugins/fleet/public/constants/page_paths.ts @@ -34,6 +34,7 @@ export type DynamicPage = | 'integration_details_custom' | 'integration_details_language_clients' | 'integration_details_api_reference' + | 'integration_details_configs' | 'integration_policy_edit' | 'integration_policy_upgrade' | 'policy_details' @@ -101,6 +102,7 @@ export const INTEGRATIONS_ROUTING_PATHS = { integration_details_policies: '/detail/:pkgkey/policies', integration_details_assets: '/detail/:pkgkey/assets', integration_details_settings: '/detail/:pkgkey/settings', + integration_details_configs: '/detail/:pkgkey/configs', integration_details_custom: '/detail/:pkgkey/custom', integration_details_api_reference: '/detail/:pkgkey/api-reference', integration_details_language_clients: '/language_clients/:pkgkey/overview', @@ -166,6 +168,10 @@ export const pagePathGetters: { INTEGRATIONS_BASE_PATH, `/detail/${pkgkey}/settings${integration ? `?integration=${integration}` : ''}`, ], + integration_details_configs: ({ pkgkey, integration }) => [ + INTEGRATIONS_BASE_PATH, + `/detail/${pkgkey}/configs${integration ? `?integration=${integration}` : ''}`, + ], integration_details_custom: ({ pkgkey, integration }) => [ INTEGRATIONS_BASE_PATH, `/detail/${pkgkey}/custom${integration ? `?integration=${integration}` : ''}`, diff --git a/x-pack/plugins/fleet/public/hooks/use_request/epm.ts b/x-pack/plugins/fleet/public/hooks/use_request/epm.ts index 24a36f969247db..03b2b5973c98a7 100644 --- a/x-pack/plugins/fleet/public/hooks/use_request/epm.ts +++ b/x-pack/plugins/fleet/public/hooks/use_request/epm.ts @@ -26,6 +26,8 @@ import type { GetBulkAssetsRequest, GetBulkAssetsResponse, GetVerificationKeyIdResponse, + GetInputsTemplatesRequest, + GetInputsTemplatesResponse, } from '../../types'; import type { FleetErrorResponse, GetStatsResponse } from '../../../common/types'; import { API_VERSIONS } from '../../../common/constants'; @@ -313,3 +315,19 @@ export const sendGetBulkAssets = (body: GetBulkAssetsRequest['body']) => { body, }); }; + +export function useGetInputsTemplatesQuery( + { pkgName, pkgVersion }: GetInputsTemplatesRequest['params'], + query: GetInputsTemplatesRequest['query'] +) { + return useQuery( + ['inputsTemplates', pkgName, pkgVersion, query], + () => + sendRequestForRq({ + path: epmRouteService.getInputsTemplatesPath(pkgName, pkgVersion), + method: 'get', + query, + version: API_VERSIONS.public.v1, + }) + ); +} diff --git a/x-pack/plugins/fleet/public/types/index.ts b/x-pack/plugins/fleet/public/types/index.ts index 1cd2e2f798db3c..8c7d3ddcf5b453 100644 --- a/x-pack/plugins/fleet/public/types/index.ts +++ b/x-pack/plugins/fleet/public/types/index.ts @@ -135,6 +135,8 @@ export type { GetBulkAssetsRequest, GetBulkAssetsResponse, KibanaSavedObjectType, + GetInputsTemplatesRequest, + GetInputsTemplatesResponse, } from '../../common/types'; export { entries, From d7028ca9e0f7c60f9910ce93c85724875d160512 Mon Sep 17 00:00:00 2001 From: dkirchan <55240027+dkirchan@users.noreply.github.com> Date: Mon, 16 Oct 2023 19:34:29 +0300 Subject: [PATCH 10/87] Commented out the security quality gate - Not ready for integration (#168979) ## Summary Security quality gate is not ready to be integrated yet. In case of questions reach out to : @charlie-pichette @dkirchan ### 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) --- .../quality-gates/pipeline.tests-qa.yaml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.buildkite/pipelines/quality-gates/pipeline.tests-qa.yaml b/.buildkite/pipelines/quality-gates/pipeline.tests-qa.yaml index e0a892326eb186..29c7ad4ee8491a 100644 --- a/.buildkite/pipelines/quality-gates/pipeline.tests-qa.yaml +++ b/.buildkite/pipelines/quality-gates/pipeline.tests-qa.yaml @@ -12,14 +12,15 @@ steps: EC_ENV: qa EC_REGION: aws-eu-west-1 message: "${BUILDKITE_MESSAGE} (triggered by pipeline.tests-qa.yaml)" - - - label: ":pipeline::female-detective::seedling: Trigger Security Solution quality gate script" - trigger: security-serverless-quality-gate # https://buildkite.com/elastic/security-serverless-quality-gate - soft_fail: true # Remove this when tests are fixed - build: - env: - ENVIRONMENT: ${ENVIRONMENT} - message: "${BUILDKITE_MESSAGE} (triggered by pipeline.tests-qa.yaml)" + + # TODO: Uncomment this code when the integration is ready. + # - label: ":pipeline::female-detective::seedling: Trigger Security Solution quality gate script" + # trigger: security-serverless-quality-gate # https://buildkite.com/elastic/security-serverless-quality-gate + # soft_fail: true # Remove this when tests are fixed + # build: + # env: + # ENVIRONMENT: ${ENVIRONMENT} + # message: "${BUILDKITE_MESSAGE} (triggered by pipeline.tests-qa.yaml)" - label: ":pipeline::ship::seedling: Trigger Fleet serverless smoke tests for ${ENVIRONMENT}" trigger: fleet-smoke-tests # https://buildkite.com/elastic/fleet-smoke-tests From 6fcf8c9efe43fd9c6b9cd24ed6445b59720fb00b Mon Sep 17 00:00:00 2001 From: Coen Warmer Date: Mon, 16 Oct 2023 18:34:50 +0200 Subject: [PATCH 11/87] Add ESLint rule for Translations (#168001) Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Jon --- .eslintrc.js | 2 + .github/CODEOWNERS | 1 + package.json | 1 + packages/kbn-eslint-config/.eslintrc.js | 1 + packages/kbn-eslint-plugin-i18n/README.mdx | 17 ++ .../helpers/get_function_name.ts | 35 ++++ ...get_i18n_identifier_from_file_path.test.ts | 31 +++ .../get_i18n_identifier_from_file_path.ts | 29 +++ .../helpers/get_i18n_import_fixer.ts | 50 +++++ .../helpers/get_intent_from_node.ts | 40 ++++ .../kbn-eslint-plugin-i18n/helpers/utils.ts | 19 ++ packages/kbn-eslint-plugin-i18n/index.ts | 20 ++ .../kbn-eslint-plugin-i18n/jest.config.js | 13 ++ packages/kbn-eslint-plugin-i18n/kibana.jsonc | 6 + packages/kbn-eslint-plugin-i18n/package.json | 6 + ..._translated_with_formatted_message.test.ts | 176 ++++++++++++++++++ ...ld_be_translated_with_formatted_message.ts | 77 ++++++++ ...ngs_should_be_translated_with_i18n.test.ts | 164 ++++++++++++++++ .../strings_should_be_translated_with_i18n.ts | 74 ++++++++ packages/kbn-eslint-plugin-i18n/tsconfig.json | 11 ++ tsconfig.base.json | 2 + yarn.lock | 4 + 22 files changed, 779 insertions(+) create mode 100644 packages/kbn-eslint-plugin-i18n/README.mdx create mode 100644 packages/kbn-eslint-plugin-i18n/helpers/get_function_name.ts create mode 100644 packages/kbn-eslint-plugin-i18n/helpers/get_i18n_identifier_from_file_path.test.ts create mode 100644 packages/kbn-eslint-plugin-i18n/helpers/get_i18n_identifier_from_file_path.ts create mode 100644 packages/kbn-eslint-plugin-i18n/helpers/get_i18n_import_fixer.ts create mode 100644 packages/kbn-eslint-plugin-i18n/helpers/get_intent_from_node.ts create mode 100644 packages/kbn-eslint-plugin-i18n/helpers/utils.ts create mode 100644 packages/kbn-eslint-plugin-i18n/index.ts create mode 100644 packages/kbn-eslint-plugin-i18n/jest.config.js create mode 100644 packages/kbn-eslint-plugin-i18n/kibana.jsonc create mode 100644 packages/kbn-eslint-plugin-i18n/package.json create mode 100644 packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_formatted_message.test.ts create mode 100644 packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_formatted_message.ts create mode 100644 packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_i18n.test.ts create mode 100644 packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_i18n.ts create mode 100644 packages/kbn-eslint-plugin-i18n/tsconfig.json diff --git a/.eslintrc.js b/.eslintrc.js index 7b18904722c26b..67cb263bcf4938 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -924,6 +924,8 @@ module.exports = { ], rules: { '@kbn/telemetry/event_generating_elements_should_be_instrumented': 'error', + '@kbn/i18n/strings_should_be_translated_with_i18n': 'warn', + '@kbn/i18n/strings_should_be_translated_with_formatted_message': 'warn', }, }, { diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ccb65e643d219e..044ce6273292cf 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -360,6 +360,7 @@ src/plugins/es_ui_shared @elastic/platform-deployment-management packages/kbn-eslint-config @elastic/kibana-operations packages/kbn-eslint-plugin-disable @elastic/kibana-operations packages/kbn-eslint-plugin-eslint @elastic/kibana-operations +packages/kbn-eslint-plugin-i18n @elastic/actionable-observability packages/kbn-eslint-plugin-imports @elastic/kibana-operations packages/kbn-eslint-plugin-telemetry @elastic/actionable-observability x-pack/test/encrypted_saved_objects_api_integration/plugins/api_consumer_plugin @elastic/kibana-security diff --git a/package.json b/package.json index fb0d2494e98420..5718ec17493f3d 100644 --- a/package.json +++ b/package.json @@ -1196,6 +1196,7 @@ "@kbn/eslint-config": "link:packages/kbn-eslint-config", "@kbn/eslint-plugin-disable": "link:packages/kbn-eslint-plugin-disable", "@kbn/eslint-plugin-eslint": "link:packages/kbn-eslint-plugin-eslint", + "@kbn/eslint-plugin-i18n": "link:packages/kbn-eslint-plugin-i18n", "@kbn/eslint-plugin-imports": "link:packages/kbn-eslint-plugin-imports", "@kbn/eslint-plugin-telemetry": "link:packages/kbn-eslint-plugin-telemetry", "@kbn/expect": "link:packages/kbn-expect", diff --git a/packages/kbn-eslint-config/.eslintrc.js b/packages/kbn-eslint-config/.eslintrc.js index 36504cb8b83554..e9fae3fd1b2900 100644 --- a/packages/kbn-eslint-config/.eslintrc.js +++ b/packages/kbn-eslint-config/.eslintrc.js @@ -8,6 +8,7 @@ module.exports = { '@kbn/eslint-plugin-eslint', '@kbn/eslint-plugin-imports', '@kbn/eslint-plugin-telemetry', + '@kbn/eslint-plugin-i18n', 'prettier', ], diff --git a/packages/kbn-eslint-plugin-i18n/README.mdx b/packages/kbn-eslint-plugin-i18n/README.mdx new file mode 100644 index 00000000000000..0a22ff846726ee --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/README.mdx @@ -0,0 +1,17 @@ +--- +id: kibDevDocsOpsEslintPluginI18N +slug: /kibana-dev-docs/ops/kbn-eslint-plugin-i18n +title: '@kbn/eslint-plugin-i18n' +description: Custom ESLint rules to support translations in the Kibana repository +tags: ['kibana', 'dev', 'contributor', 'operations', 'eslint', 'i18n'] +--- + +`@kbn/eslint-plugin-i18n` is an ESLint plugin providing custom rules for validating JSXCode in the Kibana repo to make sure they are translated. + +## `@kbn/i18n/strings_should_be_translated_with_i18n` + +This rule warns engineers to translate their strings by using i18n.translate from the '@kbn/i18n' package. It provides an autofix that takes into account the context of the translatable string in the JSX tree to generate a translation ID. + +## `@kbn/i18n/strings_should_be_translated_with_formatted_message` + +This rule warns engineers to translate their strings by using `` from the '@kbn/i18n-react' package. It provides an autofix that takes into account the context of the translatable string in the JSX tree and to generate a translation ID. diff --git a/packages/kbn-eslint-plugin-i18n/helpers/get_function_name.ts b/packages/kbn-eslint-plugin-i18n/helpers/get_function_name.ts new file mode 100644 index 00000000000000..c82ce04480b82b --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/helpers/get_function_name.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 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 { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree'; +import { lowerCaseFirstLetter } from './utils'; + +export function getFunctionName(func: TSESTree.FunctionDeclaration | TSESTree.Node): string { + if ( + 'id' in func && + func.id && + func.type === AST_NODE_TYPES.FunctionDeclaration && + func.id.type === AST_NODE_TYPES.Identifier + ) { + return lowerCaseFirstLetter(func.id.name); + } + + if ( + func.parent && + (func.parent.type !== AST_NODE_TYPES.VariableDeclarator || + func.parent.id.type !== AST_NODE_TYPES.Identifier) + ) { + return getFunctionName(func.parent); + } + + if (func.parent?.id && 'name' in func.parent.id) { + return lowerCaseFirstLetter(func.parent.id.name); + } + + return ''; +} diff --git a/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_identifier_from_file_path.test.ts b/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_identifier_from_file_path.test.ts new file mode 100644 index 00000000000000..d1157b7b16f10f --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_identifier_from_file_path.test.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 { getI18nIdentifierFromFilePath } from './get_i18n_identifier_from_file_path'; + +const SYSTEMPATH = 'systemPath'; + +const testMap = [ + ['x-pack/plugins/observability/foo/bar/baz/header_actions.tsx', 'xpack.observability'], + ['x-pack/plugins/apm/public/components/app/correlations/correlations_table.tsx', 'xpack.apm'], + ['x-pack/plugins/cases/public/components/foo.tsx', 'xpack.cases'], + [ + 'packages/kbn-alerts-ui-shared/src/alert_lifecycle_status_badge/index.tsx', + 'app_not_found_in_i18nrc', + ], +]; + +describe('Get i18n Identifier for file', () => { + test.each(testMap)( + 'should get the right i18n identifier for a file inside an x-pack plugin', + (path, expectedValue) => { + const appName = getI18nIdentifierFromFilePath(`${SYSTEMPATH}/${path}`, SYSTEMPATH); + expect(appName).toBe(expectedValue); + } + ); +}); diff --git a/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_identifier_from_file_path.ts b/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_identifier_from_file_path.ts new file mode 100644 index 00000000000000..360f70e0b3fa82 --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_identifier_from_file_path.ts @@ -0,0 +1,29 @@ +/* + * 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 fs from 'fs'; +import { join, parse, resolve } from 'path'; +import { findKey } from 'lodash'; + +export function getI18nIdentifierFromFilePath(fileName: string, cwd: string) { + const { dir } = parse(fileName); + const relativePathToFile = dir.replace(cwd, ''); + + const relativePathArray = relativePathToFile.split('/'); + + const path = `${relativePathArray[2]}/${relativePathArray[3]}`; + + const xpackRC = resolve(join(__dirname, '../../../'), 'x-pack/.i18nrc.json'); + + const i18nrcFile = fs.readFileSync(xpackRC, 'utf8'); + const i18nrc = JSON.parse(i18nrcFile); + + return i18nrc && i18nrc.paths + ? findKey(i18nrc.paths, (v) => v === path) ?? 'app_not_found_in_i18nrc' + : 'app_not_found_in_i18nrc'; +} diff --git a/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_import_fixer.ts b/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_import_fixer.ts new file mode 100644 index 00000000000000..f26bc62c555f05 --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_import_fixer.ts @@ -0,0 +1,50 @@ +/* + * 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 { SourceCode } from 'eslint'; + +const KBN_I18N_I18N_IMPORT = "import { i18n } from '@kbn/i18n';" as const; +const KBN_I18N_REACT_FORMATTED_MESSAGE_IMPORT = + "import { FormattedMessage } from '@kbn/i18n-react';" as const; +export function getI18nImportFixer({ + sourceCode, + mode, +}: { + sourceCode: SourceCode; + mode: 'i18n.translate' | 'FormattedMessage'; +}) { + const hasI18nImportLine = Boolean( + sourceCode.lines.find((l) => + mode === 'i18n.translate' + ? l === KBN_I18N_I18N_IMPORT + : l === KBN_I18N_REACT_FORMATTED_MESSAGE_IMPORT + ) + ); + + if (hasI18nImportLine) return { hasI18nImportLine }; + + // Translation package has not been imported yet so we need to add it. + // Pretty safe bet to add it underneath the React import. + const reactImportLineIndex = sourceCode.lines.findIndex((l) => l.includes("from 'react'")); + + const targetLine = sourceCode.lines[reactImportLineIndex]; + const column = targetLine.length; + + const start = sourceCode.getIndexFromLoc({ line: reactImportLineIndex + 1, column: 0 }); + const end = sourceCode.getIndexFromLoc({ + line: reactImportLineIndex + 1, + column, + }); + + return { + hasI18nImportLine, + i18nPackageImportLine: + mode === 'i18n.translate' ? KBN_I18N_I18N_IMPORT : KBN_I18N_REACT_FORMATTED_MESSAGE_IMPORT, + rangeToAddI18nImportLine: [start, end] as [number, number], + }; +} diff --git a/packages/kbn-eslint-plugin-i18n/helpers/get_intent_from_node.ts b/packages/kbn-eslint-plugin-i18n/helpers/get_intent_from_node.ts new file mode 100644 index 00000000000000..4cbd6bb9e330d5 --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/helpers/get_intent_from_node.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 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 { TSESTree } from '@typescript-eslint/typescript-estree'; +import { lowerCaseFirstLetter, upperCaseFirstLetter } from './utils'; + +export function getIntentFromNode(originalNode: TSESTree.JSXText): string { + const value = lowerCaseFirstLetter( + originalNode.value + .replace(/[?!@#$%^&*()_+\][{}|/<>,'"]/g, '') + .trim() + .split(' ') + .filter((v, i) => i < 4) + .map(upperCaseFirstLetter) + .join('') + ); + + const { parent } = originalNode; + + if ( + parent && + 'openingElement' in parent && + 'name' in parent.openingElement && + 'name' in parent.openingElement.name + ) { + const parentTagName = String(parent.openingElement.name.name); + + if (parentTagName.includes('Eui')) { + return `${value}${parentTagName.replace('Eui', '')}Label`; + } + + return `${lowerCaseFirstLetter(parentTagName)}.${value}Label`; + } + + return `${value}Label`; +} diff --git a/packages/kbn-eslint-plugin-i18n/helpers/utils.ts b/packages/kbn-eslint-plugin-i18n/helpers/utils.ts new file mode 100644 index 00000000000000..74ce8aa7c5c554 --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/helpers/utils.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. + */ + +export function lowerCaseFirstLetter(str: string) { + return str.charAt(0).toLowerCase() + str.slice(1); +} + +export function upperCaseFirstLetter(str: string) { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +export function isTruthy(value: T): value is NonNullable { + return value != null; +} diff --git a/packages/kbn-eslint-plugin-i18n/index.ts b/packages/kbn-eslint-plugin-i18n/index.ts new file mode 100644 index 00000000000000..d6fba728b7d219 --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/index.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 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 { StringsShouldBeTranslatedWithI18n } from './rules/strings_should_be_translated_with_i18n'; +import { StringsShouldBeTranslatedWithFormattedMessage } from './rules/strings_should_be_translated_with_formatted_message'; + +/** + * Custom ESLint rules, add `'@kbn/eslint-plugin-telemetry'` to your eslint config to use them + * @internal + */ +export const rules = { + strings_should_be_translated_with_i18n: StringsShouldBeTranslatedWithI18n, + strings_should_be_translated_with_formatted_message: + StringsShouldBeTranslatedWithFormattedMessage, +}; diff --git a/packages/kbn-eslint-plugin-i18n/jest.config.js b/packages/kbn-eslint-plugin-i18n/jest.config.js new file mode 100644 index 00000000000000..1ab5f78f024bf3 --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/jest.config.js @@ -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. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../..', + roots: ['/packages/kbn-eslint-plugin-i18n'], +}; diff --git a/packages/kbn-eslint-plugin-i18n/kibana.jsonc b/packages/kbn-eslint-plugin-i18n/kibana.jsonc new file mode 100644 index 00000000000000..7d8c994400108b --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/kibana.jsonc @@ -0,0 +1,6 @@ +{ + "type": "shared-common", + "id": "@kbn/eslint-plugin-i18n", + "owner": "@elastic/actionable-observability", + "devOnly": true +} diff --git a/packages/kbn-eslint-plugin-i18n/package.json b/packages/kbn-eslint-plugin-i18n/package.json new file mode 100644 index 00000000000000..1668a7e0f3690c --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/eslint-plugin-i18n", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_formatted_message.test.ts b/packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_formatted_message.test.ts new file mode 100644 index 00000000000000..aa545c9bb0ee06 --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_formatted_message.test.ts @@ -0,0 +1,176 @@ +/* + * 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 { RuleTester } from 'eslint'; +import { StringsShouldBeTranslatedWithFormattedMessage } from './strings_should_be_translated_with_formatted_message'; + +const tsTester = [ + '@typescript-eslint/parser', + new RuleTester({ + parser: require.resolve('@typescript-eslint/parser'), + parserOptions: { + sourceType: 'module', + ecmaVersion: 2018, + ecmaFeatures: { + jsx: true, + }, + }, + }), +] as const; + +const babelTester = [ + '@babel/eslint-parser', + new RuleTester({ + parser: require.resolve('@babel/eslint-parser'), + parserOptions: { + sourceType: 'module', + ecmaVersion: 2018, + requireConfigFile: false, + babelOptions: { + presets: ['@kbn/babel-preset/node_preset'], + }, + }, + }), +] as const; + +const valid = [ + { + filename: 'x-pack/plugins/observability/public/test_component.tsx', + code: ` +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; + +function TestComponent() { + return ( +
+
+ ) +}`, + }, + { + filename: 'x-pack/plugins/observability/public/another_component.tsx', + code: ` +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; + +function AnotherComponent() { + return ( + + + + + + + + + ) +}`, + }, + { + filename: 'x-pack/plugins/observability/public/yet_another_component.tsx', + code: ` +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; + +function YetAnotherComponent() { + return ( +
+ + +
+ ) +}`, + }, +]; + +const invalid = [ + { + filename: valid[0].filename, + code: ` +import React from 'react'; + +function TestComponent() { + return ( +
This is a test
+ ) +}`, + errors: [ + { + line: 6, + message: `Strings should be translated with . Use the autofix suggestion or add your own.`, + }, + ], + output: valid[0].code, + }, + { + filename: valid[1].filename, + code: ` +import React from 'react'; + +function AnotherComponent() { + return ( + + + + This is a test + + + + ) +}`, + errors: [ + { + line: 9, + message: `Strings should be translated with . Use the autofix suggestion or add your own.`, + }, + ], + output: valid[1].code, + }, + { + filename: valid[2].filename, + code: ` +import React from 'react'; + +function YetAnotherComponent() { + return ( +
+ Select me +
+ ) +}`, + errors: [ + { + line: 7, + message: `Strings should be translated with . Use the autofix suggestion or add your own.`, + }, + ], + output: valid[2].code, + }, +]; + +for (const [name, tester] of [tsTester, babelTester]) { + describe(name, () => { + tester.run( + '@kbn/event_generating_elements_should_be_instrumented', + StringsShouldBeTranslatedWithFormattedMessage, + { + valid, + invalid, + } + ); + }); +} diff --git a/packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_formatted_message.ts b/packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_formatted_message.ts new file mode 100644 index 00000000000000..251fb3b3752fce --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_formatted_message.ts @@ -0,0 +1,77 @@ +/* + * 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 { TSESTree } from '@typescript-eslint/typescript-estree'; +import type { Rule } from 'eslint'; +import { getIntentFromNode } from '../helpers/get_intent_from_node'; +import { getI18nIdentifierFromFilePath } from '../helpers/get_i18n_identifier_from_file_path'; +import { getFunctionName } from '../helpers/get_function_name'; +import { getI18nImportFixer } from '../helpers/get_i18n_import_fixer'; +import { isTruthy } from '../helpers/utils'; + +export const StringsShouldBeTranslatedWithFormattedMessage: Rule.RuleModule = { + meta: { + type: 'suggestion', + fixable: 'code', + }, + create(context) { + const { cwd, filename, getScope, sourceCode, report } = context; + + return { + JSXText: (node: TSESTree.JSXText) => { + const value = node.value.trim(); + + // If the JSXText element is empty we don't need to do anything + if (!value) return; + + // Get the whitespaces before the string so we can add them to the autofix suggestion + const regex = /^(\s*)(\S)(.*)/; + const whiteSpaces = node.value.match(regex)?.[1] ?? ''; + + // Start building the translation ID suggestion + const i18nAppId = getI18nIdentifierFromFilePath(filename, cwd); + const functionDeclaration = getScope().block as TSESTree.FunctionDeclaration; + const functionName = getFunctionName(functionDeclaration); + const intent = getIntentFromNode(node); + + const translationIdSuggestion = `${i18nAppId}.${functionName}.${intent}`; // 'xpack.observability.overview.logs.loadMoreLabel' + + // Check if i18n has already been imported into the file. + const { + hasI18nImportLine, + i18nPackageImportLine: i18nImportLine, + rangeToAddI18nImportLine, + } = getI18nImportFixer({ + sourceCode, + mode: 'FormattedMessage', + }); + + // Show warning to developer and offer autofix suggestion + report({ + node: node as any, + message: + 'Strings should be translated with . Use the autofix suggestion or add your own.', + fix(fixer) { + return [ + fixer.replaceText( + node, + `${whiteSpaces}\n` + ), + !hasI18nImportLine + ? fixer.insertTextAfterRange(rangeToAddI18nImportLine, `\n${i18nImportLine}`) + : null, + ].filter(isTruthy); + }, + }); + }, + } as Rule.RuleListener; + }, +}; diff --git a/packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_i18n.test.ts b/packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_i18n.test.ts new file mode 100644 index 00000000000000..4c5916831b6cbc --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_i18n.test.ts @@ -0,0 +1,164 @@ +/* + * 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 { RuleTester } from 'eslint'; +import { StringsShouldBeTranslatedWithI18n } from './strings_should_be_translated_with_i18n'; + +const tsTester = [ + '@typescript-eslint/parser', + new RuleTester({ + parser: require.resolve('@typescript-eslint/parser'), + parserOptions: { + sourceType: 'module', + ecmaVersion: 2018, + ecmaFeatures: { + jsx: true, + }, + }, + }), +] as const; + +const babelTester = [ + '@babel/eslint-parser', + new RuleTester({ + parser: require.resolve('@babel/eslint-parser'), + parserOptions: { + sourceType: 'module', + ecmaVersion: 2018, + requireConfigFile: false, + babelOptions: { + presets: ['@kbn/babel-preset/node_preset'], + }, + }, + }), +] as const; + +const valid = [ + { + filename: 'x-pack/plugins/observability/public/test_component.tsx', + code: ` +import React from 'react'; +import { i18n } from '@kbn/i18n'; + +function TestComponent() { + return ( +
{i18n.translate('app_not_found_in_i18nrc.testComponent.div.thisIsATestLabel', { defaultMessage: "This is a test"})}
+ ) +}`, + }, + { + filename: 'x-pack/plugins/observability/public/another_component.tsx', + code: ` +import React from 'react'; +import { i18n } from '@kbn/i18n'; + +function AnotherComponent() { + return ( + + + + {i18n.translate('app_not_found_in_i18nrc.anotherComponent.thisIsATestButtonLabel', { defaultMessage: "This is a test"})} + + + + ) +}`, + }, + { + filename: 'x-pack/plugins/observability/public/yet_another_component.tsx', + code: ` +import React from 'react'; +import { i18n } from '@kbn/i18n'; + +function YetAnotherComponent() { + return ( +
+ {i18n.translate('app_not_found_in_i18nrc.yetAnotherComponent.selectMeSelectLabel', { defaultMessage: "Select me"})} +
+ ) +}`, + }, +]; + +const invalid = [ + { + filename: valid[0].filename, + code: ` +import React from 'react'; + +function TestComponent() { + return ( +
This is a test
+ ) +}`, + errors: [ + { + line: 6, + message: `Strings should be translated with i18n. Use the autofix suggestion or add your own.`, + }, + ], + output: valid[0].code, + }, + { + filename: valid[1].filename, + code: ` +import React from 'react'; + +function AnotherComponent() { + return ( + + + + This is a test + + + + ) +}`, + errors: [ + { + line: 9, + message: `Strings should be translated with i18n. Use the autofix suggestion or add your own.`, + }, + ], + output: valid[1].code, + }, + { + filename: valid[2].filename, + code: ` +import React from 'react'; + +function YetAnotherComponent() { + return ( +
+ Select me +
+ ) +}`, + errors: [ + { + line: 7, + message: `Strings should be translated with i18n. Use the autofix suggestion or add your own.`, + }, + ], + output: valid[2].code, + }, +]; + +for (const [name, tester] of [tsTester, babelTester]) { + describe(name, () => { + tester.run( + '@kbn/event_generating_elements_should_be_instrumented', + StringsShouldBeTranslatedWithI18n, + { + valid, + invalid, + } + ); + }); +} diff --git a/packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_i18n.ts b/packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_i18n.ts new file mode 100644 index 00000000000000..a1e0da36921b6d --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/rules/strings_should_be_translated_with_i18n.ts @@ -0,0 +1,74 @@ +/* + * 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 { TSESTree } from '@typescript-eslint/typescript-estree'; +import type { Rule } from 'eslint'; +import { getIntentFromNode } from '../helpers/get_intent_from_node'; +import { getI18nIdentifierFromFilePath } from '../helpers/get_i18n_identifier_from_file_path'; +import { getFunctionName } from '../helpers/get_function_name'; +import { getI18nImportFixer } from '../helpers/get_i18n_import_fixer'; +import { isTruthy } from '../helpers/utils'; + +export const StringsShouldBeTranslatedWithI18n: Rule.RuleModule = { + meta: { + type: 'suggestion', + fixable: 'code', + }, + create(context) { + const { cwd, filename, getScope, sourceCode, report } = context; + + return { + JSXText: (node: TSESTree.JSXText) => { + const value = node.value.trim(); + + // If the JSXText element is empty we don't need to do anything + if (!value) return; + + // Get the whitespaces before the string so we can add them to the autofix suggestion + const regex = /^(\s*)(\S)(.*)/; + const whiteSpaces = node.value.match(regex)?.[1] ?? ''; + + // Start building the translation ID suggestion + const i18nAppId = getI18nIdentifierFromFilePath(filename, cwd); + const functionDeclaration = getScope().block as TSESTree.FunctionDeclaration; + const functionName = getFunctionName(functionDeclaration); + const intent = getIntentFromNode(node); + + const translationIdSuggestion = `${i18nAppId}.${functionName}.${intent}`; // 'xpack.observability.overview.logs.loadMoreLabel' + + // Check if i18n has already been imported into the file. + const { + hasI18nImportLine, + i18nPackageImportLine: i18nImportLine, + rangeToAddI18nImportLine, + } = getI18nImportFixer({ + sourceCode, + mode: 'i18n.translate', + }); + + // Show warning to developer and offer autofix suggestion + report({ + node: node as any, + message: + 'Strings should be translated with i18n. Use the autofix suggestion or add your own.', + fix(fixer) { + return [ + fixer.replaceText( + node, + `${whiteSpaces}{i18n.translate('${translationIdSuggestion}', { defaultMessage: "${value}"})}` + ), + !hasI18nImportLine + ? fixer.insertTextAfterRange(rangeToAddI18nImportLine, `\n${i18nImportLine}`) + : null, + ].filter(isTruthy); + }, + }); + }, + } as Rule.RuleListener; + }, +}; diff --git a/packages/kbn-eslint-plugin-i18n/tsconfig.json b/packages/kbn-eslint-plugin-i18n/tsconfig.json new file mode 100644 index 00000000000000..a6dec1c1a62c5e --- /dev/null +++ b/packages/kbn-eslint-plugin-i18n/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": ["jest", "node"], + "lib": ["es2021"] + }, + "include": ["**/*.ts"], + "exclude": ["target/**/*"], + "kbn_references": [] +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 3d3f2fd964a06f..fd0601d9416fe1 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -714,6 +714,8 @@ "@kbn/eslint-plugin-disable/*": ["packages/kbn-eslint-plugin-disable/*"], "@kbn/eslint-plugin-eslint": ["packages/kbn-eslint-plugin-eslint"], "@kbn/eslint-plugin-eslint/*": ["packages/kbn-eslint-plugin-eslint/*"], + "@kbn/eslint-plugin-i18n": ["packages/kbn-eslint-plugin-i18n"], + "@kbn/eslint-plugin-i18n/*": ["packages/kbn-eslint-plugin-i18n/*"], "@kbn/eslint-plugin-imports": ["packages/kbn-eslint-plugin-imports"], "@kbn/eslint-plugin-imports/*": ["packages/kbn-eslint-plugin-imports/*"], "@kbn/eslint-plugin-telemetry": ["packages/kbn-eslint-plugin-telemetry"], diff --git a/yarn.lock b/yarn.lock index d0fcadff0f1b64..d704bf985e9ada 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4366,6 +4366,10 @@ version "0.0.0" uid "" +"@kbn/eslint-plugin-i18n@link:packages/kbn-eslint-plugin-i18n": + version "0.0.0" + uid "" + "@kbn/eslint-plugin-imports@link:packages/kbn-eslint-plugin-imports": version "0.0.0" uid "" From c77f30f64a3820b80b1a243d5440857fd9a2a54c Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 16 Oct 2023 12:35:34 -0400 Subject: [PATCH 12/87] [Fleet] Enable package filtering in serverless using an exclude list (#167445) --- config/serverless.oblt.yml | 17 ++++++++++++++--- config/serverless.security.yml | 16 +++++++++++++--- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/config/serverless.oblt.yml b/config/serverless.oblt.yml index cd180cb3829fa5..ed011cd90063a1 100644 --- a/config/serverless.oblt.yml +++ b/config/serverless.oblt.yml @@ -27,10 +27,21 @@ xpack.apm.serverlessOnboarding: true # Fleet specific configuration xpack.fleet.internal.registry.capabilities: ['apm', 'observability'] +xpack.fleet.internal.registry.kibanaVersionCheckEnabled: false xpack.fleet.internal.registry.spec.max: '3.0' -# Disabled until packages implement the new spec https://github.com/elastic/kibana/issues/166742 -# xpack.fleet.internal.registry.kibanaVersionCheckEnabled: false -# xpack.fleet.internal.registry.spec.min: '3.0' +# Temporary until all packages implement new spec https://github.com/elastic/kibana/issues/166742 +xpack.fleet.internal.registry.spec.min: '1.0' +xpack.fleet.internal.registry.excludePackages: [ + # Security integrations + 'endpoint', + 'beaconing', + 'osquery_manager', + # Removed in 8.11 integrations + 'cisco', + 'microsoft', + 'symantec', + 'cyberark', + ] ## Required for force installation of APM Package xpack.fleet.packages: diff --git a/config/serverless.security.yml b/config/serverless.security.yml index 1d3e83c76202ae..d5edac4507c5d3 100644 --- a/config/serverless.security.yml +++ b/config/serverless.security.yml @@ -37,9 +37,19 @@ telemetry.labels.serverless: security # Fleet specific configuration xpack.fleet.internal.registry.capabilities: ['security'] xpack.fleet.internal.registry.spec.max: '3.0' -# Disabled until packages implement the new spec https://github.com/elastic/kibana/issues/166742 -# xpack.fleet.internal.registry.kibanaVersionCheckEnabled: false -# xpack.fleet.internal.registry.spec.min: '3.0' +xpack.fleet.internal.registry.kibanaVersionCheckEnabled: false +# Temporary until all packages implement new spec https://github.com/elastic/kibana/issues/166742 +xpack.fleet.internal.registry.spec.min: '1.0' +xpack.fleet.internal.registry.excludePackages: [ + # Oblt integrations + 'apm', + 'synthetics', + # Removed in 8.11 integrations + 'cisco', + 'microsoft', + 'symantec', + 'cyberark', + ] xpack.ml.ad.enabled: true xpack.ml.dfa.enabled: true From 6851bb848a9bec5ef3c18754d0f0d291858e4228 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Mon, 16 Oct 2023 18:54:57 +0200 Subject: [PATCH 13/87] [AO] Fix TestQuery button for Elasticsearch rule under Observability with ES|QL (#168703) ## Summary It fixes #168702 Screenshot 2023-10-12 at 14 46 55 --- x-pack/plugins/observability/kibana.jsonc | 30 +++++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/observability/kibana.jsonc b/x-pack/plugins/observability/kibana.jsonc index bdb4c3ca2949e9..467c31969c28a7 100644 --- a/x-pack/plugins/observability/kibana.jsonc +++ b/x-pack/plugins/observability/kibana.jsonc @@ -6,7 +6,10 @@ "id": "observability", "server": true, "browser": true, - "configPath": ["xpack", "observability"], + "configPath": [ + "xpack", + "observability" + ], "requiredPlugins": [ "aiops", "alerting", @@ -32,9 +35,26 @@ "unifiedSearch", "visualizations", "dashboard", + "expressions" + ], + "optionalPlugins": [ + "discover", + "home", + "licensing", + "usageCollection", + "cloud", + "spaces" + ], + "requiredBundles": [ + "data", + "kibanaReact", + "kibanaUtils", + "unifiedSearch", + "stackAlerts", + "spaces" ], - "optionalPlugins": ["discover", "home", "licensing", "usageCollection", "cloud", "spaces"], - "requiredBundles": ["data", "kibanaReact", "kibanaUtils", "unifiedSearch", "stackAlerts", "spaces"], - "extraPublicDirs": ["common"] + "extraPublicDirs": [ + "common" + ] } -} +} \ No newline at end of file From 9080836d6ae882b7287e9bb3cdbd6ac3191e6704 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Mon, 16 Oct 2023 11:59:51 -0500 Subject: [PATCH 14/87] Revert "Introducing "tiered dependencies" in observability plugins (#166524)" This reverts commit e6a389f4c3040b67438ce655825ba0a5e8bab560. --- .../dev_docs/how-we-manage-dependencies.md | 70 ------------------- 1 file changed, 70 deletions(-) delete mode 100644 x-pack/plugins/observability_shared/dev_docs/how-we-manage-dependencies.md diff --git a/x-pack/plugins/observability_shared/dev_docs/how-we-manage-dependencies.md b/x-pack/plugins/observability_shared/dev_docs/how-we-manage-dependencies.md deleted file mode 100644 index 5cd525e97954f9..00000000000000 --- a/x-pack/plugins/observability_shared/dev_docs/how-we-manage-dependencies.md +++ /dev/null @@ -1,70 +0,0 @@ -# Dependency Management in Observability Kibana - -Our goal in observability is to provide as seamless of an experience as possible for our observability users, especially when it comes to navigating between areas owned by different teams. In Kibana, these different teams each own their own experiences inside of a Kibana plugin that provides a public UI interface and, optionally, a back-end server interface. As these plugins begin to share more components, utilities, data clients, and more, the Kibana architecture requires them to depend on each other using runtime dependencies. These dependencies can only be single-direction, which severely limits the types of sharing our plugins can do with one another. - -## Problem summary - -For years, the APM plugin has declared a single-direction runtime dependency on the Infra plugin, allowing APM to make use of components and utilities made available by Infra. Because of this existing dependency, the infra plugin can never make use of similar shared items that could be made available from APM. As Logs+ grows and evolves, Synthetics and Profiling both continue to grow beyond GA, and Elastic begins to fully embrace a unified Observability user experience, we expect this problem to multiply quickly. - -To solve this problem, we need a clear approach for how to organize plugins, packages, and the dependencies between them. - -## Plan summary - -This is the plan we aim to follow, summarized. More details about this plan are found below. - -1. **Resist over-abstraction, but abstract when needed.** If something doesn't need to be shared yet, it's not necessarily good to break it out into its own plugin _or_ package. That said, we will need to break items out of our end user plugins and/or rearrange them, and we shouldn't be scared of doing this because of longtime technical limitations. - - TODO: Add information about possible Kibana event system to consider as a first sharing step, prior to abstraction. -1. **Prefer packages to plugins.** A stateless package is easier to bootstrap, test, and maintain in most cases. If you don't need access to stateful dependencies from core or other plugins, or if you can accept a reasonable number of injected dependencies, make a package. - - TODO: Add link to docs/examples of how to make a Kibana package - - TODO: Add more clarity on the trade-offs between plugin vs package -1. **If you need to make a new plugin, be sure to carefully consider the plugin tiers and how your new plugin will fit.**. In most cases, we should avoid new plugins (with the exception of data access plugins which should only depend on Kibana core.) -1. **Never introduce or add to existing dependencies between plugins in the same tier.** This is the main problem we need to avoid, especially between end user plugins. - -## Plugin tier system - -The system we'll embrace revolves around a "tier system" to help us organize different types of plugins. The plugin tiers look like this: - -Screenshot 2023-09-14 at 3 27 56 PM - -Within this system, a plugin in any tier may ONLY introduce dependencies on other plugins that are in a tier below theirs. They may NOT depend on plugins in the same tier or in tiers above their own. Packages, on the other hand, may be depended on from _any_ plugin, as well as from _any other_ package. - -**Note:** Tiers are NOT currently enforced by any lint rule or other rule. Tiers are a convention that allow us to structure our code in such a way as to avoid the circular dependency problem, but they require manual enforcement via code review. In the near future, we should explore simple ways to codify and enforce this system, either in linting rules, Kibana bundling enforcement, precommit hooks, etc. - -### Tier 1: End user tier - -End user plugins are the plugins that provide visible sections of the Observability UI in Kibana. Each of these plugins may provide one or more navigational areas inside of the Observability product, and they each may provide one or more Kibana server APIs as well. - -These plugins should stop introducing dependencies on each other immediately, and should also stop introducing new functionality that relies on existing dependencies immediately, as well. As soon as possible, existing dependencies between these plugins should be removed and replaced with extracted functionality. - -Screenshot 2023-09-14 at 3 32 17 PM - -### Tier 2: Share tier - -"Share plugins" provide shared functionality (UI components, utility functions, shared logic, etc.) that can be used by multiple end user plugins. Being plugins, they still take advantage of the Kibana runtime lifecycle (setup, start, stop) and have access to Kibana's core functionality and core plugin system. - -This tier is where we would move any shared items, business logic, and stateful dependencies that need access to the plugin lifecycle and, for whatever reason, can't or don't want to accept runtime dependencies as injected parameters. These share plugins can make use of the core-only plugins that typically provide encapsulated access to observability data of other kinds. - -Screenshot 2023-09-14 at 3 32 25 PM - -### Tier 3: Core-only tier (aka data access tier) - -This tier is for plugins that ONLY depend on Kibana core functionality such as scoped ES clients, saved object clients, etc. The main examples of these for now are the new "data access client" plugins which encapsulate the logic for accessing our various types of signal data in observability. By keeping this tier isolated from the other code and only allowing for it to depend on Kibana core, we make data access safely available to any other plugin in the end user or share tiers. - -Screenshot 2023-09-14 at 3 32 30 PM - -### Core: Kibana core - -Anything made available by Kibana core, either in the CoreSetup, CoreStart, or one of the core-maintained plugins such as saved objects, etc. is fair game as a dependency of any observability plugin in any tier. - -### Packages - -Kibana packages are stateless and therefore can be imported into any plugin in any tier. If your shareable item is stateless, or if it can be simply built to accept strongly-typed items using dependency injection, using a package is almost always the best choice. - -## Putting it all together - -Screenshot 2023-09-14 at 3 37 35 PM - -With the exception of package dependencies, all plugin-to-plugin dependencies may only flow _downward_ in the tier diagram. - -Screenshot 2023-09-14 at 3 37 42 PM - From eef222f1347bc0de0c199f6ad8bc14aefd5c8dea Mon Sep 17 00:00:00 2001 From: Kyle Pollich Date: Mon, 16 Oct 2023 13:04:59 -0400 Subject: [PATCH 15/87] [Fleet] Add new keep_monitoring_alive flag to agent policies (#168865) ## Summary Ref https://github.com/elastic/kibana/issues/168629 Adds a new `keep_monitoring_alive` flag to agent policies that allows agent environments to keep the monitoring server if they choose. > [!note] > `monitoring_enabled: []` needs to be explicitly set for this flag to be honored. If `monitoring_enabled` is omitted entirely, Fleet defaults to enabling monitoring for logs and metrics. ## To test Create a preconfigured policy where logs/metrics monitoring is explicitly disabled and include this new flag e.g. ```yml xpack.fleet.agentPolicies: - name: Test preconfigured policy id: test-preconfigured-policy package_policies: [] monitoring_enabled: [] keep_monitoring_alive: true ``` Then, run Kibana and verify the `monitoring` block in the full agent policy has monitoring enabled, but logs/metrics as disabled, e.g. ![image](https://github.com/elastic/kibana/assets/6766512/f5b205ad-96f0-4e88-967a-43546bf2bf84) You can also verify the need for `monitoring_enabled: []` by creating another preconfigured policy e.g. ```yml - name: Test preconfigured policy 2 id: test-preconfigured-policy-2 package_policies: [] keep_monitoring_alive: true ``` This will generate a policy e.g. ![image](https://github.com/elastic/kibana/assets/6766512/013b0381-b605-49a4-8819-3dec713f1e1f) All other combinations of enabling monitoring for logs/metrics should also generate the policies as expected. If you want to verify every combination manually: ```yml xpack.fleet.agentPolicies: - name: Test preconfigured policy id: test-preconfigured-policy package_policies: [] monitoring_enabled: [] keep_monitoring_alive: true - name: Test preconfigured policy 2 id: test-preconfigured-policy-2 package_policies: [] keep_monitoring_alive: true - name: Test preconfigured policy 3 id: test-preconfigured-policy-3 package_policies: [] monitoring_enabled: ['logs'] - name: Test preconfigured policy 4 id: test-preconfigured-policy-4 package_policies: [] monitoring_enabled: ['metrics'] - name: Test preconfigured policy 5 id: test-preconfigured-policy-5 package_policies: [] monitoring_enabled: ['logs', 'metrics'] ``` --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- docs/settings/fleet-settings.asciidoc | 2 + .../current_mappings.json | 203 +++++++++--------- .../group2/check_registered_types.test.ts | 2 +- .../plugins/fleet/common/openapi/bundled.json | 5 + .../plugins/fleet/common/openapi/bundled.yaml | 6 + .../components/schemas/agent_policy.yaml | 4 + .../fleet/common/types/models/agent_policy.ts | 17 +- .../fleet/server/saved_objects/index.ts | 1 + .../agent_policies/full_agent_policy.test.ts | 14 ++ .../agent_policies/full_agent_policy.ts | 46 +++- .../fleet/server/types/models/agent_policy.ts | 1 + 11 files changed, 182 insertions(+), 119 deletions(-) diff --git a/docs/settings/fleet-settings.asciidoc b/docs/settings/fleet-settings.asciidoc index 0960937564b7d0..a222e4e5af5789 100644 --- a/docs/settings/fleet-settings.asciidoc +++ b/docs/settings/fleet-settings.asciidoc @@ -95,6 +95,8 @@ List of agent policies that are configured when the {fleet} app starts. String identifying this policy's namespace. `monitoring_enabled`::: List of keywords that specify the monitoring data to collect. Valid values include `['logs']`, `['metrics']`, and `['logs', 'metrics']`. + `keep_monitoring_alive`::: + If `true`, monitoring will be enabled, but logs/metrics collection will be disabled. Use this if you want to keep agent's monitoring server alive even when logs/metrics aren't being collected. `is_managed`::: If `true`, this policy is not editable by the user and can only be changed by updating the {kib} config. `is_default`::: diff --git a/packages/kbn-check-mappings-update-cli/current_mappings.json b/packages/kbn-check-mappings-update-cli/current_mappings.json index 4ebb8065dbe1df..7fc18bb58a00b5 100644 --- a/packages/kbn-check-mappings-update-cli/current_mappings.json +++ b/packages/kbn-check-mappings-update-cli/current_mappings.json @@ -1645,6 +1645,9 @@ "overrides": { "type": "flattened", "index": false + }, + "keep_monitoring_alive": { + "type": "boolean" } } }, @@ -2594,6 +2597,106 @@ "dynamic": false, "properties": {} }, + "infrastructure-ui-source": { + "dynamic": false, + "properties": {} + }, + "inventory-view": { + "dynamic": false, + "properties": {} + }, + "metrics-explorer-view": { + "dynamic": false, + "properties": {} + }, + "upgrade-assistant-reindex-operation": { + "dynamic": false, + "properties": { + "indexName": { + "type": "keyword" + }, + "status": { + "type": "integer" + } + } + }, + "upgrade-assistant-ml-upgrade-operation": { + "dynamic": false, + "properties": { + "snapshotId": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + }, + "monitoring-telemetry": { + "properties": { + "reportedClusterUuids": { + "type": "keyword" + } + } + }, + "apm-telemetry": { + "dynamic": false, + "properties": {} + }, + "apm-server-schema": { + "properties": { + "schemaJson": { + "type": "text", + "index": false + } + } + }, + "apm-service-group": { + "properties": { + "groupName": { + "type": "keyword" + }, + "kuery": { + "type": "text" + }, + "description": { + "type": "text" + }, + "color": { + "type": "text" + } + } + }, + "apm-custom-dashboards": { + "properties": { + "dashboardSavedObjectId": { + "type": "keyword" + }, + "kuery": { + "type": "text" + }, + "serviceEnvironmentFilterEnabled": { + "type": "boolean" + }, + "serviceNameFilterEnabled": { + "type": "boolean" + } + } + }, + "enterprise_search_telemetry": { + "dynamic": false, + "properties": {} + }, + "app_search_telemetry": { + "dynamic": false, + "properties": {} + }, + "workplace_search_telemetry": { + "dynamic": false, + "properties": {} + }, "siem-ui-timeline-note": { "properties": { "eventId": { @@ -3055,105 +3158,5 @@ "index": false } } - }, - "infrastructure-ui-source": { - "dynamic": false, - "properties": {} - }, - "inventory-view": { - "dynamic": false, - "properties": {} - }, - "metrics-explorer-view": { - "dynamic": false, - "properties": {} - }, - "upgrade-assistant-reindex-operation": { - "dynamic": false, - "properties": { - "indexName": { - "type": "keyword" - }, - "status": { - "type": "integer" - } - } - }, - "upgrade-assistant-ml-upgrade-operation": { - "dynamic": false, - "properties": { - "snapshotId": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } - }, - "monitoring-telemetry": { - "properties": { - "reportedClusterUuids": { - "type": "keyword" - } - } - }, - "apm-telemetry": { - "dynamic": false, - "properties": {} - }, - "apm-server-schema": { - "properties": { - "schemaJson": { - "type": "text", - "index": false - } - } - }, - "apm-service-group": { - "properties": { - "groupName": { - "type": "keyword" - }, - "kuery": { - "type": "text" - }, - "description": { - "type": "text" - }, - "color": { - "type": "text" - } - } - }, - "apm-custom-dashboards": { - "properties": { - "dashboardSavedObjectId": { - "type": "keyword" - }, - "kuery": { - "type": "text" - }, - "serviceEnvironmentFilterEnabled": { - "type": "boolean" - }, - "serviceNameFilterEnabled": { - "type": "boolean" - } - } - }, - "enterprise_search_telemetry": { - "dynamic": false, - "properties": {} - }, - "app_search_telemetry": { - "dynamic": false, - "properties": {} - }, - "workplace_search_telemetry": { - "dynamic": false, - "properties": {} } } 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 01794d226e3125..62780b66727efc 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 @@ -104,7 +104,7 @@ describe('checking migration metadata changes on all registered SO types', () => "index-pattern": "997108a9ea1e8076e22231e1c95517cdb192b9c5", "infrastructure-monitoring-log-view": "5f86709d3c27aed7a8379153b08ee5d3d90d77f5", "infrastructure-ui-source": "113182d6895764378dfe7fa9fa027244f3a457c4", - "ingest-agent-policies": "f11cc19275f4c3e4ee7c5cd6423b6706b21b989d", + "ingest-agent-policies": "7633e578f60c074f8267bc50ec4763845e431437", "ingest-download-sources": "279a68147e62e4d8858c09ad1cf03bd5551ce58d", "ingest-outputs": "b4e636b13a5d0f89f0400fb67811d4cca4736eb0", "ingest-package-policies": "a0c9fb48e04dcd638e593db55f1c6451523f90ea", diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index 509a598a62ad4c..e260764d57de85 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -7036,6 +7036,11 @@ ] } }, + "keep_monitoring_alive": { + "description": "When set to true, monitoring will be enabled but logs/metrics collection will be disabled", + "type": "boolean", + "nullable": true + }, "data_output_id": { "type": "string", "nullable": true diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index 7f43bb2e3b710b..9ed380d26726b1 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -4491,6 +4491,12 @@ components: enum: - metrics - logs + keep_monitoring_alive: + description: >- + When set to true, monitoring will be enabled but logs/metrics + collection will be disabled + type: boolean + nullable: true data_output_id: type: string nullable: true diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy.yaml index ac29a287b91c89..251f76fad966fb 100644 --- a/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy.yaml +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_policy.yaml @@ -16,6 +16,10 @@ properties: enum: - metrics - logs + keep_monitoring_alive: + description: When set to true, monitoring will be enabled but logs/metrics collection will be disabled + type: boolean + nullable: true data_output_id: type: string nullable: true diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index a653bbfb8b2238..4e5d6250208a5d 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -52,6 +52,7 @@ export interface AgentPolicy extends Omit { revision: number; agents?: number; is_protected: boolean; + keep_monitoring_alive?: boolean; } export interface FullAgentPolicyInputStream { @@ -87,6 +88,14 @@ export type FullAgentPolicyOutput = Pick [key: string]: any; }; +export interface FullAgentPolicyMonitoring { + namespace?: string; + use_output?: string; + enabled: boolean; + metrics: boolean; + logs: boolean; +} + export interface FullAgentPolicy { id: string; outputs: { @@ -103,13 +112,7 @@ export interface FullAgentPolicy { inputs: FullAgentPolicyInput[]; revision?: number; agent?: { - monitoring: { - namespace?: string; - use_output?: string; - enabled: boolean; - metrics: boolean; - logs: boolean; - }; + monitoring: FullAgentPolicyMonitoring; download: { sourceURI: string }; features: Record; protection?: { diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index 9bf37677ae9055..8791d9871982b5 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -147,6 +147,7 @@ const getSavedObjectTypes = (): { [key: string]: SavedObjectsType } => ({ }, is_protected: { type: 'boolean' }, overrides: { type: 'flattened', index: false }, + keep_monitoring_alive: { type: 'boolean' }, }, }, migrations: { diff --git a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts index 050b5f983c794b..d9bf271210bc9b 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts +++ b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.test.ts @@ -283,6 +283,20 @@ describe('getFullAgentPolicy', () => { }); }); + it('should return a policy with monitoring enabled but no logs/metrics if keep_monitoring_alive is true', async () => { + mockAgentPolicy({ + keep_monitoring_alive: true, + }); + + const agentPolicy = await getFullAgentPolicy(savedObjectsClientMock.create(), 'agent-policy'); + + expect(agentPolicy?.agent?.monitoring).toEqual({ + enabled: true, + logs: false, + metrics: false, + }); + }); + it('should get the permissions for monitoring', async () => { mockAgentPolicy({ namespace: 'testnamespace', diff --git a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts index 2cdd04483e108e..d15e7adb9bd7fc 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts @@ -18,7 +18,11 @@ import type { FleetProxy, FleetServerHost, } from '../../types'; -import type { FullAgentPolicyOutputPermissions, PackageInfo } from '../../../common/types'; +import type { + FullAgentPolicyMonitoring, + FullAgentPolicyOutputPermissions, + PackageInfo, +} from '../../../common/types'; import { agentPolicyService } from '../agent_policy'; import { dataTypes, kafkaCompressionType, outputType } from '../../../common/constants'; import { DEFAULT_OUTPUT } from '../../constants'; @@ -105,6 +109,35 @@ export async function getFullAgentPolicy( acc[name] = featureConfig; return acc; }, {} as NonNullable['features']); + + const defaultMonitoringConfig: FullAgentPolicyMonitoring = { + enabled: false, + logs: false, + metrics: false, + }; + + let monitoring: FullAgentPolicyMonitoring = { ...defaultMonitoringConfig }; + + // If the agent policy has monitoring enabled for at least one of "logs" or "metrics", generate + // a monitoring config for the resulting compiled agent policy + if (agentPolicy.monitoring_enabled && agentPolicy.monitoring_enabled.length > 0) { + monitoring = { + namespace: agentPolicy.namespace, + use_output: getOutputIdForAgentPolicy(monitoringOutput), + enabled: true, + logs: agentPolicy.monitoring_enabled.includes(dataTypes.Logs), + metrics: agentPolicy.monitoring_enabled.includes(dataTypes.Metrics), + }; + // If the `keep_monitoring_alive` flag is set, enable monitoring but don't enable logs or metrics. + // This allows cloud or other environments to keep the monitoring server alive without tearing it down. + } else if (agentPolicy.keep_monitoring_alive) { + monitoring = { + enabled: true, + logs: false, + metrics: false, + }; + } + const fullAgentPolicy: FullAgentPolicy = { id: agentPolicy.id, outputs: { @@ -128,16 +161,7 @@ export async function getFullAgentPolicy( sourceURI: downloadSourceUri, ...(downloadSourceProxyUri ? { proxy_url: downloadSourceProxyUri } : {}), }, - monitoring: - agentPolicy.monitoring_enabled && agentPolicy.monitoring_enabled.length > 0 - ? { - namespace: agentPolicy.namespace, - use_output: getOutputIdForAgentPolicy(monitoringOutput), - enabled: true, - logs: agentPolicy.monitoring_enabled.includes(dataTypes.Logs), - metrics: agentPolicy.monitoring_enabled.includes(dataTypes.Metrics), - } - : { enabled: false, logs: false, metrics: false }, + monitoring, features, protection: { enabled: agentPolicy.is_protected, diff --git a/x-pack/plugins/fleet/server/types/models/agent_policy.ts b/x-pack/plugins/fleet/server/types/models/agent_policy.ts index 0fb27475c0779e..9b7e0d779cd9cf 100644 --- a/x-pack/plugins/fleet/server/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/server/types/models/agent_policy.ts @@ -35,6 +35,7 @@ export const AgentPolicyBaseSchema = { schema.oneOf([schema.literal(dataTypes.Logs), schema.literal(dataTypes.Metrics)]) ) ), + keep_monitoring_alive: schema.maybe(schema.boolean({ defaultValue: false })), data_output_id: schema.maybe(schema.nullable(schema.string())), monitoring_output_id: schema.maybe(schema.nullable(schema.string())), download_source_id: schema.maybe(schema.nullable(schema.string())), From b3e66b1e0abfbf10e51bd77abcdf2bb7e3c1e622 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 16 Oct 2023 21:04:22 +0200 Subject: [PATCH 16/87] [Synthetics] Unskip test now mode e2e test (#168932) --- x-pack/plugins/synthetics/e2e/synthetics/journeys/index.ts | 2 +- .../e2e/synthetics/journeys/test_now_mode.journey.ts | 4 ++-- .../common/monitor_test_result/step_duration_text.tsx | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/synthetics/e2e/synthetics/journeys/index.ts b/x-pack/plugins/synthetics/e2e/synthetics/journeys/index.ts index 63f460ec567711..40418a55e8d8eb 100644 --- a/x-pack/plugins/synthetics/e2e/synthetics/journeys/index.ts +++ b/x-pack/plugins/synthetics/e2e/synthetics/journeys/index.ts @@ -18,7 +18,7 @@ export * from './alerting_default.journey'; export * from './global_parameters.journey'; export * from './detail_flyout'; // export * from './alert_rules/default_status_alert.journey'; -// export * from './test_now_mode.journey'; +export * from './test_now_mode.journey'; // export * from './data_retention.journey'; export * from './monitor_details_page/monitor_summary.journey'; export * from './test_run_details.journey'; diff --git a/x-pack/plugins/synthetics/e2e/synthetics/journeys/test_now_mode.journey.ts b/x-pack/plugins/synthetics/e2e/synthetics/journeys/test_now_mode.journey.ts index 3c99b173f781f0..9df533b4df2ed3 100644 --- a/x-pack/plugins/synthetics/e2e/synthetics/journeys/test_now_mode.journey.ts +++ b/x-pack/plugins/synthetics/e2e/synthetics/journeys/test_now_mode.journey.ts @@ -31,7 +31,7 @@ journey(`TestNowMode`, async ({ page, params }) => { if ( evt.resourceType() === 'fetch' && (evt.url().includes('service/monitors/trigger/') || - evt.url().includes('uptime/service/monitors/run_once')) + evt.url().includes('synthetics/service/monitors/run_once')) ) { evt .response() @@ -139,7 +139,7 @@ journey(`TestNowMode`, async ({ page, params }) => { await page.waitForSelector( '.euiTableRowCell--hideForMobile :has-text("Go to https://www.google.com")' ); - await page.waitForSelector('.euiTableRowCell--hideForMobile :has-text("1.42 s")'); + expect(await page.getByTestId('stepDurationText1').first()).toHaveText('1.4 sec'); await page.waitForSelector('text=Complete'); }); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/step_duration_text.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/step_duration_text.tsx index 68f5d919f90e32..7bee1f0d018876 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/step_duration_text.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/step_duration_text.tsx @@ -29,7 +29,11 @@ export const StepDurationText = ({ step }: { step: JourneyStep }) => { }, [euiTheme.colors, step.synthetics.step?.duration?.us, step.synthetics.step?.status]); return ( - + {stepDuration.text} ); From 0b8a2d51e873c83f7064914cf9c32c3ac1ef0b86 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 16 Oct 2023 20:09:52 +0100 Subject: [PATCH 17/87] skip flaky suite (#168899) --- .../apps/ml/short_tests/model_management/model_list.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/ml/short_tests/model_management/model_list.ts b/x-pack/test/functional/apps/ml/short_tests/model_management/model_list.ts index 9ae541c834714a..c8b0e76a2071b5 100644 --- a/x-pack/test/functional/apps/ml/short_tests/model_management/model_list.ts +++ b/x-pack/test/functional/apps/ml/short_tests/model_management/model_list.ts @@ -453,7 +453,8 @@ export default function ({ getService }: FtrProviderContext) { await ml.navigation.navigateToTrainedModels(); }); - describe('with imported models', function () { + // FLAKY: https://github.com/elastic/kibana/issues/168899 + describe.skip('with imported models', function () { before(async () => { await ml.navigation.navigateToTrainedModels(); }); From b69c619c2eb2fade5d6bccf5136de2f3d5e04528 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Mon, 16 Oct 2023 12:10:45 -0700 Subject: [PATCH 18/87] [DOCS] Automate more anomaly detection rule screenshots (#168900) --- .../generate_anomaly_alerts.ts | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/generate_anomaly_alerts.ts b/x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/generate_anomaly_alerts.ts index 57bae974ce273b..cec6ed8528a10e 100644 --- a/x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/generate_anomaly_alerts.ts +++ b/x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/generate_anomaly_alerts.ts @@ -123,6 +123,18 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 1920, 1400 ); + await ml.alerting.selectSlackConnectorType(); + await ml.testExecution.logTestStep('should open connectors'); + await ml.alerting.clickCreateConnectorButton(); + await ml.alerting.setConnectorName('test-connector'); + await ml.alerting.setWebhookUrl('https://www.elastic.co'); + await ml.alerting.clickSaveActionButton(); + await commonScreenshots.takeScreenshot( + 'ml-health-check-action', + screenshotDirectories, + 1920, + 1400 + ); await ml.alerting.clickCancelSaveRuleButton(); await pageObjects.triggersActionsUI.clickCreateAlertButton(); @@ -150,12 +162,13 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 1920, 1400 ); - await ml.alerting.selectSlackConnectorType(); - await ml.testExecution.logTestStep('should open connectors'); - await ml.alerting.clickCreateConnectorButton(); - await ml.alerting.setConnectorName('test-connector'); - await ml.alerting.setWebhookUrl('https://www.elastic.co'); - await ml.alerting.clickSaveActionButton(); + await testSubjects.click('.slack-alerting-ActionTypeSelectOption'); + await commonScreenshots.takeScreenshot( + 'ml-anomaly-alert-action-score-matched', + screenshotDirectories, + 1920, + 1400 + ); await ml.alerting.openAddRuleVariable(); await ml.testExecution.logTestStep('take screenshot'); await commonScreenshots.takeScreenshot( @@ -164,6 +177,16 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 1920, 1400 ); + const actionFrequency = await testSubjects.find('summaryOrPerRuleSelect'); + await actionFrequency.click(); + const actionSummary = await testSubjects.find('actionNotifyWhen-option-summary'); + await actionSummary.click(); + await commonScreenshots.takeScreenshot( + 'ml-anomaly-alert-action-summary', + screenshotDirectories, + 1920, + 1400 + ); }); }); }); From 3cbf42e01a94bdb85d0676dbddcbdd90548f4634 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 16 Oct 2023 20:21:10 +0100 Subject: [PATCH 19/87] skip flaky suite (#165084) --- .../apps/ml/short_tests/model_management/model_list.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/ml/short_tests/model_management/model_list.ts b/x-pack/test/functional/apps/ml/short_tests/model_management/model_list.ts index c8b0e76a2071b5..7d3cf599558f4c 100644 --- a/x-pack/test/functional/apps/ml/short_tests/model_management/model_list.ts +++ b/x-pack/test/functional/apps/ml/short_tests/model_management/model_list.ts @@ -17,7 +17,8 @@ export default function ({ getService }: FtrProviderContext) { id: model.name, })); - describe('trained models', function () { + // FLAKY: https://github.com/elastic/kibana/issues/165084 + describe.skip('trained models', function () { // 'Created at' will be different on each run, // so we will just assert that the value is in the expected timestamp format. const builtInModelData = { From 48bb5ae6797fd58f5c4076df583b32060572ca66 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Mon, 16 Oct 2023 13:55:39 -0600 Subject: [PATCH 20/87] [SLO] Fix SLO burn rate rule to call `alertWithLifecycle` before `getAlertUuid` (#169004) ## Summary This PR fixes #168962 by calling `alertWithLifecycle` before `getAlertUuid`. When `getAlertUuid` is called first it will generate a UUID which is not associated with the actual alert. When you call `alertWithLifecycle`, it generates the Alert then stores the `alertUuid` that maps the `alertId` to the `alertUuid`; `getAlertUuid` tries to recall this association but falls back to generating a UUID. I had to change the way the test worked by modifying mock's behavior to match the implementation; once I had a test that failed similarly to what we see in the real world, I fixed the issue by changing the implementation to call `alertWithLifecycle` first Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../lib/rules/slo_burn_rate/executor.test.ts | 24 +++++++++---------- .../lib/rules/slo_burn_rate/executor.ts | 24 +++++++++---------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.test.ts b/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.test.ts index 47277a003f393f..0837973ec7ee22 100644 --- a/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.test.ts +++ b/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.test.ts @@ -101,6 +101,8 @@ describe('BurnRateRuleExecutor', () => { let esClientMock: ElasticsearchClientMock; let soClientMock: jest.Mocked; let loggerMock: jest.Mocked; + let alertUuidMap: Map; + let alertMock: Partial; const alertUuid = 'mockedAlertUuid'; const basePathMock = { publicBaseUrl: 'https://kibana.dev' } as IBasePath; const alertsLocatorMock = { @@ -124,9 +126,17 @@ describe('BurnRateRuleExecutor', () => { LifecycleAlertServices; beforeEach(() => { + alertUuidMap = new Map(); + alertMock = { + scheduleActions: jest.fn(), + replaceState: jest.fn(), + }; esClientMock = elasticsearchServiceMock.createElasticsearchClient(); soClientMock = savedObjectsClientMock.create(); - alertWithLifecycleMock = jest.fn(); + alertWithLifecycleMock = jest.fn().mockImplementation(({ id }) => { + alertUuidMap.set(id, alertUuid); + return alertMock as any; + }); alertFactoryMock = { create: jest.fn(), done: jest.fn(), @@ -144,7 +154,7 @@ describe('BurnRateRuleExecutor', () => { shouldWriteAlerts: jest.fn(), shouldStopExecution: jest.fn(), getAlertStartedDate: jest.fn(), - getAlertUuid: jest.fn().mockImplementation(() => alertUuid), + getAlertUuid: jest.fn().mockImplementation((id) => alertUuidMap.get(id) || 'bad-uuid'), getAlertByAlertUuid: jest.fn(), share: {} as SharePluginStart, dataViews: dataViewPluginMocks.createStartContract(), @@ -312,11 +322,6 @@ describe('BurnRateRuleExecutor', () => { esClientMock.search.mockResolvedValueOnce( generateEsResponse(ruleParams, [], { instanceId: 'bar' }) ); - const alertMock: Partial = { - scheduleActions: jest.fn(), - replaceState: jest.fn(), - }; - alertWithLifecycleMock.mockImplementation(() => alertMock as any); alertFactoryMock.done.mockReturnValueOnce({ getRecoveredAlerts: () => [] }); const executor = getRuleExecutor({ @@ -417,11 +422,6 @@ describe('BurnRateRuleExecutor', () => { esClientMock.search.mockResolvedValueOnce( generateEsResponse(ruleParams, [], { instanceId: 'bar' }) ); - const alertMock: Partial = { - scheduleActions: jest.fn(), - replaceState: jest.fn(), - }; - alertWithLifecycleMock.mockImplementation(() => alertMock as any); alertFactoryMock.done.mockReturnValueOnce({ getRecoveredAlerts: () => [] }); const executor = getRuleExecutor({ basePath: basePathMock }); diff --git a/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.ts b/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.ts index 22e5594f0fc199..63c5ede6d7d6ce 100644 --- a/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.ts +++ b/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/executor.ts @@ -120,6 +120,17 @@ export const getRuleExecutor = ({ ); const alertId = instanceId; + const alert = alertWithLifecycle({ + id: alertId, + fields: { + [ALERT_REASON]: reason, + [ALERT_EVALUATION_THRESHOLD]: windowDef.burnRateThreshold, + [ALERT_EVALUATION_VALUE]: Math.min(longWindowBurnRate, shortWindowBurnRate), + [SLO_ID_FIELD]: slo.id, + [SLO_REVISION_FIELD]: slo.revision, + [SLO_INSTANCE_ID_FIELD]: instanceId, + }, + }); const indexedStartedAt = getAlertStartedDate(alertId) ?? startedAt.toISOString(); const alertUuid = getAlertUuid(alertId); const alertDetailsUrl = await getAlertUrl( @@ -143,19 +154,6 @@ export const getRuleExecutor = ({ sloInstanceId: instanceId, }; - const alert = alertWithLifecycle({ - id: alertId, - - fields: { - [ALERT_REASON]: reason, - [ALERT_EVALUATION_THRESHOLD]: windowDef.burnRateThreshold, - [ALERT_EVALUATION_VALUE]: Math.min(longWindowBurnRate, shortWindowBurnRate), - [SLO_ID_FIELD]: slo.id, - [SLO_REVISION_FIELD]: slo.revision, - [SLO_INSTANCE_ID_FIELD]: instanceId, - }, - }); - alert.scheduleActions(windowDef.actionGroup, context); alert.replaceState({ alertState: AlertStates.ALERT }); } From 1d2cd5889df34ac7a04218e38ab0f927ba2d3ab8 Mon Sep 17 00:00:00 2001 From: Rodney Norris Date: Mon, 16 Oct 2023 15:10:00 -0500 Subject: [PATCH 21/87] [Enterprise Search] fix: use full path for search apps nav url (#169014) ## Summary Updated the left nav `to` path for search applications to match the full path so the isActive check can pass instead of used the base path to redirect. ![image](https://github.com/elastic/kibana/assets/1972968/9b8ac4fa-8896-43d5-825c-39f5b38d48ee) --- .../public/applications/shared/layout/nav.test.tsx | 6 +++--- .../public/applications/shared/layout/nav.tsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx index c67a3f877d720d..f68a2eee1c5aff 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx @@ -63,7 +63,7 @@ describe('useEnterpriseSearchContentNav', () => { id: 'applications', items: [ { - href: '/app/enterprise_search/applications', + href: '/app/enterprise_search/applications/search_applications', id: 'searchApplications', name: 'Search Applications', }, @@ -226,7 +226,7 @@ describe('useEnterpriseSearchApplicationNav', () => { id: 'applications', items: [ { - href: '/app/enterprise_search/applications', + href: '/app/enterprise_search/applications/search_applications', id: 'searchApplications', name: 'Search Applications', }, @@ -413,7 +413,7 @@ describe('useEnterpriseSearchAnalyticsNav', () => { id: 'applications', items: [ { - href: '/app/enterprise_search/applications', + href: '/app/enterprise_search/applications/search_applications', id: 'searchApplications', name: 'Search Applications', }, diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx index ed2730a217c72d..8fe9c36766c602 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx @@ -78,7 +78,7 @@ export const useEnterpriseSearchNav = () => { }), ...generateNavLink({ shouldNotCreateHref: true, - to: APPLICATIONS_PLUGIN.URL, + to: APPLICATIONS_PLUGIN.URL + SEARCH_APPLICATIONS_PATH, }), }, { From b61f5709798afdb6cec03ff93e2043e549b3ea9d Mon Sep 17 00:00:00 2001 From: Alex Szabo Date: Mon, 16 Oct 2023 22:17:11 +0200 Subject: [PATCH 22/87] [Ops] Fix missing endquote in ES Serverless generated json (#169024) ## Summary chore: fix missing end quote on generated json for ES Serverless snaphot manifests --- .../scripts/steps/es_serverless/promote_es_serverless_image.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.buildkite/scripts/steps/es_serverless/promote_es_serverless_image.sh b/.buildkite/scripts/steps/es_serverless/promote_es_serverless_image.sh index c15d6011da3e9d..d99cff34f6fbb6 100755 --- a/.buildkite/scripts/steps/es_serverless/promote_es_serverless_image.sh +++ b/.buildkite/scripts/steps/es_serverless/promote_es_serverless_image.sh @@ -76,7 +76,7 @@ if [[ "${PUBLISH_MANIFEST:-}" =~ ^(1|true)$ && "$SOURCE_IMAGE_OR_TAG" =~ ^git-[0 "kibana_commit": "$BUILDKITE_COMMIT", "kibana_branch": "$BUILDKITE_BRANCH", "elasticsearch_serverless_tag": "$SOURCE_IMAGE_OR_TAG", - "elasticsearch_serverless_image_url: "$SOURCE_IMAGE", + "elasticsearch_serverless_image_url": "$SOURCE_IMAGE", "elasticsearch_serverless_commit": "TODO: this currently can't be decided", "elasticsearch_commit": "$ELASTIC_COMMIT_HASH", "created_at": "`date`", From 91435a573f3d61e3793d31687d7c8a4a67237655 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Mon, 16 Oct 2023 14:19:50 -0600 Subject: [PATCH 23/87] Data views, `getExistingIndices` method to server side (#168522) --- src/plugins/data_views/common/constants.ts | 6 ++ .../common/data_views/data_views.test.ts | 32 ------- .../common/data_views/data_views.ts | 43 --------- src/plugins/data_views/common/types.ts | 5 + .../public/data_views_service_public.ts | 19 ++++ src/plugins/data_views/public/plugin.ts | 1 + src/plugins/data_views/public/types.ts | 6 ++ .../fetcher/index_patterns_fetcher.test.ts | 40 +++++++- .../server/fetcher/index_patterns_fetcher.ts | 35 +++++++ .../internal/existing_indices.test.ts | 53 +++++++++++ .../internal/existing_indices.ts | 77 ++++++++++++++++ src/plugins/data_views/server/routes.ts | 2 + .../existing_indices_route/index.ts | 16 ++++ .../existing_indices_route/params.ts | 79 ++++++++++++++++ .../existing_indices_route/response.ts | 46 ++++++++++ test/api_integration/apis/data_views/index.ts | 1 + .../sourcerer/create_sourcerer_data_view.ts | 9 +- .../sourcerer/get_sourcerer_data_view.test.ts | 4 +- .../sourcerer/get_sourcerer_data_view.ts | 4 +- .../existing_indices_route/index.ts | 15 +++ .../existing_indices_route/params.ts | 91 +++++++++++++++++++ .../existing_indices_route/response.ts | 50 ++++++++++ .../test_suites/common/data_views/index.ts | 1 + 23 files changed, 547 insertions(+), 88 deletions(-) create mode 100644 src/plugins/data_views/server/rest_api_routes/internal/existing_indices.test.ts create mode 100644 src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts create mode 100644 test/api_integration/apis/data_views/existing_indices_route/index.ts create mode 100644 test/api_integration/apis/data_views/existing_indices_route/params.ts create mode 100644 test/api_integration/apis/data_views/existing_indices_route/response.ts create mode 100644 x-pack/test_serverless/api_integration/test_suites/common/data_views/existing_indices_route/index.ts create mode 100644 x-pack/test_serverless/api_integration/test_suites/common/data_views/existing_indices_route/params.ts create mode 100644 x-pack/test_serverless/api_integration/test_suites/common/data_views/existing_indices_route/response.ts diff --git a/src/plugins/data_views/common/constants.ts b/src/plugins/data_views/common/constants.ts index 02a05ab2a44d70..dc396f2772aa83 100644 --- a/src/plugins/data_views/common/constants.ts +++ b/src/plugins/data_views/common/constants.ts @@ -57,3 +57,9 @@ export const PLUGIN_NAME = 'DataViews'; * @public */ export const FIELDS_FOR_WILDCARD_PATH = '/internal/data_views/_fields_for_wildcard'; + +/** + * Existing indices path + * @public + */ +export const EXISTING_INDICES_PATH = '/internal/data_views/_existing_indices'; diff --git a/src/plugins/data_views/common/data_views/data_views.test.ts b/src/plugins/data_views/common/data_views/data_views.test.ts index 059c911561e3ef..e95e5c6736d174 100644 --- a/src/plugins/data_views/common/data_views/data_views.test.ts +++ b/src/plugins/data_views/common/data_views/data_views.test.ts @@ -662,36 +662,4 @@ describe('IndexPatterns', () => { expect(apiClient.getFieldsForWildcard.mock.calls[0][0].allowNoIndex).toBe(true); }); }); - - describe('getExistingIndices', () => { - test('getExistingIndices returns the valid matched indices', async () => { - apiClient.getFieldsForWildcard = jest - .fn() - .mockResolvedValueOnce({ fields: ['length'] }) - .mockResolvedValue({ fields: [] }); - const patternList = await indexPatterns.getExistingIndices(['packetbeat-*', 'filebeat-*']); - expect(apiClient.getFieldsForWildcard).toBeCalledTimes(2); - expect(patternList.length).toBe(1); - }); - - test('getExistingIndices checks the positive pattern if provided with a negative pattern', async () => { - const mockFn = jest.fn().mockResolvedValue({ fields: ['length'] }); - apiClient.getFieldsForWildcard = mockFn; - const patternList = await indexPatterns.getExistingIndices(['-filebeat-*', 'filebeat-*']); - expect(mockFn.mock.calls[0][0].pattern).toEqual('filebeat-*'); - expect(mockFn.mock.calls[1][0].pattern).toEqual('filebeat-*'); - expect(patternList).toEqual(['-filebeat-*', 'filebeat-*']); - }); - - test('getExistingIndices handles an error', async () => { - apiClient.getFieldsForWildcard = jest - .fn() - .mockImplementationOnce(async () => { - throw new DataViewMissingIndices('Catch me if you can!'); - }) - .mockImplementation(() => Promise.resolve({ fields: ['length'] })); - const patternList = await indexPatterns.getExistingIndices(['packetbeat-*', 'filebeat-*']); - expect(patternList).toEqual(['filebeat-*']); - }); - }); }); diff --git a/src/plugins/data_views/common/data_views/data_views.ts b/src/plugins/data_views/common/data_views/data_views.ts index 8bac81f19ef628..7ec161e689e76f 100644 --- a/src/plugins/data_views/common/data_views/data_views.ts +++ b/src/plugins/data_views/common/data_views/data_views.ts @@ -7,12 +7,10 @@ */ import { i18n } from '@kbn/i18n'; -import { defer, from } from 'rxjs'; import type { PublicMethodsOf } from '@kbn/utility-types'; import { castEsToKbnFieldTypeName } from '@kbn/field-types'; import { FieldFormatsStartCommon, FORMATS_UI_SETTINGS } from '@kbn/field-formats-plugin/common'; import { v4 as uuidv4 } from 'uuid'; -import { rateLimitingForkJoin } from './utils'; import { PersistenceAPI } from '../types'; import { createDataViewCache } from '.'; @@ -240,12 +238,6 @@ export interface DataViewsServicePublicMethods { * @param options - options for getting fields */ getFieldsForWildcard: (options: GetFieldsOptions) => Promise; - /** - * Get existing index pattern list by providing string array index pattern list. - * @param indices - index pattern list - * @returns index pattern list of index patterns that match indices - */ - getExistingIndices: (indices: string[]) => Promise; /** * Get list of data view ids. * @param refresh - clear cache and fetch from server @@ -524,41 +516,6 @@ export class DataViewsService { return fields; }; - /** - * Get existing index pattern list by providing string array index pattern list. - * @param indices index pattern list - * @returns index pattern list - */ - getExistingIndices = async (indices: string[]): Promise => { - const indicesObs = indices.map((pattern) => { - // when checking a negative pattern, check if the positive pattern exists - const indexToQuery = pattern.trim().startsWith('-') - ? pattern.trim().substring(1) - : pattern.trim(); - return defer(() => - from( - this.getFieldsForWildcard({ - // check one field to keep request fast/small - fields: ['_id'], - // true so no errors thrown in browser - allowNoIndex: true, - pattern: indexToQuery, - }) - ) - ); - }); - - return new Promise((resolve) => { - rateLimitingForkJoin(indicesObs, 3, []).subscribe((value) => { - resolve(value.map((v) => v.length > 0)); - }); - }) - .then((allPatterns: boolean[]) => - indices.filter((pattern, i, self) => self.indexOf(pattern) === i && allPatterns[i]) - ) - .catch(() => indices); - }; - /** * Get field list by providing an index patttern (or spec). * @param options options for getting field list diff --git a/src/plugins/data_views/common/types.ts b/src/plugins/data_views/common/types.ts index 9061c4643dce9d..79a2524a4d80c5 100644 --- a/src/plugins/data_views/common/types.ts +++ b/src/plugins/data_views/common/types.ts @@ -319,6 +319,11 @@ export interface FieldsForWildcardResponse { indices: string[]; } +/** + * Existing Indices response + */ +export type ExistingIndicesResponse = string[]; + export interface IDataViewsApiClient { getFieldsForWildcard: (options: GetFieldsOptions) => Promise; hasUserDataView: () => Promise; diff --git a/src/plugins/data_views/public/data_views_service_public.ts b/src/plugins/data_views/public/data_views_service_public.ts index 565fc8dc167088..71ec3ae0a3d0e5 100644 --- a/src/plugins/data_views/public/data_views_service_public.ts +++ b/src/plugins/data_views/public/data_views_service_public.ts @@ -6,11 +6,15 @@ * Side Public License, v 1. */ +import { HttpStart } from '@kbn/core/public'; import { DataViewsService, MatchedItem } from '.'; import { DataViewsServiceDeps } from '../common/data_views/data_views'; import { HasDataService } from '../common'; +import { ExistingIndicesResponse } from '../common/types'; +import { EXISTING_INDICES_PATH } from '../common/constants'; + /** * Data Views public service dependencies * @public @@ -32,6 +36,7 @@ export interface DataViewsServicePublicDeps extends DataViewsServiceDeps { getRollupsEnabled: () => boolean; scriptedFieldsEnabled: boolean; + http: HttpStart; } /** @@ -48,6 +53,7 @@ export class DataViewsServicePublic extends DataViewsService { }) => Promise; public hasData: HasDataService; private rollupsEnabled: boolean = false; + private readonly http: HttpStart; public readonly scriptedFieldsEnabled: boolean; /** @@ -62,9 +68,22 @@ export class DataViewsServicePublic extends DataViewsService { this.getIndices = deps.getIndices; this.rollupsEnabled = deps.getRollupsEnabled(); this.scriptedFieldsEnabled = deps.scriptedFieldsEnabled; + this.http = deps.http; } getRollupsEnabled() { return this.rollupsEnabled; } + + /** + * Get existing index pattern list by providing string array index pattern list. + * @param indices - index pattern list + * @returns index pattern list of index patterns that match indices + */ + async getExistingIndices(indices: string[]): Promise { + return this.http.get(EXISTING_INDICES_PATH, { + query: { indices }, + version: '1', + }); + } } diff --git a/src/plugins/data_views/public/plugin.ts b/src/plugins/data_views/public/plugin.ts index b6997b107410f7..d00292c3f4fe8c 100644 --- a/src/plugins/data_views/public/plugin.ts +++ b/src/plugins/data_views/public/plugin.ts @@ -88,6 +88,7 @@ export class DataViewsPublicPlugin savedObjectsClient: new ContentMagementWrapper(contentManagement.client), apiClient: new DataViewsApiClient(http), fieldFormats, + http, onNotification: (toastInputFields, key) => { onNotifDebounced(key)(toastInputFields); }, diff --git a/src/plugins/data_views/public/types.ts b/src/plugins/data_views/public/types.ts index 08c8eeb62fc2e9..7d6cbbc6cf5335 100644 --- a/src/plugins/data_views/public/types.ts +++ b/src/plugins/data_views/public/types.ts @@ -123,6 +123,12 @@ export interface DataViewsServicePublic extends DataViewsServicePublicMethods { }) => Promise; getRollupsEnabled: () => boolean; scriptedFieldsEnabled: boolean; + /** + * Get existing index pattern list by providing string array index pattern list. + * @param indices - index pattern list + * @returns index pattern list of index patterns that match indices + */ + getExistingIndices: (indices: string[]) => Promise; } export type DataViewsContract = DataViewsServicePublic; diff --git a/src/plugins/data_views/server/fetcher/index_patterns_fetcher.test.ts b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.test.ts index 6253c68d84fbaf..669a370badebc5 100644 --- a/src/plugins/data_views/server/fetcher/index_patterns_fetcher.test.ts +++ b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.test.ts @@ -9,6 +9,7 @@ import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IndexPatternsFetcher } from '.'; import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; +import { DataViewMissingIndices } from '../../common'; const rollupResponse = { foo: { @@ -34,17 +35,16 @@ describe('Index Pattern Fetcher - server', () => { beforeEach(() => { jest.clearAllMocks(); esClient = elasticsearchServiceMock.createElasticsearchClient(); + esClient.fieldCaps.mockResponse(response as unknown as estypes.FieldCapsResponse); indexPatterns = new IndexPatternsFetcher(esClient, false, true); }); it('calls fieldcaps once', async () => { - esClient.fieldCaps.mockResponse(response as unknown as estypes.FieldCapsResponse); indexPatterns = new IndexPatternsFetcher(esClient, true, true); await indexPatterns.getFieldsForWildcard({ pattern: patternList }); expect(esClient.fieldCaps).toHaveBeenCalledTimes(1); }); it('calls rollup api when given rollup data view', async () => { - esClient.fieldCaps.mockResponse(response as unknown as estypes.FieldCapsResponse); esClient.rollup.getRollupIndexCaps.mockResponse( rollupResponse as unknown as estypes.RollupGetRollupIndexCapsResponse ); @@ -58,7 +58,6 @@ describe('Index Pattern Fetcher - server', () => { }); it("doesn't call rollup api when given rollup data view and rollups are disabled", async () => { - esClient.fieldCaps.mockResponse(response as unknown as estypes.FieldCapsResponse); esClient.rollup.getRollupIndexCaps.mockResponse( rollupResponse as unknown as estypes.RollupGetRollupIndexCapsResponse ); @@ -70,4 +69,39 @@ describe('Index Pattern Fetcher - server', () => { }); expect(esClient.rollup.getRollupIndexCaps).toHaveBeenCalledTimes(0); }); + + describe('getExistingIndices', () => { + test('getExistingIndices returns the valid matched indices', async () => { + indexPatterns = new IndexPatternsFetcher(esClient, true, true); + indexPatterns.getFieldsForWildcard = jest + .fn() + .mockResolvedValueOnce({ indices: ['length'] }) + .mockResolvedValue({ indices: [] }); + const result = await indexPatterns.getExistingIndices(['packetbeat-*', 'filebeat-*']); + expect(indexPatterns.getFieldsForWildcard).toBeCalledTimes(2); + expect(result.length).toBe(1); + }); + + test('getExistingIndices checks the positive pattern if provided with a negative pattern', async () => { + indexPatterns = new IndexPatternsFetcher(esClient, true, true); + const mockFn = jest.fn().mockResolvedValue({ indices: ['length'] }); + indexPatterns.getFieldsForWildcard = mockFn; + const result = await indexPatterns.getExistingIndices(['-filebeat-*', 'filebeat-*']); + expect(mockFn.mock.calls[0][0].pattern).toEqual('filebeat-*'); + expect(mockFn.mock.calls[1][0].pattern).toEqual('filebeat-*'); + expect(result).toEqual(['-filebeat-*', 'filebeat-*']); + }); + + test('getExistingIndices handles an error', async () => { + indexPatterns = new IndexPatternsFetcher(esClient, true, true); + indexPatterns.getFieldsForWildcard = jest + .fn() + .mockImplementationOnce(async () => { + throw new DataViewMissingIndices('Catch me if you can!'); + }) + .mockImplementation(() => Promise.resolve({ indices: ['length'] })); + const result = await indexPatterns.getExistingIndices(['packetbeat-*', 'filebeat-*']); + expect(result).toEqual(['filebeat-*']); + }); + }); }); diff --git a/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts index b1d22dc5523c8d..82f07bd7f489a1 100644 --- a/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts +++ b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts @@ -9,6 +9,8 @@ import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from '@kbn/core/server'; import { keyBy } from 'lodash'; +import { defer, from } from 'rxjs'; +import { rateLimitingForkJoin } from '../../common/data_views/utils'; import type { QueryDslQueryContainer } from '../../common/types'; import { @@ -117,4 +119,37 @@ export class IndexPatternsFetcher { } return fieldCapsResponse; } + + /** + * Get existing index pattern list by providing string array index pattern list. + * @param indices - index pattern list + * @returns index pattern list of index patterns that match indices + */ + async getExistingIndices(indices: string[]): Promise { + const indicesObs = indices.map((pattern) => { + // when checking a negative pattern, check if the positive pattern exists + const indexToQuery = pattern.trim().startsWith('-') + ? pattern.trim().substring(1) + : pattern.trim(); + return defer(() => + from( + this.getFieldsForWildcard({ + // check one field to keep request fast/small + fields: ['_id'], + pattern: indexToQuery, + }) + ) + ); + }); + + return new Promise((resolve) => { + rateLimitingForkJoin(indicesObs, 3, { fields: [], indices: [] }).subscribe((value) => { + resolve(value.map((v) => v.indices.length > 0)); + }); + }) + .then((allPatterns: boolean[]) => + indices.filter((pattern, i, self) => self.indexOf(pattern) === i && allPatterns[i]) + ) + .catch(() => indices); + } } diff --git a/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.test.ts b/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.test.ts new file mode 100644 index 00000000000000..a6ba52f2208e53 --- /dev/null +++ b/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.test.ts @@ -0,0 +1,53 @@ +/* + * 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 { parseIndices } from './existing_indices'; + +describe('parseIndices', () => { + it('should return an array of indices when given an array of indices', () => { + const indices = ['index1', 'index2', 'index3']; + const result = parseIndices(indices); + expect(result).toEqual(indices); + }); + + it('should return an array of indices when given a JSON-stringified array of indices', () => { + const indices = '["index1", "index2", "index3"]'; + const result = parseIndices(indices); + expect(result).toEqual(['index1', 'index2', 'index3']); + }); + + it('should return an array with a single index when given a single index name', () => { + const index = 'index1'; + const result = parseIndices(index); + expect(result).toEqual(['index1']); + }); + + it('should throw an error when given an invalid JSON-stringified array', () => { + const indices = '["index1", "index2"'; + expect(() => { + parseIndices(indices); + }).toThrowError( + 'indices should be an array of index aliases, a JSON-stringified array of index aliases, or a single index alias' + ); + }); + + it('should throw an error when given a string with a comma but not JSON-stringified', () => { + const indices = 'index1,index2'; + expect(() => { + parseIndices(indices); + }).toThrowError( + 'indices should be an array of index aliases, a JSON-stringified array of index aliases, or a single index alias' + ); + }); + + it('should return an empty array when given an empty array', () => { + const indices: string[] = []; + const result = parseIndices(indices); + expect(result).toEqual([]); + }); +}); diff --git a/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts b/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts new file mode 100644 index 00000000000000..a87d993181aae7 --- /dev/null +++ b/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts @@ -0,0 +1,77 @@ +/* + * 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 { IRouter, RequestHandler } from '@kbn/core/server'; +import { schema } from '@kbn/config-schema'; +import { INITIAL_REST_VERSION_INTERNAL as version } from '../../constants'; +import { IndexPatternsFetcher } from '../..'; +import { EXISTING_INDICES_PATH } from '../../../common/constants'; + +/** + * Accepts one of the following: + * 1. An array of field names + * 2. A JSON-stringified array of field names + * 3. A single field name (not comma-separated) + * @returns an array of indices + * @param indices + */ +export const parseIndices = (indices: string | string[]): string[] => { + if (Array.isArray(indices)) return indices; + try { + return JSON.parse(indices); + } catch (e) { + if (!indices.includes(',')) return [indices]; + throw new Error( + 'indices should be an array of index aliases, a JSON-stringified array of index aliases, or a single index alias' + ); + } +}; +export const handler: RequestHandler<{}, { indices: string | string[] }, string[]> = async ( + ctx, + req, + res +) => { + const { indices } = req.query; + try { + const indexArray = parseIndices(indices); + const core = await ctx.core; + const elasticsearchClient = core.elasticsearch.client.asCurrentUser; + const indexPatterns = new IndexPatternsFetcher(elasticsearchClient, true); + + const response: string[] = await indexPatterns.getExistingIndices(indexArray); + return res.ok({ body: response }); + } catch (error) { + return res.badRequest(); + } +}; + +export const registerExistingIndicesPath = (router: IRouter): void => { + router.versioned + .get({ + path: EXISTING_INDICES_PATH, + access: 'internal', + }) + .addVersion( + { + version, + validate: { + request: { + query: schema.object({ + indices: schema.oneOf([schema.string(), schema.arrayOf(schema.string())]), + }), + }, + response: { + 200: { + body: schema.arrayOf(schema.string()), + }, + }, + }, + }, + handler + ); +}; diff --git a/src/plugins/data_views/server/routes.ts b/src/plugins/data_views/server/routes.ts index 9c1da30bc99e72..c77dd9a8236cf0 100644 --- a/src/plugins/data_views/server/routes.ts +++ b/src/plugins/data_views/server/routes.ts @@ -11,6 +11,7 @@ import { UsageCounter } from '@kbn/usage-collection-plugin/server'; import { routes } from './rest_api_routes/public'; import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from './types'; +import { registerExistingIndicesPath } from './rest_api_routes/internal/existing_indices'; import { registerFieldForWildcard } from './rest_api_routes/internal/fields_for'; import { registerHasDataViewsRoute } from './rest_api_routes/internal/has_data_views'; @@ -27,6 +28,7 @@ export function registerRoutes( routes.forEach((route) => route(router, getStartServices, dataViewRestCounter)); + registerExistingIndicesPath(router); registerFieldForWildcard(router, getStartServices, isRollupsEnabled); registerHasDataViewsRoute(router); } diff --git a/test/api_integration/apis/data_views/existing_indices_route/index.ts b/test/api_integration/apis/data_views/existing_indices_route/index.ts new file mode 100644 index 00000000000000..8542ac36cdf149 --- /dev/null +++ b/test/api_integration/apis/data_views/existing_indices_route/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 { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('index_patterns/_existing_indices route', () => { + loadTestFile(require.resolve('./params')); + loadTestFile(require.resolve('./response')); + }); +} diff --git a/test/api_integration/apis/data_views/existing_indices_route/params.ts b/test/api_integration/apis/data_views/existing_indices_route/params.ts new file mode 100644 index 00000000000000..5f015f68392325 --- /dev/null +++ b/test/api_integration/apis/data_views/existing_indices_route/params.ts @@ -0,0 +1,79 @@ +/* + * 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 { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; +import { INITIAL_REST_VERSION_INTERNAL } from '@kbn/data-views-plugin/server/constants'; +import { EXISTING_INDICES_PATH } from '@kbn/data-views-plugin/common/constants'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const supertest = getService('supertest'); + const randomness = getService('randomness'); + + describe('_existing_indices params', () => { + before(() => + esArchiver.load('test/api_integration/fixtures/es_archiver/index_patterns/basic_index') + ); + after(() => + esArchiver.unload('test/api_integration/fixtures/es_archiver/index_patterns/basic_index') + ); + + it('requires a query param', () => + supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + .query({}) + .expect(400)); + + it('accepts indices param as single index string', () => + supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + .query({ + indices: 'filebeat-*', + }) + .expect(200)); + + it('accepts indices param as single index array', () => + supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + .query({ + indices: ['filebeat-*'], + }) + .expect(200)); + + it('accepts indices param', () => + supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + .query({ + indices: ['filebeat-*', 'packetbeat-*'], + }) + .expect(200)); + + it('rejects unexpected query params', () => + supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + .query({ + [randomness.word()]: randomness.word(), + }) + .expect(400)); + + it('rejects a comma-separated list of indices', () => + supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + .query({ + indices: 'filebeat-*,packetbeat-*', + }) + .expect(400)); + }); +} diff --git a/test/api_integration/apis/data_views/existing_indices_route/response.ts b/test/api_integration/apis/data_views/existing_indices_route/response.ts new file mode 100644 index 00000000000000..e21edc256de1c2 --- /dev/null +++ b/test/api_integration/apis/data_views/existing_indices_route/response.ts @@ -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 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 { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; +import { INITIAL_REST_VERSION_INTERNAL } from '@kbn/data-views-plugin/server/constants'; +import { EXISTING_INDICES_PATH } from '@kbn/data-views-plugin/common/constants'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const supertest = getService('supertest'); + + describe('_existing_indices response', () => { + before(() => + esArchiver.load('test/api_integration/fixtures/es_archiver/index_patterns/basic_index') + ); + after(() => + esArchiver.unload('test/api_integration/fixtures/es_archiver/index_patterns/basic_index') + ); + + it('returns an array of existing indices', async () => { + await supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + .query({ + indices: ['basic_index', 'bad_index'], + }) + .expect(200, ['basic_index']); + }); + + it('returns an empty array when no indices exist', async () => { + await supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + .query({ + indices: ['bad_index'], + }) + .expect(200, []); + }); + }); +} diff --git a/test/api_integration/apis/data_views/index.ts b/test/api_integration/apis/data_views/index.ts index 72fb1f780311b9..a6589d5680b3d5 100644 --- a/test/api_integration/apis/data_views/index.ts +++ b/test/api_integration/apis/data_views/index.ts @@ -11,6 +11,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('index_patterns', () => { loadTestFile(require.resolve('./es_errors')); + loadTestFile(require.resolve('./existing_indices_route')); loadTestFile(require.resolve('./fields_for_wildcard_route')); loadTestFile(require.resolve('./data_views_crud')); loadTestFile(require.resolve('./scripted_fields_crud')); diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/create_sourcerer_data_view.ts b/x-pack/plugins/security_solution/public/common/containers/sourcerer/create_sourcerer_data_view.ts index b8b680959e2d07..abfaa564ec536b 100644 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/create_sourcerer_data_view.ts +++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/create_sourcerer_data_view.ts @@ -5,11 +5,8 @@ * 2.0. */ -import type { - DataViewListItem, - DataViewsContract, - DataView as DataViewType, -} from '@kbn/data-views-plugin/common'; +import type { DataViewListItem, DataView as DataViewType } from '@kbn/data-views-plugin/common'; +import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public/types'; import { transformError } from '@kbn/securitysolution-es-utils'; import { ensurePatternFormat } from '../../../../common/utils/sourcerer'; import type { KibanaDataView } from '../../store/sourcerer/model'; @@ -21,7 +18,7 @@ export interface GetSourcererDataView { body: { patternList: string[]; }; - dataViewService: DataViewsContract; + dataViewService: DataViewsServicePublic; dataViewId: string | null; } diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/get_sourcerer_data_view.test.ts b/x-pack/plugins/security_solution/public/common/containers/sourcerer/get_sourcerer_data_view.test.ts index cc4921380fac80..082fbf8d1765fd 100644 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/get_sourcerer_data_view.test.ts +++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/get_sourcerer_data_view.test.ts @@ -6,7 +6,7 @@ */ import { getSourcererDataView } from './get_sourcerer_data_view'; -import type { DataViewsService } from '@kbn/data-views-plugin/common'; +import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public/types'; const dataViewId = 'test-id'; const dataViewsService = { @@ -20,7 +20,7 @@ const dataViewsService = { fields: {}, }), getExistingIndices: jest.fn().mockResolvedValue(['test-pattern']), -} as unknown as jest.Mocked; +} as unknown as jest.Mocked; describe('getSourcererDataView', () => { beforeEach(() => { jest.clearAllMocks(); diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/get_sourcerer_data_view.ts b/x-pack/plugins/security_solution/public/common/containers/sourcerer/get_sourcerer_data_view.ts index a3cc1a8041b4c9..388ac93f310ce5 100644 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/get_sourcerer_data_view.ts +++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/get_sourcerer_data_view.ts @@ -5,14 +5,14 @@ * 2.0. */ -import type { DataViewsContract } from '@kbn/data-views-plugin/common'; +import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public/types'; import { ensurePatternFormat } from '../../../../common/utils/sourcerer'; import type { SourcererDataView, RunTimeMappings } from '../../store/sourcerer/model'; import { getDataViewStateFromIndexFields } from '../source/use_data_view'; export const getSourcererDataView = async ( dataViewId: string, - dataViewsService: DataViewsContract, + dataViewsService: DataViewsServicePublic, refreshFields = false ): Promise => { const dataView = await dataViewsService.get(dataViewId, true, refreshFields); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/data_views/existing_indices_route/index.ts b/x-pack/test_serverless/api_integration/test_suites/common/data_views/existing_indices_route/index.ts new file mode 100644 index 00000000000000..9b0dcc33d96157 --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/common/data_views/existing_indices_route/index.ts @@ -0,0 +1,15 @@ +/* + * 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 { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('index_patterns/_existing_indices route', () => { + loadTestFile(require.resolve('./params')); + loadTestFile(require.resolve('./response')); + }); +} diff --git a/x-pack/test_serverless/api_integration/test_suites/common/data_views/existing_indices_route/params.ts b/x-pack/test_serverless/api_integration/test_suites/common/data_views/existing_indices_route/params.ts new file mode 100644 index 00000000000000..60ca17d70cee05 --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/common/data_views/existing_indices_route/params.ts @@ -0,0 +1,91 @@ +/* + * 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 { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; +import { INITIAL_REST_VERSION_INTERNAL } from '@kbn/data-views-plugin/server/constants'; +import { EXISTING_INDICES_PATH } from '@kbn/data-views-plugin/common/constants'; +import type { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const supertest = getService('supertest'); + const randomness = getService('randomness'); + const svlCommonApi = getService('svlCommonApi'); + + describe('_existing_indices params', () => { + before(() => + esArchiver.load('test/api_integration/fixtures/es_archiver/index_patterns/basic_index') + ); + after(() => + esArchiver.unload('test/api_integration/fixtures/es_archiver/index_patterns/basic_index') + ); + + it('requires a query param', () => + supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + // TODO: API requests in Serverless require internal request headers + .set(svlCommonApi.getInternalRequestHeader()) + .query({}) + .expect(400)); + + it('accepts indices param as single index string', () => + supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + // TODO: API requests in Serverless require internal request headers + .set(svlCommonApi.getInternalRequestHeader()) + .query({ + indices: 'filebeat-*', + }) + .expect(200)); + + it('accepts indices param as single index array', () => + supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + // TODO: API requests in Serverless require internal request headers + .set(svlCommonApi.getInternalRequestHeader()) + .query({ + indices: ['filebeat-*'], + }) + .expect(200)); + + it('accepts indices param', () => + supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + // TODO: API requests in Serverless require internal request headers + .set(svlCommonApi.getInternalRequestHeader()) + .query({ + indices: ['filebeat-*', 'packetbeat-*'], + }) + .expect(200)); + + it('rejects unexpected query params', () => + supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + // TODO: API requests in Serverless require internal request headers + .set(svlCommonApi.getInternalRequestHeader()) + .query({ + [randomness.word()]: randomness.word(), + }) + .expect(400)); + + it('rejects a comma-separated list of indices', () => + supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + // TODO: API requests in Serverless require internal request headers + .set(svlCommonApi.getInternalRequestHeader()) + .query({ + indices: 'filebeat-*,packetbeat-*', + }) + .expect(400)); + }); +} diff --git a/x-pack/test_serverless/api_integration/test_suites/common/data_views/existing_indices_route/response.ts b/x-pack/test_serverless/api_integration/test_suites/common/data_views/existing_indices_route/response.ts new file mode 100644 index 00000000000000..8cea2292402c26 --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/common/data_views/existing_indices_route/response.ts @@ -0,0 +1,50 @@ +/* + * 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 { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; +import { INITIAL_REST_VERSION_INTERNAL } from '@kbn/data-views-plugin/server/constants'; +import { EXISTING_INDICES_PATH } from '@kbn/data-views-plugin/common/constants'; +import type { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const supertest = getService('supertest'); + const svlCommonApi = getService('svlCommonApi'); + + describe('_existing_indices response', () => { + before(() => + esArchiver.load('test/api_integration/fixtures/es_archiver/index_patterns/basic_index') + ); + after(() => + esArchiver.unload('test/api_integration/fixtures/es_archiver/index_patterns/basic_index') + ); + + it('returns an array of existing indices', async () => { + await supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + // TODO: API requests in Serverless require internal request headers + .set(svlCommonApi.getInternalRequestHeader()) + .query({ + indices: ['basic_index', 'bad_index'], + }) + .expect(200, ['basic_index']); + }); + + it('returns an empty array when no indices exist', async () => { + await supertest + .get(EXISTING_INDICES_PATH) + .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION_INTERNAL) + // TODO: API requests in Serverless require internal request headers + .set(svlCommonApi.getInternalRequestHeader()) + .query({ + indices: ['bad_index'], + }) + .expect(200, []); + }); + }); +} diff --git a/x-pack/test_serverless/api_integration/test_suites/common/data_views/index.ts b/x-pack/test_serverless/api_integration/test_suites/common/data_views/index.ts index dafe36565a8fe1..5a2623a8b7c435 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/data_views/index.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/data_views/index.ts @@ -12,6 +12,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { this.tags(['esGate']); loadTestFile(require.resolve('./es_errors')); + loadTestFile(require.resolve('./existing_indices_route')); loadTestFile(require.resolve('./fields_for_wildcard_route')); loadTestFile(require.resolve('./data_views_crud')); // TODO: Removed `scripted_fields_crud` since From 8cf27642d078a2a7e0b2194ec078ece06c963f98 Mon Sep 17 00:00:00 2001 From: Pete Hampton Date: Mon, 16 Oct 2023 21:43:15 +0100 Subject: [PATCH 24/87] Update process/parent filterlists for RAD detection research. (#168974) ## Summary Adds requested filterlist entries for prebuilt rules - required for tuning and research. ### 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 ### 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) --- .../lib/telemetry/filterlists/index.test.ts | 56 +++++++++++++++++++ .../filterlists/prebuilt_rules_alerts.ts | 14 +++++ 2 files changed, 70 insertions(+) diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/index.test.ts b/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/index.test.ts index d63fa7510f4950..d61a3e92068182 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/index.test.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/index.test.ts @@ -278,5 +278,61 @@ describe('Security Telemetry filters', () => { }, }); }); + + it('copies over process/parent fields', () => { + const event = { + not_event: 'much data, much wow', + process: { + code_signature: { + status: 'test', + exists: false, + }, + Ext: { + api: { + parameters: { + desired_access: 'test', + desired_access_numeric: 'test', + text_block: 'i should not be here', + }, + }, + relative_file_creation_time: 'test', + }, + parent: { + code_signature: { + subject_name: 'test', + status: 'test', + text_block: 'i should not be here', + exists: false, + trusted: false, + }, + }, + }, + }; + expect(copyAllowlistedFields(prebuiltRuleAllowlistFields, event)).toStrictEqual({ + process: { + code_signature: { + status: 'test', + exists: false, + }, + Ext: { + api: { + parameters: { + desired_access: 'test', + desired_access_numeric: 'test', + }, + }, + relative_file_creation_time: 'test', + }, + parent: { + code_signature: { + subject_name: 'test', + status: 'test', + exists: false, + trusted: false, + }, + }, + }, + }); + }); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/prebuilt_rules_alerts.ts b/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/prebuilt_rules_alerts.ts index 98d4816e01ceee..1b4a8819c12b80 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/prebuilt_rules_alerts.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/prebuilt_rules_alerts.ts @@ -99,6 +99,7 @@ export const prebuiltRuleAllowlistFields: AllowlistFields = { relative_file_name_modify_time: true, }, code_signature: { + exists: true, status: true, subject_name: true, trusted: true, @@ -147,6 +148,8 @@ export const prebuiltRuleAllowlistFields: AllowlistFields = { args: true, args_count: true, code_signature: { + exists: true, + status: true, subject_name: true, trusted: true, }, @@ -159,11 +162,16 @@ export const prebuiltRuleAllowlistFields: AllowlistFields = { Ext: { api: { name: true, + parameters: { + desired_access: true, + desired_access_numeric: true, + }, }, effective_parent: { executable: true, name: true, }, + relative_file_creation_time: true, token: { integrity_level_name: true, }, @@ -174,6 +182,12 @@ export const prebuiltRuleAllowlistFields: AllowlistFields = { parent: { args: true, command_line: true, + code_signature: { + subject_name: true, + status: true, + exists: true, + trusted: true, + }, entity_id: true, executable: true, Ext: { From 9827aece21e0d423f5c457505b851f6479cd9f54 Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Mon, 16 Oct 2023 15:06:37 -0700 Subject: [PATCH 25/87] moves bulk_update unit tests to separate file (#168762) Part of https://github.com/elastic/kibana/issues/165434 Moves the unit tests to their own file Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../src/lib/apis/bulk_update.test.ts | 535 ++++++++++++++++++ .../src/lib/repository.test.ts | 432 -------------- 2 files changed, 535 insertions(+), 432 deletions(-) create mode 100644 packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_update.test.ts diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_update.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_update.test.ts new file mode 100644 index 00000000000000..d24c11f1906968 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/bulk_update.test.ts @@ -0,0 +1,535 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/no-shadow */ + +import { + pointInTimeFinderMock, + mockGetBulkOperationError, + mockGetCurrentTime, + mockGetSearchDsl, +} from '../repository.test.mock'; + +import type { Payload } from '@hapi/boom'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import type { + SavedObjectsBulkUpdateObject, + SavedObjectsBulkUpdateOptions, +} from '@kbn/core-saved-objects-api-server'; +import { type SavedObjectReference } from '@kbn/core-saved-objects-server'; +import { ALL_NAMESPACES_STRING } from '@kbn/core-saved-objects-utils-server'; +import { SavedObjectsRepository } from '../repository'; +import { loggerMock } from '@kbn/logging-mocks'; +import { + SavedObjectsSerializer, + encodeHitVersion, +} from '@kbn/core-saved-objects-base-server-internal'; +import { kibanaMigratorMock } from '../../mocks'; +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; + +import { + NAMESPACE_AGNOSTIC_TYPE, + MULTI_NAMESPACE_ISOLATED_TYPE, + HIDDEN_TYPE, + mockTimestampFields, + mockTimestamp, + mappings, + createRegistry, + createDocumentMigrator, + getMockMgetResponse, + type TypeIdTuple, + createSpySerializer, + bulkUpdateSuccess, + getMockBulkUpdateResponse, + expectErrorResult, + expectErrorNotFound, + expectError, + createBadRequestErrorPayload, + expectUpdateResult, +} from '../../test_helpers/repository.test.common'; + +interface ExpectedErrorResult { + type: string; + id: string; + error: Record; +} + +describe('SavedObjectsRepository', () => { + let client: ReturnType; + let repository: SavedObjectsRepository; + let migrator: ReturnType; + let logger: ReturnType; + let serializer: jest.Mocked; + + const registry = createRegistry(); + const documentMigrator = createDocumentMigrator(registry); + + const expectSuccess = ({ type, id }: { type: string; id: string }) => { + // @ts-expect-error TS is not aware of the extension + return expect.toBeDocumentWithoutError(type, id); + }; + + beforeEach(() => { + pointInTimeFinderMock.mockClear(); + client = elasticsearchClientMock.createElasticsearchClient(); + migrator = kibanaMigratorMock.create(); + documentMigrator.prepareMigrations(); + migrator.migrateDocument = jest.fn().mockImplementation(documentMigrator.migrate); + migrator.runMigrations = jest.fn().mockResolvedValue([{ status: 'skipped' }]); + logger = loggerMock.create(); + + // create a mock serializer "shim" so we can track function calls, but use the real serializer's implementation + serializer = createSpySerializer(registry); + + const allTypes = registry.getAllTypes().map((type) => type.name); + const allowedTypes = [...new Set(allTypes.filter((type) => !registry.isHidden(type)))]; + + // @ts-expect-error must use the private constructor to use the mocked serializer + repository = new SavedObjectsRepository({ + index: '.kibana-test', + mappings, + client, + migrator, + typeRegistry: registry, + serializer, + allowedTypes, + logger, + }); + + mockGetCurrentTime.mockReturnValue(mockTimestamp); + mockGetSearchDsl.mockClear(); + }); + + describe('#bulkUpdate', () => { + const obj1: SavedObjectsBulkUpdateObject = { + type: 'config', + id: '6.0.0-alpha1', + attributes: { title: 'Test One' }, + }; + const obj2: SavedObjectsBulkUpdateObject = { + type: 'index-pattern', + id: 'logstash-*', + attributes: { title: 'Test Two' }, + }; + const references = [{ name: 'ref_0', type: 'test', id: '1' }]; + const originId = 'some-origin-id'; + const namespace = 'foo-namespace'; + + // bulk create calls have two objects for each source -- the action, and the source + const expectClientCallArgsAction = ( + objects: TypeIdTuple[], + { + method, + _index = expect.any(String), + getId = () => expect.any(String), + overrides = {}, + }: { + method: string; + _index?: string; + getId?: (type: string, id: string) => string; + overrides?: Record; + } + ) => { + const body = []; + for (const { type, id } of objects) { + body.push({ + [method]: { + _index, + _id: getId(type, id), + ...overrides, + }, + }); + body.push(expect.any(Object)); + } + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ body }), + expect.anything() + ); + }; + + const expectObjArgs = ({ type, attributes }: { type: string; attributes: unknown }) => [ + expect.any(Object), + { + doc: expect.objectContaining({ + [type]: attributes, + ...mockTimestampFields, + }), + }, + ]; + + describe('client calls', () => { + it(`should use the ES bulk action by default`, async () => { + await bulkUpdateSuccess(client, repository, registry, [obj1, obj2]); + expect(client.bulk).toHaveBeenCalled(); + }); + + it(`should use the ES mget action before bulk action for any types that are multi-namespace`, async () => { + const objects = [obj1, { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE }]; + await bulkUpdateSuccess(client, repository, registry, objects); + expect(client.bulk).toHaveBeenCalled(); + expect(client.mget).toHaveBeenCalled(); + + const docs = [ + expect.objectContaining({ _id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:${obj2.id}` }), + ]; + expect(client.mget).toHaveBeenCalledWith( + expect.objectContaining({ body: { docs } }), + expect.anything() + ); + }); + + it(`formats the ES request`, async () => { + await bulkUpdateSuccess(client, repository, registry, [obj1, obj2]); + const body = [...expectObjArgs(obj1), ...expectObjArgs(obj2)]; + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ body }), + expect.anything() + ); + }); + + it(`formats the ES request for any types that are multi-namespace`, async () => { + const _obj2 = { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE }; + await bulkUpdateSuccess(client, repository, registry, [obj1, _obj2]); + const body = [...expectObjArgs(obj1), ...expectObjArgs(_obj2)]; + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ body }), + expect.anything() + ); + }); + + it(`doesnt call Elasticsearch if there are no valid objects to update`, async () => { + const objects = [obj1, obj2].map((x) => ({ ...x, type: 'unknownType' })); + await repository.bulkUpdate(objects); + expect(client.bulk).toHaveBeenCalledTimes(0); + }); + + it(`defaults to no references`, async () => { + await bulkUpdateSuccess(client, repository, registry, [obj1, obj2]); + const expected = { doc: expect.not.objectContaining({ references: expect.anything() }) }; + const body = [expect.any(Object), expected, expect.any(Object), expected]; + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ body }), + expect.anything() + ); + }); + + it(`accepts custom references array`, async () => { + const test = async (references: SavedObjectReference[]) => { + const objects = [obj1, obj2].map((obj) => ({ ...obj, references })); + await bulkUpdateSuccess(client, repository, registry, objects); + const expected = { doc: expect.objectContaining({ references }) }; + const body = [expect.any(Object), expected, expect.any(Object), expected]; + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ body }), + expect.anything() + ); + client.bulk.mockClear(); + }; + await test(references); + await test([{ type: 'type', id: 'id', name: 'some ref' }]); + await test([]); + }); + + it(`doesn't accept custom references if not an array`, async () => { + const test = async (references: unknown) => { + const objects = [obj1, obj2]; // .map((obj) => ({ ...obj })); + await bulkUpdateSuccess(client, repository, registry, objects); + const expected = { doc: expect.not.objectContaining({ references: expect.anything() }) }; + const body = [expect.any(Object), expected, expect.any(Object), expected]; + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ body }), + expect.anything() + ); + client.bulk.mockClear(); + }; + await test('string'); + await test(123); + await test(true); + await test(null); + }); + + it(`defaults to a refresh setting of wait_for`, async () => { + await bulkUpdateSuccess(client, repository, registry, [obj1, obj2]); + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ refresh: 'wait_for' }), + expect.anything() + ); + }); + + it(`defaults to no version for types that are not multi-namespace`, async () => { + const objects = [obj1, { ...obj2, type: NAMESPACE_AGNOSTIC_TYPE }]; + await bulkUpdateSuccess(client, repository, registry, objects); + expectClientCallArgsAction(objects, { method: 'update' }); + }); + + it(`accepts version`, async () => { + const version = encodeHitVersion({ _seq_no: 100, _primary_term: 200 }); + // test with both non-multi-namespace and multi-namespace types + const objects = [ + { ...obj1, version }, + { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE, version }, + ]; + await bulkUpdateSuccess(client, repository, registry, objects); + const overrides = { if_seq_no: 100, if_primary_term: 200 }; + expectClientCallArgsAction(objects, { method: 'update', overrides }); + }); + + it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { + const getId = (type: string, id: string) => `${namespace}:${type}:${id}`; // test that the raw document ID equals this (e.g., has a namespace prefix) + await bulkUpdateSuccess(client, repository, registry, [obj1, obj2], { namespace }); + expectClientCallArgsAction([obj1, obj2], { method: 'update', getId }); + + jest.clearAllMocks(); + // test again with object namespace string that supersedes the operation's namespace ID + await bulkUpdateSuccess(client, repository, registry, [ + { ...obj1, namespace }, + { ...obj2, namespace }, + ]); + expectClientCallArgsAction([obj1, obj2], { method: 'update', getId }); + }); + + it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { + const getId = (type: string, id: string) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix) + await bulkUpdateSuccess(client, repository, registry, [obj1, obj2]); + expectClientCallArgsAction([obj1, obj2], { method: 'update', getId }); + + jest.clearAllMocks(); + // test again with object namespace string that supersedes the operation's namespace ID + await bulkUpdateSuccess( + client, + repository, + registry, + [ + { ...obj1, namespace: 'default' }, + { ...obj2, namespace: 'default' }, + ], + { namespace } + ); + expectClientCallArgsAction([obj1, obj2], { method: 'update', getId }); + }); + + it(`normalizes options.namespace from 'default' to undefined`, async () => { + const getId = (type: string, id: string) => `${type}:${id}`; + await bulkUpdateSuccess(client, repository, registry, [obj1, obj2], { + namespace: 'default', + }); + expectClientCallArgsAction([obj1, obj2], { method: 'update', getId }); + }); + + it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { + const getId = (type: string, id: string) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix) + const _obj1 = { ...obj1, type: NAMESPACE_AGNOSTIC_TYPE }; + const _obj2 = { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE }; + + await bulkUpdateSuccess(client, repository, registry, [_obj1], { namespace }); + expectClientCallArgsAction([_obj1], { method: 'update', getId }); + client.bulk.mockClear(); + await bulkUpdateSuccess(client, repository, registry, [_obj2], { namespace }); + expectClientCallArgsAction([_obj2], { method: 'update', getId }); + + jest.clearAllMocks(); + // test again with object namespace string that supersedes the operation's namespace ID + await bulkUpdateSuccess(client, repository, registry, [{ ..._obj1, namespace }]); + expectClientCallArgsAction([_obj1], { method: 'update', getId }); + client.bulk.mockClear(); + await bulkUpdateSuccess(client, repository, registry, [{ ..._obj2, namespace }]); + expectClientCallArgsAction([_obj2], { method: 'update', getId }); + }); + }); + + describe('errors', () => { + afterEach(() => { + mockGetBulkOperationError.mockReset(); + }); + + const obj: SavedObjectsBulkUpdateObject = { + type: 'dashboard', + id: 'three', + attributes: {}, + }; + + const bulkUpdateError = async ( + obj: SavedObjectsBulkUpdateObject, + isBulkError: boolean, + expectedErrorResult: ExpectedErrorResult + ) => { + const objects = [obj1, obj, obj2]; + const mockResponse = getMockBulkUpdateResponse(registry, objects); + if (isBulkError) { + // mock the bulk error for only the second object + mockGetBulkOperationError.mockReturnValueOnce(undefined); + mockGetBulkOperationError.mockReturnValueOnce(expectedErrorResult.error as Payload); + } + client.bulk.mockResponseOnce(mockResponse); + + const result = await repository.bulkUpdate(objects); + expect(client.bulk).toHaveBeenCalled(); + const objCall = isBulkError ? expectObjArgs(obj) : []; + const body = [...expectObjArgs(obj1), ...objCall, ...expectObjArgs(obj2)]; + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ body }), + expect.anything() + ); + expect(result).toEqual({ + saved_objects: [expectSuccess(obj1), expectedErrorResult, expectSuccess(obj2)], + }); + }; + + const bulkUpdateMultiError = async ( + [obj1, _obj, obj2]: SavedObjectsBulkUpdateObject[], + options: SavedObjectsBulkUpdateOptions | undefined, + mgetResponse: estypes.MgetResponse, + mgetOptions?: { statusCode?: number } + ) => { + client.mget.mockResponseOnce(mgetResponse, { statusCode: mgetOptions?.statusCode }); + + const bulkResponse = getMockBulkUpdateResponse(registry, [obj1, obj2], { namespace }); + client.bulk.mockResponseOnce(bulkResponse); + + const result = await repository.bulkUpdate([obj1, _obj, obj2], options); + expect(client.bulk).toHaveBeenCalled(); + expect(client.mget).toHaveBeenCalled(); + const body = [...expectObjArgs(obj1), ...expectObjArgs(obj2)]; + expect(client.bulk).toHaveBeenCalledWith( + expect.objectContaining({ body }), + expect.anything() + ); + + expect(result).toEqual({ + saved_objects: [expectSuccess(obj1), expectErrorNotFound(_obj), expectSuccess(obj2)], + }); + }; + + it(`throws when options.namespace is '*'`, async () => { + await expect( + repository.bulkUpdate([obj], { namespace: ALL_NAMESPACES_STRING }) + ).rejects.toThrowError(createBadRequestErrorPayload('"options.namespace" cannot be "*"')); + }); + + it(`returns error when type is invalid`, async () => { + const _obj = { ...obj, type: 'unknownType' }; + await bulkUpdateError(_obj, false, expectErrorNotFound(_obj)); + }); + + it(`returns error when type is hidden`, async () => { + const _obj = { ...obj, type: HIDDEN_TYPE }; + await bulkUpdateError(_obj, false, expectErrorNotFound(_obj)); + }); + + it(`returns error when object namespace is '*'`, async () => { + const _obj = { ...obj, namespace: '*' }; + await bulkUpdateError( + _obj, + false, + expectErrorResult(obj, createBadRequestErrorPayload('"namespace" cannot be "*"')) + ); + }); + + it(`returns error when ES is unable to find the document (mget)`, async () => { + const _obj = { ...obj, type: MULTI_NAMESPACE_ISOLATED_TYPE, found: false }; + const mgetResponse = getMockMgetResponse(registry, [_obj]); + await bulkUpdateMultiError([obj1, _obj, obj2], undefined, mgetResponse); + }); + + it(`returns error when ES is unable to find the index (mget)`, async () => { + const _obj = { ...obj, type: MULTI_NAMESPACE_ISOLATED_TYPE }; + const mgetResponse = getMockMgetResponse(registry, [_obj]); + await bulkUpdateMultiError([obj1, _obj, obj2], { namespace }, mgetResponse, { + statusCode: 404, + }); + }); + + it(`returns error when there is a conflict with an existing multi-namespace saved object (mget)`, async () => { + const _obj = { ...obj, type: MULTI_NAMESPACE_ISOLATED_TYPE }; + const mgetResponse = getMockMgetResponse(registry, [_obj], 'bar-namespace'); + await bulkUpdateMultiError([obj1, _obj, obj2], { namespace }, mgetResponse); + }); + + it(`returns bulk error`, async () => { + const expectedErrorResult = { + type: obj.type, + id: obj.id, + error: { message: 'Oh no, a bulk error!' }, + }; + await bulkUpdateError(obj, true, expectedErrorResult); + }); + }); + + describe('returns', () => { + it(`formats the ES response`, async () => { + const response = await bulkUpdateSuccess(client, repository, registry, [obj1, obj2]); + expect(response).toEqual({ + saved_objects: [obj1, obj2].map(expectUpdateResult), + }); + }); + + it(`includes references`, async () => { + const objects = [obj1, obj2].map((obj) => ({ ...obj, references })); + const response = await bulkUpdateSuccess(client, repository, registry, objects); + expect(response).toEqual({ + saved_objects: objects.map(expectUpdateResult), + }); + }); + + it(`handles a mix of successful updates and errors`, async () => { + const obj: SavedObjectsBulkUpdateObject = { + type: 'unknownType', + id: 'three', + attributes: {}, + }; + const objects = [obj1, obj, obj2]; + const mockResponse = getMockBulkUpdateResponse(registry, objects); + client.bulk.mockResponseOnce(mockResponse); + + const result = await repository.bulkUpdate(objects); + expect(client.bulk).toHaveBeenCalledTimes(1); + expect(result).toEqual({ + saved_objects: [expectUpdateResult(obj1), expectError(obj), expectUpdateResult(obj2)], + }); + }); + + it(`includes namespaces property for single-namespace and multi-namespace documents`, async () => { + const obj: SavedObjectsBulkUpdateObject = { + type: MULTI_NAMESPACE_ISOLATED_TYPE, + id: 'three', + attributes: {}, + }; + const result = await bulkUpdateSuccess(client, repository, registry, [obj1, obj]); + expect(result).toEqual({ + saved_objects: [ + expect.objectContaining({ namespaces: expect.any(Array) }), + expect.objectContaining({ namespaces: expect.any(Array) }), + ], + }); + }); + + it(`includes originId property if present in cluster call response`, async () => { + const obj: SavedObjectsBulkUpdateObject = { + type: MULTI_NAMESPACE_ISOLATED_TYPE, + id: 'three', + attributes: {}, + }; + const result = await bulkUpdateSuccess( + client, + repository, + registry, + [obj1, obj], + {}, + originId + ); + expect(result).toEqual({ + saved_objects: [ + expect.objectContaining({ originId }), + expect.objectContaining({ originId }), + ], + }); + }); + }); + }); +}); diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.test.ts index fa1fda60d09fd0..1084ad3e589661 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.test.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/repository.test.ts @@ -34,8 +34,6 @@ import type { SavedObjectsCreatePointInTimeFinderOptions, SavedObjectsBulkCreateObject, SavedObjectsBulkGetObject, - SavedObjectsBulkUpdateObject, - SavedObjectsBulkUpdateOptions, SavedObjectsCreateOptions, SavedObjectsDeleteOptions, SavedObjectsOpenPointInTimeOptions, @@ -89,10 +87,8 @@ import { type TypeIdTuple, createSpySerializer, bulkCreateSuccess, - bulkUpdateSuccess, getMockBulkCreateResponse, bulkGet, - getMockBulkUpdateResponse, expectErrorResult, expectErrorInvalidType, expectErrorNotFound, @@ -110,7 +106,6 @@ import { createConflictErrorPayload, createGenericNotFoundErrorPayload, expectCreateResult, - expectUpdateResult, mockTimestampFieldsWithCreated, getMockEsBulkDeleteResponse, bulkDeleteSuccess, @@ -1472,433 +1467,6 @@ describe('SavedObjectsRepository', () => { }); }); - describe('#bulkUpdate', () => { - const obj1: SavedObjectsBulkUpdateObject = { - type: 'config', - id: '6.0.0-alpha1', - attributes: { title: 'Test One' }, - }; - const obj2: SavedObjectsBulkUpdateObject = { - type: 'index-pattern', - id: 'logstash-*', - attributes: { title: 'Test Two' }, - }; - const references = [{ name: 'ref_0', type: 'test', id: '1' }]; - const originId = 'some-origin-id'; - const namespace = 'foo-namespace'; - - // bulk create calls have two objects for each source -- the action, and the source - const expectClientCallArgsAction = ( - objects: TypeIdTuple[], - { - method, - _index = expect.any(String), - getId = () => expect.any(String), - overrides = {}, - }: { - method: string; - _index?: string; - getId?: (type: string, id: string) => string; - overrides?: Record; - } - ) => { - const body = []; - for (const { type, id } of objects) { - body.push({ - [method]: { - _index, - _id: getId(type, id), - ...overrides, - }, - }); - body.push(expect.any(Object)); - } - expect(client.bulk).toHaveBeenCalledWith( - expect.objectContaining({ body }), - expect.anything() - ); - }; - - const expectObjArgs = ({ type, attributes }: { type: string; attributes: unknown }) => [ - expect.any(Object), - { - doc: expect.objectContaining({ - [type]: attributes, - ...mockTimestampFields, - }), - }, - ]; - - describe('client calls', () => { - it(`should use the ES bulk action by default`, async () => { - await bulkUpdateSuccess(client, repository, registry, [obj1, obj2]); - expect(client.bulk).toHaveBeenCalled(); - }); - - it(`should use the ES mget action before bulk action for any types that are multi-namespace`, async () => { - const objects = [obj1, { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE }]; - await bulkUpdateSuccess(client, repository, registry, objects); - expect(client.bulk).toHaveBeenCalled(); - expect(client.mget).toHaveBeenCalled(); - - const docs = [ - expect.objectContaining({ _id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:${obj2.id}` }), - ]; - expect(client.mget).toHaveBeenCalledWith( - expect.objectContaining({ body: { docs } }), - expect.anything() - ); - }); - - it(`formats the ES request`, async () => { - await bulkUpdateSuccess(client, repository, registry, [obj1, obj2]); - const body = [...expectObjArgs(obj1), ...expectObjArgs(obj2)]; - expect(client.bulk).toHaveBeenCalledWith( - expect.objectContaining({ body }), - expect.anything() - ); - }); - - it(`formats the ES request for any types that are multi-namespace`, async () => { - const _obj2 = { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE }; - await bulkUpdateSuccess(client, repository, registry, [obj1, _obj2]); - const body = [...expectObjArgs(obj1), ...expectObjArgs(_obj2)]; - expect(client.bulk).toHaveBeenCalledWith( - expect.objectContaining({ body }), - expect.anything() - ); - }); - - it(`doesnt call Elasticsearch if there are no valid objects to update`, async () => { - const objects = [obj1, obj2].map((x) => ({ ...x, type: 'unknownType' })); - await repository.bulkUpdate(objects); - expect(client.bulk).toHaveBeenCalledTimes(0); - }); - - it(`defaults to no references`, async () => { - await bulkUpdateSuccess(client, repository, registry, [obj1, obj2]); - const expected = { doc: expect.not.objectContaining({ references: expect.anything() }) }; - const body = [expect.any(Object), expected, expect.any(Object), expected]; - expect(client.bulk).toHaveBeenCalledWith( - expect.objectContaining({ body }), - expect.anything() - ); - }); - - it(`accepts custom references array`, async () => { - const test = async (references: SavedObjectReference[]) => { - const objects = [obj1, obj2].map((obj) => ({ ...obj, references })); - await bulkUpdateSuccess(client, repository, registry, objects); - const expected = { doc: expect.objectContaining({ references }) }; - const body = [expect.any(Object), expected, expect.any(Object), expected]; - expect(client.bulk).toHaveBeenCalledWith( - expect.objectContaining({ body }), - expect.anything() - ); - client.bulk.mockClear(); - }; - await test(references); - await test([{ type: 'type', id: 'id', name: 'some ref' }]); - await test([]); - }); - - it(`doesn't accept custom references if not an array`, async () => { - const test = async (references: unknown) => { - const objects = [obj1, obj2]; // .map((obj) => ({ ...obj })); - await bulkUpdateSuccess(client, repository, registry, objects); - const expected = { doc: expect.not.objectContaining({ references: expect.anything() }) }; - const body = [expect.any(Object), expected, expect.any(Object), expected]; - expect(client.bulk).toHaveBeenCalledWith( - expect.objectContaining({ body }), - expect.anything() - ); - client.bulk.mockClear(); - }; - await test('string'); - await test(123); - await test(true); - await test(null); - }); - - it(`defaults to a refresh setting of wait_for`, async () => { - await bulkUpdateSuccess(client, repository, registry, [obj1, obj2]); - expect(client.bulk).toHaveBeenCalledWith( - expect.objectContaining({ refresh: 'wait_for' }), - expect.anything() - ); - }); - - it(`defaults to no version for types that are not multi-namespace`, async () => { - const objects = [obj1, { ...obj2, type: NAMESPACE_AGNOSTIC_TYPE }]; - await bulkUpdateSuccess(client, repository, registry, objects); - expectClientCallArgsAction(objects, { method: 'update' }); - }); - - it(`accepts version`, async () => { - const version = encodeHitVersion({ _seq_no: 100, _primary_term: 200 }); - // test with both non-multi-namespace and multi-namespace types - const objects = [ - { ...obj1, version }, - { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE, version }, - ]; - await bulkUpdateSuccess(client, repository, registry, objects); - const overrides = { if_seq_no: 100, if_primary_term: 200 }; - expectClientCallArgsAction(objects, { method: 'update', overrides }); - }); - - it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => { - const getId = (type: string, id: string) => `${namespace}:${type}:${id}`; // test that the raw document ID equals this (e.g., has a namespace prefix) - await bulkUpdateSuccess(client, repository, registry, [obj1, obj2], { namespace }); - expectClientCallArgsAction([obj1, obj2], { method: 'update', getId }); - - jest.clearAllMocks(); - // test again with object namespace string that supersedes the operation's namespace ID - await bulkUpdateSuccess(client, repository, registry, [ - { ...obj1, namespace }, - { ...obj2, namespace }, - ]); - expectClientCallArgsAction([obj1, obj2], { method: 'update', getId }); - }); - - it(`doesn't prepend namespace to the id when providing no namespace for single-namespace type`, async () => { - const getId = (type: string, id: string) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix) - await bulkUpdateSuccess(client, repository, registry, [obj1, obj2]); - expectClientCallArgsAction([obj1, obj2], { method: 'update', getId }); - - jest.clearAllMocks(); - // test again with object namespace string that supersedes the operation's namespace ID - await bulkUpdateSuccess( - client, - repository, - registry, - [ - { ...obj1, namespace: 'default' }, - { ...obj2, namespace: 'default' }, - ], - { namespace } - ); - expectClientCallArgsAction([obj1, obj2], { method: 'update', getId }); - }); - - it(`normalizes options.namespace from 'default' to undefined`, async () => { - const getId = (type: string, id: string) => `${type}:${id}`; - await bulkUpdateSuccess(client, repository, registry, [obj1, obj2], { - namespace: 'default', - }); - expectClientCallArgsAction([obj1, obj2], { method: 'update', getId }); - }); - - it(`doesn't prepend namespace to the id when not using single-namespace type`, async () => { - const getId = (type: string, id: string) => `${type}:${id}`; // test that the raw document ID equals this (e.g., does not have a namespace prefix) - const _obj1 = { ...obj1, type: NAMESPACE_AGNOSTIC_TYPE }; - const _obj2 = { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE }; - - await bulkUpdateSuccess(client, repository, registry, [_obj1], { namespace }); - expectClientCallArgsAction([_obj1], { method: 'update', getId }); - client.bulk.mockClear(); - await bulkUpdateSuccess(client, repository, registry, [_obj2], { namespace }); - expectClientCallArgsAction([_obj2], { method: 'update', getId }); - - jest.clearAllMocks(); - // test again with object namespace string that supersedes the operation's namespace ID - await bulkUpdateSuccess(client, repository, registry, [{ ..._obj1, namespace }]); - expectClientCallArgsAction([_obj1], { method: 'update', getId }); - client.bulk.mockClear(); - await bulkUpdateSuccess(client, repository, registry, [{ ..._obj2, namespace }]); - expectClientCallArgsAction([_obj2], { method: 'update', getId }); - }); - }); - - describe('errors', () => { - afterEach(() => { - mockGetBulkOperationError.mockReset(); - }); - - const obj: SavedObjectsBulkUpdateObject = { - type: 'dashboard', - id: 'three', - attributes: {}, - }; - - const bulkUpdateError = async ( - obj: SavedObjectsBulkUpdateObject, - isBulkError: boolean, - expectedErrorResult: ExpectedErrorResult - ) => { - const objects = [obj1, obj, obj2]; - const mockResponse = getMockBulkUpdateResponse(registry, objects); - if (isBulkError) { - // mock the bulk error for only the second object - mockGetBulkOperationError.mockReturnValueOnce(undefined); - mockGetBulkOperationError.mockReturnValueOnce(expectedErrorResult.error as Payload); - } - client.bulk.mockResponseOnce(mockResponse); - - const result = await repository.bulkUpdate(objects); - expect(client.bulk).toHaveBeenCalled(); - const objCall = isBulkError ? expectObjArgs(obj) : []; - const body = [...expectObjArgs(obj1), ...objCall, ...expectObjArgs(obj2)]; - expect(client.bulk).toHaveBeenCalledWith( - expect.objectContaining({ body }), - expect.anything() - ); - expect(result).toEqual({ - saved_objects: [expectSuccess(obj1), expectedErrorResult, expectSuccess(obj2)], - }); - }; - - const bulkUpdateMultiError = async ( - [obj1, _obj, obj2]: SavedObjectsBulkUpdateObject[], - options: SavedObjectsBulkUpdateOptions | undefined, - mgetResponse: estypes.MgetResponse, - mgetOptions?: { statusCode?: number } - ) => { - client.mget.mockResponseOnce(mgetResponse, { statusCode: mgetOptions?.statusCode }); - - const bulkResponse = getMockBulkUpdateResponse(registry, [obj1, obj2], { namespace }); - client.bulk.mockResponseOnce(bulkResponse); - - const result = await repository.bulkUpdate([obj1, _obj, obj2], options); - expect(client.bulk).toHaveBeenCalled(); - expect(client.mget).toHaveBeenCalled(); - const body = [...expectObjArgs(obj1), ...expectObjArgs(obj2)]; - expect(client.bulk).toHaveBeenCalledWith( - expect.objectContaining({ body }), - expect.anything() - ); - - expect(result).toEqual({ - saved_objects: [expectSuccess(obj1), expectErrorNotFound(_obj), expectSuccess(obj2)], - }); - }; - - it(`throws when options.namespace is '*'`, async () => { - await expect( - repository.bulkUpdate([obj], { namespace: ALL_NAMESPACES_STRING }) - ).rejects.toThrowError(createBadRequestErrorPayload('"options.namespace" cannot be "*"')); - }); - - it(`returns error when type is invalid`, async () => { - const _obj = { ...obj, type: 'unknownType' }; - await bulkUpdateError(_obj, false, expectErrorNotFound(_obj)); - }); - - it(`returns error when type is hidden`, async () => { - const _obj = { ...obj, type: HIDDEN_TYPE }; - await bulkUpdateError(_obj, false, expectErrorNotFound(_obj)); - }); - - it(`returns error when object namespace is '*'`, async () => { - const _obj = { ...obj, namespace: '*' }; - await bulkUpdateError( - _obj, - false, - expectErrorResult(obj, createBadRequestErrorPayload('"namespace" cannot be "*"')) - ); - }); - - it(`returns error when ES is unable to find the document (mget)`, async () => { - const _obj = { ...obj, type: MULTI_NAMESPACE_ISOLATED_TYPE, found: false }; - const mgetResponse = getMockMgetResponse(registry, [_obj]); - await bulkUpdateMultiError([obj1, _obj, obj2], undefined, mgetResponse); - }); - - it(`returns error when ES is unable to find the index (mget)`, async () => { - const _obj = { ...obj, type: MULTI_NAMESPACE_ISOLATED_TYPE }; - const mgetResponse = getMockMgetResponse(registry, [_obj]); - await bulkUpdateMultiError([obj1, _obj, obj2], { namespace }, mgetResponse, { - statusCode: 404, - }); - }); - - it(`returns error when there is a conflict with an existing multi-namespace saved object (mget)`, async () => { - const _obj = { ...obj, type: MULTI_NAMESPACE_ISOLATED_TYPE }; - const mgetResponse = getMockMgetResponse(registry, [_obj], 'bar-namespace'); - await bulkUpdateMultiError([obj1, _obj, obj2], { namespace }, mgetResponse); - }); - - it(`returns bulk error`, async () => { - const expectedErrorResult = { - type: obj.type, - id: obj.id, - error: { message: 'Oh no, a bulk error!' }, - }; - await bulkUpdateError(obj, true, expectedErrorResult); - }); - }); - - describe('returns', () => { - it(`formats the ES response`, async () => { - const response = await bulkUpdateSuccess(client, repository, registry, [obj1, obj2]); - expect(response).toEqual({ - saved_objects: [obj1, obj2].map(expectUpdateResult), - }); - }); - - it(`includes references`, async () => { - const objects = [obj1, obj2].map((obj) => ({ ...obj, references })); - const response = await bulkUpdateSuccess(client, repository, registry, objects); - expect(response).toEqual({ - saved_objects: objects.map(expectUpdateResult), - }); - }); - - it(`handles a mix of successful updates and errors`, async () => { - const obj: SavedObjectsBulkUpdateObject = { - type: 'unknownType', - id: 'three', - attributes: {}, - }; - const objects = [obj1, obj, obj2]; - const mockResponse = getMockBulkUpdateResponse(registry, objects); - client.bulk.mockResponseOnce(mockResponse); - - const result = await repository.bulkUpdate(objects); - expect(client.bulk).toHaveBeenCalledTimes(1); - expect(result).toEqual({ - saved_objects: [expectUpdateResult(obj1), expectError(obj), expectUpdateResult(obj2)], - }); - }); - - it(`includes namespaces property for single-namespace and multi-namespace documents`, async () => { - const obj: SavedObjectsBulkUpdateObject = { - type: MULTI_NAMESPACE_ISOLATED_TYPE, - id: 'three', - attributes: {}, - }; - const result = await bulkUpdateSuccess(client, repository, registry, [obj1, obj]); - expect(result).toEqual({ - saved_objects: [ - expect.objectContaining({ namespaces: expect.any(Array) }), - expect.objectContaining({ namespaces: expect.any(Array) }), - ], - }); - }); - - it(`includes originId property if present in cluster call response`, async () => { - const obj: SavedObjectsBulkUpdateObject = { - type: MULTI_NAMESPACE_ISOLATED_TYPE, - id: 'three', - attributes: {}, - }; - const result = await bulkUpdateSuccess( - client, - repository, - registry, - [obj1, obj], - {}, - originId - ); - expect(result).toEqual({ - saved_objects: [ - expect.objectContaining({ originId }), - expect.objectContaining({ originId }), - ], - }); - }); - }); - }); - describe('#bulkDelete', () => { const obj1: SavedObjectsBulkDeleteObject = { type: 'config', From c3936571fcbd161b479b7b1908793fe8ccc5ebdf Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 16 Oct 2023 23:09:52 +0100 Subject: [PATCH 26/87] fix(NA): missing --openssl-legacy-provider on webpack worker inside plugin helpers (#169030) This PR fixes a problem inside plugin-helpers as the webpack runner was running without `--openssl-legacy-provider` which breaks in the latest node version. --- packages/kbn-plugin-helpers/src/tasks/optimize.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-plugin-helpers/src/tasks/optimize.ts b/packages/kbn-plugin-helpers/src/tasks/optimize.ts index 3edc17e8796564..e235b69b88adac 100644 --- a/packages/kbn-plugin-helpers/src/tasks/optimize.ts +++ b/packages/kbn-plugin-helpers/src/tasks/optimize.ts @@ -63,7 +63,7 @@ export async function optimize({ const proc = fork(require.resolve('./optimize_worker'), { cwd: REPO_ROOT, - execArgv: ['--require=@kbn/babel-register/install'], + execArgv: ['--require=@kbn/babel-register/install', '--openssl-legacy-provider'], stdio: ['ignore', 'pipe', 'pipe', 'ipc'], }); From 4c2fcef7afc08fa03ad6417c4b98ca2f6134f148 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Mon, 16 Oct 2023 15:14:38 -0700 Subject: [PATCH 27/87] [OAS] Amazon Bedrock connector (#168662) --- .../connectors/action-types/bedrock.asciidoc | 1 - .../plugins/actions/docs/openapi/bundled.json | 82 ++++++++++++++++++- .../plugins/actions/docs/openapi/bundled.yaml | 61 +++++++++++++- .../schemas/config_properties_bedrock.yaml | 15 ++++ ...connector_response_properties_bedrock.yaml | 31 +++++++ .../components/schemas/connector_types.yaml | 1 + .../create_connector_request_bedrock.yaml | 23 ++++++ .../schemas/secrets_properties_bedrock.yaml | 13 +++ .../update_connector_request_bedrock.yaml | 13 +++ .../s@{spaceid}@api@actions@connector.yaml | 1 + ...}@api@actions@connector@{connectorid}.yaml | 2 + 11 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_bedrock.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_bedrock.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_bedrock.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/components/schemas/secrets_properties_bedrock.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request_bedrock.yaml diff --git a/docs/management/connectors/action-types/bedrock.asciidoc b/docs/management/connectors/action-types/bedrock.asciidoc index a01a750ae77aa3..80a8ba5b183f28 100644 --- a/docs/management/connectors/action-types/bedrock.asciidoc +++ b/docs/management/connectors/action-types/bedrock.asciidoc @@ -30,7 +30,6 @@ image::management/connectors/images/bedrock-connector.png[{bedrock} connector] Name:: The name of the connector. API URL:: The {bedrock} request URL. Default model:: The GAI model for {bedrock} to use. Current support is for the Anthropic Claude models, defaulting to Claude 2. The model can be set on a per request basis by including a "model" parameter alongside the request body. -Region:: The {bedrock} request URL. Access Key:: The AWS access key for authentication. Secret:: The secret for authentication. diff --git a/x-pack/plugins/actions/docs/openapi/bundled.json b/x-pack/plugins/actions/docs/openapi/bundled.json index 801dd78a76936d..1db5f55b1c7441 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled.json +++ b/x-pack/plugins/actions/docs/openapi/bundled.json @@ -57,6 +57,9 @@ "title": "Create connector request body properties", "description": "The properties vary depending on the connector type.", "oneOf": [ + { + "$ref": "#/components/schemas/create_connector_request_bedrock" + }, { "$ref": "#/components/schemas/create_connector_request_cases_webhook" }, @@ -338,6 +341,9 @@ "title": "Create connector request body properties", "description": "The properties vary depending on the connector type.", "oneOf": [ + { + "$ref": "#/components/schemas/create_connector_request_bedrock" + }, { "$ref": "#/components/schemas/create_connector_request_cases_webhook" }, @@ -466,6 +472,9 @@ "title": "Update connector request body properties", "description": "The properties vary depending on the connector type.", "oneOf": [ + { + "$ref": "#/components/schemas/create_connector_request_bedrock" + }, { "$ref": "#/components/schemas/update_connector_request_cases_webhook" }, @@ -1423,6 +1432,76 @@ } }, "schemas": { + "config_properties_bedrock": { + "title": "Connector request properties for an Amazon Bedrock connector", + "description": "Defines properties for connectors when type is `.bedrock`.", + "type": "object", + "required": [ + "apiUrl" + ], + "properties": { + "apiUrl": { + "type": "string", + "description": "The Amazon Bedrock request URL." + }, + "defaultModel": { + "type": "string", + "description": "The generative artificial intelligence model for Amazon Bedrock to use. Current support is for the Anthropic Claude models.\n", + "default": "anthropic.claude-v2" + } + } + }, + "secrets_properties_bedrock": { + "title": "Connector secrets properties for an Amazon Bedrock connector", + "description": "Defines secrets for connectors when type is `.bedrock`.", + "type": "object", + "required": [ + "accessKey", + "secret" + ], + "properties": { + "accessKey": { + "type": "string", + "description": "The AWS access key for authentication." + }, + "secret": { + "type": "string", + "description": "The AWS secret for authentication." + } + } + }, + "create_connector_request_bedrock": { + "title": "Create Amazon Bedrock connector request", + "description": "The Amazon Bedrock connector uses axios to send a POST request to Amazon Bedrock.", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_bedrock" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".bedrock" + ], + "example": ".bedrock" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_bedrock" + } + } + }, "config_properties_cases_webhook": { "title": "Connector request properties for Webhook - Case Management connector", "required": [ @@ -4450,6 +4529,7 @@ "type": "string", "description": "The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`.", "enum": [ + ".bedrock", ".cases-webhook", ".d3security", ".email", @@ -5722,4 +5802,4 @@ } } } -} +} \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/bundled.yaml b/x-pack/plugins/actions/docs/openapi/bundled.yaml index 63156405da018a..9fb7caccd1f170 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled.yaml +++ b/x-pack/plugins/actions/docs/openapi/bundled.yaml @@ -37,6 +37,7 @@ paths: title: Create connector request body properties description: The properties vary depending on the connector type. oneOf: + - $ref: '#/components/schemas/create_connector_request_bedrock' - $ref: '#/components/schemas/create_connector_request_cases_webhook' - $ref: '#/components/schemas/create_connector_request_d3security' - $ref: '#/components/schemas/create_connector_request_email' @@ -191,6 +192,7 @@ paths: title: Create connector request body properties description: The properties vary depending on the connector type. oneOf: + - $ref: '#/components/schemas/create_connector_request_bedrock' - $ref: '#/components/schemas/create_connector_request_cases_webhook' - $ref: '#/components/schemas/create_connector_request_d3security' - $ref: '#/components/schemas/create_connector_request_email' @@ -250,6 +252,7 @@ paths: title: Update connector request body properties description: The properties vary depending on the connector type. oneOf: + - $ref: '#/components/schemas/create_connector_request_bedrock' - $ref: '#/components/schemas/update_connector_request_cases_webhook' - $ref: '#/components/schemas/update_connector_request_d3security' - $ref: '#/components/schemas/update_connector_request_email' @@ -818,6 +821,59 @@ components: type: string example: c55b6eb0-6bad-11eb-9f3b-611eebc6c3ad schemas: + config_properties_bedrock: + title: Connector request properties for an Amazon Bedrock connector + description: Defines properties for connectors when type is `.bedrock`. + type: object + required: + - apiUrl + properties: + apiUrl: + type: string + description: The Amazon Bedrock request URL. + defaultModel: + type: string + description: | + The generative artificial intelligence model for Amazon Bedrock to use. Current support is for the Anthropic Claude models. + default: anthropic.claude-v2 + secrets_properties_bedrock: + title: Connector secrets properties for an Amazon Bedrock connector + description: Defines secrets for connectors when type is `.bedrock`. + type: object + required: + - accessKey + - secret + properties: + accessKey: + type: string + description: The AWS access key for authentication. + secret: + type: string + description: The AWS secret for authentication. + create_connector_request_bedrock: + title: Create Amazon Bedrock connector request + description: The Amazon Bedrock connector uses axios to send a POST request to Amazon Bedrock. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_bedrock' + connector_type_id: + type: string + description: The type of connector. + enum: + - .bedrock + example: .bedrock + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_bedrock' config_properties_cases_webhook: title: Connector request properties for Webhook - Case Management connector required: @@ -1031,14 +1087,14 @@ components: type: boolean host: description: | - The host name of the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. + The host name of the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. type: string oauthTokenUrl: type: string nullable: true port: description: | - The port to connect to on the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. + The port to connect to on the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. type: integer secure: description: | @@ -3084,6 +3140,7 @@ components: type: string description: The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`. enum: + - .bedrock - .cases-webhook - .d3security - .email diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_bedrock.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_bedrock.yaml new file mode 100644 index 00000000000000..25b279c4237397 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/config_properties_bedrock.yaml @@ -0,0 +1,15 @@ +title: Connector request properties for an Amazon Bedrock connector +description: Defines properties for connectors when type is `.bedrock`. +type: object +required: + - apiUrl +properties: + apiUrl: + type: string + description: The Amazon Bedrock request URL. + defaultModel: + type: string + description: > + The generative artificial intelligence model for Amazon Bedrock to use. + Current support is for the Anthropic Claude models. + default: anthropic.claude-v2 \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_bedrock.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_bedrock.yaml new file mode 100644 index 00000000000000..0d3f308744aa3c --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_bedrock.yaml @@ -0,0 +1,31 @@ +title: Connector response properties for an Amazon Bedrock connector +type: object +required: + - config + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name +properties: + config: + $ref: 'config_properties_bedrock.yaml' + connector_type_id: + type: string + description: The type of connector. + enum: + - .bedrock + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: 'is_deprecated.yaml' + is_missing_secrets: + $ref: 'is_missing_secrets.yaml' + is_preconfigured: + $ref: 'is_preconfigured.yaml' + is_system_action: + $ref: 'is_system_action.yaml' + name: + type: string + description: The display name for the connector. diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_types.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_types.yaml index 687648acd7141f..5d0bc42ab83177 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_types.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_types.yaml @@ -2,6 +2,7 @@ title: Connector types type: string description: The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`. enum: + - .bedrock - .cases-webhook - .d3security - .email diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_bedrock.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_bedrock.yaml new file mode 100644 index 00000000000000..2acc21bfbfac74 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request_bedrock.yaml @@ -0,0 +1,23 @@ +title: Create Amazon Bedrock connector request +description: The Amazon Bedrock connector uses axios to send a POST request to Amazon Bedrock. +type: object +required: + - config + - connector_type_id + - name + - secrets +properties: + config: + $ref: 'config_properties_bedrock.yaml' + connector_type_id: + type: string + description: The type of connector. + enum: + - .bedrock + example: .bedrock + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: 'secrets_properties_bedrock.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/secrets_properties_bedrock.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/secrets_properties_bedrock.yaml new file mode 100644 index 00000000000000..5f31baade28df9 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/secrets_properties_bedrock.yaml @@ -0,0 +1,13 @@ +title: Connector secrets properties for an Amazon Bedrock connector +description: Defines secrets for connectors when type is `.bedrock`. +type: object +required: + - accessKey + - secret +properties: + accessKey: + type: string + description: The AWS access key for authentication. + secret: + type: string + description: The AWS secret for authentication. diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request_bedrock.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request_bedrock.yaml new file mode 100644 index 00000000000000..dfa479870aab56 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request_bedrock.yaml @@ -0,0 +1,13 @@ +title: Update Amazon Bedrock connector request +type: object +required: + - config + - name +properties: + config: + $ref: 'config_properties_bedrock.yaml' + name: + type: string + description: The display name for the connector. + secrets: + $ref: 'secrets_properties_bedrock.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml index 62f2e1821eb8fd..64712858fa8a09 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml @@ -16,6 +16,7 @@ post: title: Create connector request body properties description: The properties vary depending on the connector type. oneOf: + - $ref: '../components/schemas/create_connector_request_bedrock.yaml' - $ref: '../components/schemas/create_connector_request_cases_webhook.yaml' - $ref: '../components/schemas/create_connector_request_d3security.yaml' - $ref: '../components/schemas/create_connector_request_email.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml index d85e38cff5f756..7c1d402efaca49 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml @@ -100,6 +100,7 @@ post: title: Create connector request body properties description: The properties vary depending on the connector type. oneOf: + - $ref: '../components/schemas/create_connector_request_bedrock.yaml' - $ref: '../components/schemas/create_connector_request_cases_webhook.yaml' - $ref: '../components/schemas/create_connector_request_d3security.yaml' - $ref: '../components/schemas/create_connector_request_email.yaml' @@ -160,6 +161,7 @@ put: title: Update connector request body properties description: The properties vary depending on the connector type. oneOf: + - $ref: '../components/schemas/create_connector_request_bedrock.yaml' - $ref: '../components/schemas/update_connector_request_cases_webhook.yaml' - $ref: '../components/schemas/update_connector_request_d3security.yaml' - $ref: '../components/schemas/update_connector_request_email.yaml' From bf3877c689c3c45f8b74b989f80e86c03e165e67 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Tue, 17 Oct 2023 00:47:25 +0100 Subject: [PATCH 28/87] skip flaky suite (#168267) --- x-pack/test/functional/apps/rollup_job/tsvb.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/rollup_job/tsvb.js b/x-pack/test/functional/apps/rollup_job/tsvb.js index 957b33618d9cfb..5dc4a6c6589669 100644 --- a/x-pack/test/functional/apps/rollup_job/tsvb.js +++ b/x-pack/test/functional/apps/rollup_job/tsvb.js @@ -24,7 +24,8 @@ export default function ({ getService, getPageObjects }) { const fromTime = 'Oct 15, 2019 @ 00:00:01.000'; const toTime = 'Oct 15, 2019 @ 19:31:44.000'; - describe('tsvb integration', function () { + // FLAKY: https://github.com/elastic/kibana/issues/168267 + describe.skip('tsvb integration', function () { //Since rollups can only be created once with the same name (even if you delete it), //we add the Date.now() to avoid name collision if you run the tests locally back to back. const rollupJobName = `tsvb-test-rollup-job-${Date.now()}`; From 79e9f50dbc153fa8745d3ddc70522c435a125825 Mon Sep 17 00:00:00 2001 From: Khristinin Nikita Date: Tue, 17 Oct 2023 02:19:02 +0200 Subject: [PATCH 29/87] Remove unsupported settings from index template (#168968) ## Summary those settings[ not working ](https://github.com/elastic/kibana/issues/168406#issuecomment-1764527758) in serverless --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/lib/risk_engine/risk_engine_data_client.test.ts | 2 -- .../server/lib/risk_engine/risk_engine_data_client.ts | 2 -- .../group10/risk_engine/init_and_status_apis.ts | 3 --- 3 files changed, 7 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/risk_engine/risk_engine_data_client.test.ts b/x-pack/plugins/security_solution/server/lib/risk_engine/risk_engine_data_client.test.ts index c4b16b72894dc4..8dc2da15c2e185 100644 --- a/x-pack/plugins/security_solution/server/lib/risk_engine/risk_engine_data_client.test.ts +++ b/x-pack/plugins/security_solution/server/lib/risk_engine/risk_engine_data_client.test.ts @@ -286,8 +286,6 @@ describe('RiskEngineDataClient', () => { template: { lifecycle: {}, settings: { - auto_expand_replicas: '0-1', - hidden: true, 'index.mapping.total_fields.limit': totalFieldsLimit, }, mappings: { 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 6244bec573a6b8..269f4b6dad9fd7 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 @@ -305,8 +305,6 @@ export class RiskEngineDataClient { template: { lifecycle: {}, settings: { - auto_expand_replicas: '0-1', - hidden: true, 'index.mapping.total_fields.limit': totalFieldsLimit, }, mappings: { 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 ab1dbb8dbbcd2f..a49bfe4809491b 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 @@ -244,8 +244,6 @@ export default ({ getService }: FtrProviderContext) => { limit: '1000', }, }, - hidden: 'true', - auto_expand_replicas: '0-1', }, }); @@ -274,7 +272,6 @@ export default ({ getService }: FtrProviderContext) => { expect(dataStream?.settings?.index?.hidden).to.eql('true'); expect(dataStream?.settings?.index?.number_of_shards).to.eql(1); - expect(dataStream?.settings?.index?.auto_expand_replicas).to.eql('0-1'); const indexExist = await es.indices.exists({ index: latestIndexName, From ac80b2af6363e1760f4f63c8801048f9bf88b309 Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Mon, 16 Oct 2023 17:19:18 -0700 Subject: [PATCH 30/87] Fix failing applications navigation test (#168302) fix [#166677 ](https://github.com/elastic/kibana/issues/166677) - [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: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../test_suites/core_plugins/applications.ts | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/test/plugin_functional/test_suites/core_plugins/applications.ts b/test/plugin_functional/test_suites/core_plugins/applications.ts index 22ad0b83729006..d8ad792c6e5bc7 100644 --- a/test/plugin_functional/test_suites/core_plugins/applications.ts +++ b/test/plugin_functional/test_suites/core_plugins/applications.ts @@ -11,8 +11,7 @@ import expect from '@kbn/expect'; import { PluginFunctionalProviderContext } from '../../services'; export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) { - const PageObjects = getPageObjects(['common']); - + const PageObjects = getPageObjects(['common', 'header']); const browser = getService('browser'); const appsMenu = getService('appsMenu'); const testSubjects = getService('testSubjects'); @@ -20,6 +19,11 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide const retry = getService('retry'); const deployment = getService('deployment'); const esArchiver = getService('esArchiver'); + const log = getService('log'); + + function waitUntilLoadingIsDone() { + return PageObjects.header.waitUntilLoadingHasFinished(); + } const loadingScreenNotShown = async () => expect(await testSubjects.exists('kbnLoadingMessage')).to.be(false); @@ -38,19 +42,28 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide search, }); + async function navigateToAppFromAppsMenu(title: string) { + await retry.try(async () => { + await appsMenu.clickLink(title); + await waitUntilLoadingIsDone(); + }); + } + /** Use retry logic to make URL assertions less flaky */ const waitForUrlToBe = (pathname?: string, search?: string) => { const expectedUrl = getKibanaUrl(pathname, search); return retry.waitFor(`Url to be ${expectedUrl}`, async () => { - return (await browser.getCurrentUrl()) === expectedUrl; + const currentUrl = await browser.getCurrentUrl(); + if (currentUrl !== expectedUrl) + log.debug(`expected url to be ${expectedUrl}, got ${currentUrl}`); + return currentUrl === expectedUrl; }); }; const navigateTo = async (path: string) => await browser.navigateTo(`${deployment.getHostPort()}${path}`); - // Failing: See https://github.com/elastic/kibana/issues/166677 - describe.skip('ui applications', function describeIndexTests() { + describe('ui applications', function describeIndexTests() { before(async () => { await esArchiver.emptyKibanaIndex(); await PageObjects.common.navigateToApp('foo'); @@ -92,9 +105,12 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide }); it('navigates to app root when navlink is clicked', async () => { - await appsMenu.clickLink('Foo'); + await testSubjects.click('fooNavHome'); + + navigateToAppFromAppsMenu('Foo'); + await waitForUrlToBe('/app/foo/home'); - // await loadingScreenNotShown(); + await loadingScreenNotShown(); await testSubjects.existOrFail('fooAppHome'); }); From d0e99258c68d57bc83788724814783ece176aa78 Mon Sep 17 00:00:00 2001 From: Andrew Macri Date: Mon, 16 Oct 2023 18:54:40 -0600 Subject: [PATCH 31/87] [Security Solution] [Elastic AI Assistant] Hybrid (vector + terms) search for improved ES|QL query generation (#168995) ## [Security Solution] [Elastic AI Assistant] Hybrid (vector + terms) search for improved ES|QL query generation This PR implements hybrid (vector + terms) search to improve the quality of `ES|QL` queries generated by the Elastic AI Assistant. The hybrid search combines (from a single request to Elasticsearch): - Vector search results from ELSER that vary depending on the query specified by the user - Terms search results that return a set of Knowledge Base (KB) documents marked as "required" for a topic The hybrid search results, when provided as context to an LLM, improve the quality of generated `ES|QL` queries by combining `ES|QL` parser grammar and documentation specific to the question asked by a user with additional examples of valid `ES|QL` queries that aren't specific to the query. ## Details ### Indexing additional `metadata` The `loadESQL` function in `x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.ts` loads a directory containing 13 valid, and one invalid example of `ES|QL` queries: ```typescript const rawExampleQueries = await exampleQueriesLoader.load(); // Add additional metadata to the example queries that indicates they are required KB documents: const requiredExampleQueries = addRequiredKbResourceMetadata({ docs: rawExampleQueries, kbResource: ESQL_RESOURCE, }); ``` The `addRequiredKbResourceMetadata` function adds two additional fields to the `metadata` property of the document: - `kbResource` - a `keyword` field that specifies the category of knowledge, e.g. `esql` - `required` - a `boolean` field that when `true`, indicates the document should be returned in all searches for the `kbResource` The additional metadata fields are shown below in the following abridged sample document: ``` { "_index": ".kibana-elastic-ai-assistant-kb", "_id": "e297e2d9-fb0e-4638-b4be-af31d1b31b9f", "_version": 1, "_seq_no": 129, "_primary_term": 1, "found": true, "_source": { "metadata": { "source": "/Users/andrew.goldstein/Projects/forks/andrew-goldstein/kibana/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0001.asciidoc", "required": true, "kbResource": "esql" }, "vector": { "tokens": { "serial": 0.5612584, "syntax": 0.006727545, "user": 1.1184403, // ...additional tokens }, "model_id": ".elser_model_2" }, "text": """[[esql-example-queries]] The following is an example ES|QL query: \`\`\` FROM logs-* | WHERE NOT CIDR_MATCH(destination.ip, "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16") | STATS destcount = COUNT(destination.ip) by user.name, host.name | ENRICH ldap_lookup_new ON user.name | WHERE group.name IS NOT NULL | EVAL follow_up = CASE( destcount >= 100, "true", "false") | SORT destcount desc | KEEP destcount, host.name, user.name, group.name, follow_up \`\`\` """ } } ``` ### Hybrid search The `ElasticsearchStore.similaritySearch` function is invoked by LangChain's `VectorStoreRetriever.getRelevantDocuments` function when the `RetrievalQAChain` searches for documents. A single request to Elasticsearch performs a hybrid search that combines the vector and terms searches into a single request with an [msearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html): ```typescript // requiredDocs is an array of filters that can be used in a `bool` Elasticsearch DSL query to filter in/out required KB documents: const requiredDocs = getRequiredKbDocsTermsQueryDsl(this.kbResource); // The `k` parameter is typically provided by LangChain's `VectorStoreRetriever._getRelevantDocuments`, which calls this function: const vectorSearchQuerySize = k ?? FALLBACK_SIMILARITY_SEARCH_SIZE; // build a vector search query: const vectorSearchQuery = getVectorSearchQuery({ filter, modelId: this.model, mustNotTerms: requiredDocs, query, }); // build a (separate) terms search query: const termsSearchQuery = getTermsSearchQuery(requiredDocs); // combine the vector search query and the terms search queries into a single multi-search query: const mSearchQueryBody = getMsearchQueryBody({ index: this.index, termsSearchQuery, termsSearchQuerySize: TERMS_QUERY_SIZE, vectorSearchQuery, vectorSearchQuerySize, }); try { // execute both queries via a single multi-search request: const result = await this.esClient.msearch(mSearchQueryBody); // flatten the results of the combined queries into a single array of hits: const results: FlattenedHit[] = result.responses.flatMap((response) => // ... ``` ## Desk testing 1. Delete any previous instances of the Knowledge Base by executing the following query in Kibana's `Dev Tools`: ``` DELETE .kibana-elastic-ai-assistant-kb ``` 2. In the Security Solution, open the Elastic AI Assistant 3. In the assistant, click the `Settings` gear 4. Click the `Knowledge Base` icon to view the KB settings 5. Toggle the `Knowledge Base` setting `off` if it's already on 6. Toggle the `Knowledge Base` setting `on` to load the KB documents 7. Click the `Save` button to close settings 8. Enter the following prompt, then press Enter: ``` Generate an ES|QL query that will count the number of connections made to external IP addresses, broken down by user. If the count is greater than 100 for a specific user, add a new field called "follow_up" that contains a value of "true", otherwise, it should contain "false". The user names should also be enriched with their respective group names. ``` **Expected result** A response similar to the following is returned: ``` FROM logs-* | WHERE NOT CIDR_MATCH(destination.ip, "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16") | STATS destcount = COUNT(destination.ip) BY user.name | ENRICH ldap_lookup ON user.name | EVAL follow_up = CASE( destcount >= 100, "true", "false") | SORT destcount DESC | KEEP destcount, user.name, group.name, follow_up ``` --- .../__mocks__/docs_from_directory_loader.ts | 74 +++++++ .../server/__mocks__/msearch_query.ts | 75 +++++++ .../server/__mocks__/msearch_response.ts | 101 +++++++++ .../server/__mocks__/query_text.ts | 28 +++ .../server/__mocks__/terms.ts | 28 +++ .../server/__mocks__/terms_search_query.ts | 28 +++ .../server/__mocks__/vector_search_query.ts | 39 ++++ .../server/knowledge_base/README.md | 7 +- .../esql_example_query_0001.asciidoc | 16 ++ .../esql_example_query_0002.asciidoc | 11 + .../esql_example_query_0003.asciidoc | 14 ++ .../esql_example_query_0004.asciidoc | 15 ++ .../esql_example_query_0005.asciidoc | 13 ++ .../esql_example_query_0006.asciidoc | 10 + .../esql_example_query_0007.asciidoc | 10 + .../esql_example_query_0008.asciidoc | 11 + .../esql_example_query_0009.asciidoc | 7 + .../esql_example_query_0010.asciidoc | 11 + .../esql_example_query_0011.asciidoc | 13 ++ .../esql_example_query_0012.asciidoc | 9 + .../esql_example_query_0013.asciidoc | 10 + .../esql_example_query_0014.asciidoc | 9 + .../add_required_kb_resource_metadata.test.ts | 51 +++++ .../add_required_kb_resource_metadata.ts | 36 +++ .../content_loaders/esql_loader.test.ts | 112 ++++++++++ .../langchain/content_loaders/esql_loader.ts | 36 ++- .../elasticsearch_store.test.ts | 207 ++++++++++++++---- .../elasticsearch_store.ts | 121 ++++++---- .../helpers/get_flattened_hits.test.ts | 81 +++++++ .../helpers/get_flattened_hits.ts | 37 ++++ .../helpers/get_msearch_query_body.test.ts | 46 ++++ .../helpers/get_msearch_query_body.ts | 67 ++++++ ...t_required_kb_docs_terms_query_dsl.test.ts | 21 ++ .../get_required_kb_docs_terms_query_dsl.ts | 35 +++ .../helpers/get_terms_search_query.test.ts | 21 ++ .../helpers/get_terms_search_query.ts | 29 +++ .../helpers/get_vector_search_query.test.ts | 129 +++++++++++ .../helpers/get_vector_search_query.ts | 51 +++++ .../elasticsearch_store/helpers/types.ts | 48 ++++ .../execute_custom_llm_chain/index.test.ts | 13 +- .../execute_custom_llm_chain/index.ts | 9 +- .../server/lib/langchain/executors/types.ts | 1 + .../server/routes/evaluate/post_evaluate.ts | 5 +- .../knowledge_base/get_kb_resource.test.ts | 40 ++++ .../routes/knowledge_base/get_kb_resource.ts | 30 +++ .../get_knowledge_base_status.ts | 9 +- .../knowledge_base/post_knowledge_base.ts | 9 +- .../routes/post_actions_connector_execute.ts | 2 + .../content/prompts/system/translations.ts | 2 +- 49 files changed, 1673 insertions(+), 114 deletions(-) create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/docs_from_directory_loader.ts create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/msearch_query.ts create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/msearch_response.ts create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/query_text.ts create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/terms.ts create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/terms_search_query.ts create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/vector_search_query.ts create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0001.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0002.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0003.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0004.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0005.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0006.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0007.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0008.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0009.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0010.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0011.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0012.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0013.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0014.asciidoc create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/add_required_kb_resource_metadata.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/add_required_kb_resource_metadata.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_flattened_hits.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_flattened_hits.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_msearch_query_body.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_msearch_query_body.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_required_kb_docs_terms_query_dsl.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_required_kb_docs_terms_query_dsl.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_terms_search_query.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_terms_search_query.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_vector_search_query.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_vector_search_query.ts create mode 100644 x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/types.ts create mode 100644 x-pack/plugins/elastic_assistant/server/routes/knowledge_base/get_kb_resource.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/routes/knowledge_base/get_kb_resource.ts diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/docs_from_directory_loader.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/docs_from_directory_loader.ts new file mode 100644 index 00000000000000..71100d68b73ad0 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/docs_from_directory_loader.ts @@ -0,0 +1,74 @@ +/* + * 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 { Document } from 'langchain/document'; + +/** + * Mock LangChain `Document`s from `knowledge_base/esql/docs`, loaded from a LangChain `DirectoryLoader` + */ +export const mockEsqlDocsFromDirectoryLoader: Document[] = [ + { + pageContent: + '[[esql-agg-avg]]\n=== `AVG`\nThe average of a numeric field.\n\n[source.merge.styled,esql]\n----\ninclude::{esql-specs}/stats.csv-spec[tag=avg]\n----\n[%header.monospaced.styled,format=dsv,separator=|]\n|===\ninclude::{esql-specs}/stats.csv-spec[tag=avg-result]\n|===\n\nThe result is always a `double` not matter the input type.\n', + metadata: { + source: + '/Users/andrew.goldstein/Projects/forks/andrew-goldstein/kibana/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/docs/aggregation_functions/avg.asciidoc', + }, + }, +]; + +/** + * Mock LangChain `Document`s from `knowledge_base/esql/language_definition`, loaded from a LangChain `DirectoryLoader` + */ +export const mockEsqlLanguageDocsFromDirectoryLoader: Document[] = [ + { + pageContent: + "lexer grammar EsqlBaseLexer;\n\nDISSECT : 'dissect' -> pushMode(EXPRESSION);\nDROP : 'drop' -> pushMode(SOURCE_IDENTIFIERS);\nENRICH : 'enrich' -> pushMode(SOURCE_IDENTIFIERS);\nEVAL : 'eval' -> pushMode(EXPRESSION);\nEXPLAIN : 'explain' -> pushMode(EXPLAIN_MODE);\nFROM : 'from' -> pushMode(SOURCE_IDENTIFIERS);\nGROK : 'grok' -> pushMode(EXPRESSION);\nINLINESTATS : 'inlinestats' -> pushMode(EXPRESSION);\nKEEP : 'keep' -> pushMode(SOURCE_IDENTIFIERS);\nLIMIT : 'limit' -> pushMode(EXPRESSION);\nMV_EXPAND : 'mv_expand' -> pushMode(SOURCE_IDENTIFIERS);\nPROJECT : 'project' -> pushMode(SOURCE_IDENTIFIERS);\nRENAME : 'rename' -> pushMode(SOURCE_IDENTIFIERS);\nROW : 'row' -> pushMode(EXPRESSION);\nSHOW : 'show' -> pushMode(EXPRESSION);\nSORT : 'sort' -> pushMode(EXPRESSION);\nSTATS : 'stats' -> pushMode(EXPRESSION);\nWHERE : 'where' -> pushMode(EXPRESSION);\nUNKNOWN_CMD : ~[ \\r\\n\\t[\\]/]+ -> pushMode(EXPRESSION);\n\nLINE_COMMENT\n : '//' ~[\\r\\n]* '\\r'? '\\n'? -> channel(HIDDEN)\n ;\n\nMULTILINE_COMMENT\n : '/*' (MULTILINE_COMMENT|.)*? '*/' -> channel(HIDDEN)\n ;\n\nWS\n : [ \\r\\n\\t]+ -> channel(HIDDEN)\n ;\n\n\nmode EXPLAIN_MODE;\nEXPLAIN_OPENING_BRACKET : '[' -> type(OPENING_BRACKET), pushMode(DEFAULT_MODE);\nEXPLAIN_PIPE : '|' -> type(PIPE), popMode;\nEXPLAIN_WS : WS -> channel(HIDDEN);\nEXPLAIN_LINE_COMMENT : LINE_COMMENT -> channel(HIDDEN);\nEXPLAIN_MULTILINE_COMMENT : MULTILINE_COMMENT -> channel(HIDDEN);\n\nmode EXPRESSION;\n\nPIPE : '|' -> popMode;\n\nfragment DIGIT\n : [0-9]\n ;\n\nfragment LETTER\n : [A-Za-z]\n ;\n\nfragment ESCAPE_SEQUENCE\n : '\\\\' [tnr\"\\\\]\n ;\n\nfragment UNESCAPED_CHARS\n : ~[\\r\\n\"\\\\]\n ;\n\nfragment EXPONENT\n : [Ee] [+-]? DIGIT+\n ;\n\nSTRING\n : '\"' (ESCAPE_SEQUENCE | UNESCAPED_CHARS)* '\"'\n | '\"\"\"' (~[\\r\\n])*? '\"\"\"' '\"'? '\"'?\n ;\n\nINTEGER_LITERAL\n : DIGIT+\n ;\n\nDECIMAL_LITERAL\n : DIGIT+ DOT DIGIT*\n | DOT DIGIT+\n | DIGIT+ (DOT DIGIT*)? EXPONENT\n | DOT DIGIT+ EXPONENT\n ;\n\nBY : 'by';\n\nAND : 'and';\nASC : 'asc';\nASSIGN : '=';\nCOMMA : ',';\nDESC : 'desc';\nDOT : '.';\nFALSE : 'false';\nFIRST : 'first';\nLAST : 'last';\nLP : '(';\nIN: 'in';\nIS: 'is';\nLIKE: 'like';\nNOT : 'not';\nNULL : 'null';\nNULLS : 'nulls';\nOR : 'or';\nPARAM: '?';\nRLIKE: 'rlike';\nRP : ')';\nTRUE : 'true';\nINFO : 'info';\nFUNCTIONS : 'functions';\n\nEQ : '==';\nNEQ : '!=';\nLT : '<';\nLTE : '<=';\nGT : '>';\nGTE : '>=';\n\nPLUS : '+';\nMINUS : '-';\nASTERISK : '*';\nSLASH : '/';\nPERCENT : '%';\n\n// Brackets are funny. We can happen upon a CLOSING_BRACKET in two ways - one\n// way is to start in an explain command which then shifts us to expression\n// mode. Thus, the two popModes on CLOSING_BRACKET. The other way could as\n// the start of a multivalued field constant. To line up with the double pop\n// the explain mode needs, we double push when we see that.\nOPENING_BRACKET : '[' -> pushMode(EXPRESSION), pushMode(EXPRESSION);\nCLOSING_BRACKET : ']' -> popMode, popMode;\n\n\nUNQUOTED_IDENTIFIER\n : LETTER (LETTER | DIGIT | '_')*\n // only allow @ at beginning of identifier to keep the option to allow @ as infix operator in the future\n // also, single `_` and `@` characters are not valid identifiers\n | ('_' | '@') (LETTER | DIGIT | '_')+\n ;\n\nQUOTED_IDENTIFIER\n : '`' ( ~'`' | '``' )* '`'\n ;\n\nEXPR_LINE_COMMENT\n : LINE_COMMENT -> channel(HIDDEN)\n ;\n\nEXPR_MULTILINE_COMMENT\n : MULTILINE_COMMENT -> channel(HIDDEN)\n ;\n\nEXPR_WS\n : WS -> channel(HIDDEN)\n ;\n\n\n\nmode SOURCE_IDENTIFIERS;\n\nSRC_PIPE : '|' -> type(PIPE), popMode;\nSRC_OPENING_BRACKET : '[' -> type(OPENING_BRACKET), pushMode(SOURCE_IDENTIFIERS), pushMode(SOURCE_IDENTIFIERS);\nSRC_CLOSING_BRACKET : ']' -> popMode, popMode, type(CLOSING_BRACKET);\nSRC_COMMA : ',' -> type(COMMA);\nSRC_ASSIGN : '=' -> type(ASSIGN);\nAS : 'as';\nMETADATA: 'metadata';\nON : 'on';\nWITH : 'with';\n\nSRC_UNQUOTED_IDENTIFIER\n : SRC_UNQUOTED_IDENTIFIER_PART+\n ;\n\nfragment SRC_UNQUOTED_IDENTIFIER_PART\n : ~[=`|,[\\]/ \\t\\r\\n]+\n | '/' ~[*/] // allow single / but not followed by another / or * which would start a comment\n ;\n\nSRC_QUOTED_IDENTIFIER\n : QUOTED_IDENTIFIER\n ;\n\nSRC_LINE_COMMENT\n : LINE_COMMENT -> channel(HIDDEN)\n ;\n\nSRC_MULTILINE_COMMENT\n : MULTILINE_COMMENT -> channel(HIDDEN)\n ;\n\nSRC_WS\n : WS -> channel(HIDDEN)\n ;\n", + metadata: { + source: + '/Users/andrew.goldstein/Projects/forks/andrew-goldstein/kibana/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/language_definition/esql_base_lexer.g4', + }, + }, + { + pageContent: + "DISSECT=1\nDROP=2\nENRICH=3\nEVAL=4\nEXPLAIN=5\nFROM=6\nGROK=7\nINLINESTATS=8\nKEEP=9\nLIMIT=10\nMV_EXPAND=11\nPROJECT=12\nRENAME=13\nROW=14\nSHOW=15\nSORT=16\nSTATS=17\nWHERE=18\nUNKNOWN_CMD=19\nLINE_COMMENT=20\nMULTILINE_COMMENT=21\nWS=22\nEXPLAIN_WS=23\nEXPLAIN_LINE_COMMENT=24\nEXPLAIN_MULTILINE_COMMENT=25\nPIPE=26\nSTRING=27\nINTEGER_LITERAL=28\nDECIMAL_LITERAL=29\nBY=30\nAND=31\nASC=32\nASSIGN=33\nCOMMA=34\nDESC=35\nDOT=36\nFALSE=37\nFIRST=38\nLAST=39\nLP=40\nIN=41\nIS=42\nLIKE=43\nNOT=44\nNULL=45\nNULLS=46\nOR=47\nPARAM=48\nRLIKE=49\nRP=50\nTRUE=51\nINFO=52\nFUNCTIONS=53\nEQ=54\nNEQ=55\nLT=56\nLTE=57\nGT=58\nGTE=59\nPLUS=60\nMINUS=61\nASTERISK=62\nSLASH=63\nPERCENT=64\nOPENING_BRACKET=65\nCLOSING_BRACKET=66\nUNQUOTED_IDENTIFIER=67\nQUOTED_IDENTIFIER=68\nEXPR_LINE_COMMENT=69\nEXPR_MULTILINE_COMMENT=70\nEXPR_WS=71\nAS=72\nMETADATA=73\nON=74\nWITH=75\nSRC_UNQUOTED_IDENTIFIER=76\nSRC_QUOTED_IDENTIFIER=77\nSRC_LINE_COMMENT=78\nSRC_MULTILINE_COMMENT=79\nSRC_WS=80\nEXPLAIN_PIPE=81\n'dissect'=1\n'drop'=2\n'enrich'=3\n'eval'=4\n'explain'=5\n'from'=6\n'grok'=7\n'inlinestats'=8\n'keep'=9\n'limit'=10\n'mv_expand'=11\n'project'=12\n'rename'=13\n'row'=14\n'show'=15\n'sort'=16\n'stats'=17\n'where'=18\n'by'=30\n'and'=31\n'asc'=32\n'desc'=35\n'.'=36\n'false'=37\n'first'=38\n'last'=39\n'('=40\n'in'=41\n'is'=42\n'like'=43\n'not'=44\n'null'=45\n'nulls'=46\n'or'=47\n'?'=48\n'rlike'=49\n')'=50\n'true'=51\n'info'=52\n'functions'=53\n'=='=54\n'!='=55\n'<'=56\n'<='=57\n'>'=58\n'>='=59\n'+'=60\n'-'=61\n'*'=62\n'/'=63\n'%'=64\n']'=66\n'as'=72\n'metadata'=73\n'on'=74\n'with'=75\n", + metadata: { + source: + '/Users/andrew.goldstein/Projects/forks/andrew-goldstein/kibana/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/language_definition/esql_base_lexer.tokens', + }, + }, +]; + +/** + * Mock LangChain `Document`s from `knowledge_base/esql/example_queries`, loaded from a LangChain `DirectoryLoader` + */ +export const mockExampleQueryDocsFromDirectoryLoader: Document[] = [ + { + pageContent: + '[[esql-example-queries]]\n\nThe following is an example an ES|QL query:\n\n```\nFROM logs-*\n| WHERE NOT CIDR_MATCH(destination.ip, "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16")\n| STATS destcount = COUNT(destination.ip) by user.name, host.name\n| ENRICH ldap_lookup_new ON user.name\n| WHERE group.name IS NOT NULL\n| EVAL follow_up = CASE(\n destcount >= 100, "true",\n "false")\n| SORT destcount desc\n| KEEP destcount, host.name, user.name, group.name, follow_up\n```\n', + metadata: { + source: + '/Users/andrew.goldstein/Projects/forks/andrew-goldstein/kibana/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0001.asciidoc', + }, + }, + { + pageContent: + '[[esql-example-queries]]\n\nThe following is an example an ES|QL query:\n\n```\nfrom logs-*\n| grok dns.question.name "%{DATA}\\\\.%{GREEDYDATA:dns.question.registered_domain:string}"\n| stats unique_queries = count_distinct(dns.question.name) by dns.question.registered_domain, process.name\n| where unique_queries > 5\n| sort unique_queries desc\n```\n', + metadata: { + source: + '/Users/andrew.goldstein/Projects/forks/andrew-goldstein/kibana/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0002.asciidoc', + }, + }, + { + pageContent: + '[[esql-example-queries]]\n\nThe following is an example an ES|QL query:\n\n```\nfrom logs-*\n| where event.code is not null\n| stats event_code_count = count(event.code) by event.code,host.name\n| enrich win_events on event.code with EVENT_DESCRIPTION\n| where EVENT_DESCRIPTION is not null and host.name is not null\n| rename EVENT_DESCRIPTION as event.description\n| sort event_code_count desc\n| keep event_code_count,event.code,host.name,event.description\n```\n', + metadata: { + source: + '/Users/andrew.goldstein/Projects/forks/andrew-goldstein/kibana/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0003.asciidoc', + }, + }, +]; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/msearch_query.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/msearch_query.ts new file mode 100644 index 00000000000000..a52e9faed130c4 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/msearch_query.ts @@ -0,0 +1,75 @@ +/* + * 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 { QueryDslTextExpansionQuery } from '@elastic/elasticsearch/lib/api/types'; + +import type { MsearchQueryBody } from '../lib/langchain/elasticsearch_store/helpers/get_msearch_query_body'; + +/** + * This mock Elasticsearch msearch request body contains two queries: + * - The first query is a similarity (vector) search + * - The second query is a required KB document (terms) search + */ +export const mSearchQueryBody: MsearchQueryBody = { + body: [ + { + index: '.kibana-elastic-ai-assistant-kb', + }, + { + query: { + bool: { + must_not: [ + { + term: { + 'metadata.kbResource': 'esql', + }, + }, + { + term: { + 'metadata.required': true, + }, + }, + ], + must: [ + { + text_expansion: { + 'vector.tokens': { + model_id: '.elser_model_2', + model_text: + 'Generate an ESQL query that will count the number of connections made to external IP addresses, broken down by user. If the count is greater than 100 for a specific user, add a new field called "follow_up" that contains a value of "true", otherwise, it should contain "false". The user names should also be enriched with their respective group names.', + }, + } as unknown as QueryDslTextExpansionQuery, + }, + ], + }, + }, + size: 1, + }, + { + index: '.kibana-elastic-ai-assistant-kb', + }, + { + query: { + bool: { + must: [ + { + term: { + 'metadata.kbResource': 'esql', + }, + }, + { + term: { + 'metadata.required': true, + }, + }, + ], + }, + }, + size: 1, + }, + ], +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/msearch_response.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/msearch_response.ts new file mode 100644 index 00000000000000..f281140b34b383 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/msearch_response.ts @@ -0,0 +1,101 @@ +/* + * 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 { MsearchResponse } from '@elastic/elasticsearch/lib/api/types'; + +/** + * This mock response from an Elasticsearch msearch contains two hits, where + * the first hit is from a similarity (vector) search, and the second hit is a + * required KB document (terms) search. + */ +export const mockMsearchResponse: MsearchResponse = { + took: 142, + responses: [ + { + took: 142, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + hits: { + total: { + value: 129, + relation: 'eq', + }, + max_score: 21.658352, + hits: [ + { + _index: '.kibana-elastic-ai-assistant-kb', + _id: 'fa1c8ba1-25c9-4404-9736-09b7eb7124f8', + _score: 21.658352, + _ignored: ['text.keyword'], + _source: { + metadata: { + source: + '/Users/andrew.goldstein/Projects/forks/andrew-goldstein/kibana/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/docs/source_commands/from.asciidoc', + }, + vector: { + tokens: { + wild: 1.2001507, + // truncated for mock + }, + model_id: '.elser_model_2', + }, + text: "[[esql-from]]\n=== `FROM`\n\nThe `FROM` source command returns a table with up to 10,000 documents from a\ndata stream, index, or alias. Each row in the resulting table represents a\ndocument. Each column corresponds to a field, and can be accessed by the name\nof that field.\n\n[source,esql]\n----\nFROM employees\n----\n\nYou can use <> to refer to indices, aliases\nand data streams. This can be useful for time series data, for example to access\ntoday's index:\n\n[source,esql]\n----\nFROM \n----\n\nUse comma-separated lists or wildcards to query multiple data streams, indices,\nor aliases:\n\n[source,esql]\n----\nFROM employees-00001,employees-*\n----\n", + }, + }, + ], + }, + status: 200, + }, + { + took: 3, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + hits: { + total: { + value: 14, + relation: 'eq', + }, + max_score: 0.034783483, + hits: [ + { + _index: '.kibana-elastic-ai-assistant-kb', + _id: '280d4882-0f64-4471-a268-669a3f8c958f', + _score: 0.034783483, + _ignored: ['text.keyword'], + _source: { + metadata: { + source: + '/Users/andrew.goldstein/Projects/forks/andrew-goldstein/kibana/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0001.asciidoc', + required: true, + kbResource: 'esql', + }, + vector: { + tokens: { + user: 1.1084619, + // truncated for mock + }, + model_id: '.elser_model_2', + }, + text: '[[esql-example-queries]]\n\nThe following is an example an ES|QL query:\n\n```\nFROM logs-*\n| WHERE NOT CIDR_MATCH(destination.ip, "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16")\n| STATS destcount = COUNT(destination.ip) by user.name, host.name\n| ENRICH ldap_lookup_new ON user.name\n| WHERE group.name IS NOT NULL\n| EVAL follow_up = CASE(\n destcount >= 100, "true",\n "false")\n| SORT destcount desc\n| KEEP destcount, host.name, user.name, group.name, follow_up\n```\n', + }, + }, + ], + }, + status: 200, + }, + ], +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/query_text.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/query_text.ts new file mode 100644 index 00000000000000..1ea69b786ad1fa --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/query_text.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +/** + * This mock query text is an example of a prompt that might be passed to + * the `ElasticSearchStore`'s `similaritySearch` function, as the `query` + * parameter. + * + * In the real world, an LLM extracted the `mockQueryText` from the + * following prompt, which includes a system prompt: + * + * ``` + * You are a helpful, expert assistant who answers questions about Elastic Security. Do not answer questions unrelated to Elastic Security. + * If you answer a question related to KQL, EQL, or ES|QL, it should be immediately usable within an Elastic Security timeline; please always format the output correctly with back ticks. Any answer provided for Query DSL should also be usable in a security timeline. This means you should only ever include the "filter" portion of the query. + * + * Use the following context to answer questions: + * + * Generate an ES|QL query that will count the number of connections made to external IP addresses, broken down by user. If the count is greater than 100 for a specific user, add a new field called "follow_up" that contains a value of "true", otherwise, it should contain "false". The user names should also be enriched with their respective group names. + * ``` + * + * In the example above, the LLM omitted the system prompt, such that only `mockQueryText` is passed to the `similaritySearch` function. + */ +export const mockQueryText = + 'Generate an ES|QL query that will count the number of connections made to external IP addresses, broken down by user. If the count is greater than 100 for a specific user, add a new field called follow_up that contains a value of true, otherwise, it should contain false. The user names should also be enriched with their respective group names.'; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/terms.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/terms.ts new file mode 100644 index 00000000000000..0606c905d6df3a --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/terms.ts @@ -0,0 +1,28 @@ +/* + * 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 { Field, FieldValue, QueryDslTermQuery } from '@elastic/elasticsearch/lib/api/types'; + +/** + * These (mock) terms may be used in multiple queries. + * + * For example, it may be be used in a vector search to exclude the required `esql` KB docs. + * + * It may also be used in a terms search to find all of the required `esql` KB docs. + */ +export const mockTerms: Array>> = [ + { + term: { + 'metadata.kbResource': 'esql', + }, + }, + { + term: { + 'metadata.required': true, + }, + }, +]; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/terms_search_query.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/terms_search_query.ts new file mode 100644 index 00000000000000..c8af748516a1f4 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/terms_search_query.ts @@ -0,0 +1,28 @@ +/* + * 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 { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; + +/** + * This Elasticsearch query DSL is a terms search for required `esql` KB docs + */ +export const mockTermsSearchQuery: QueryDslQueryContainer = { + bool: { + must: [ + { + term: { + 'metadata.kbResource': 'esql', + }, + }, + { + term: { + 'metadata.required': true, + }, + }, + ], + }, +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/vector_search_query.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/vector_search_query.ts new file mode 100644 index 00000000000000..30fbd0ad2c58f3 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/vector_search_query.ts @@ -0,0 +1,39 @@ +/* + * 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 { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; + +/** + * A mock vector search query DSL + */ +export const mockVectorSearchQuery: QueryDslQueryContainer = { + bool: { + must_not: [ + { + term: { + 'metadata.kbResource': 'esql', + }, + }, + { + term: { + 'metadata.required': true, + }, + }, + ], + must: [ + { + text_expansion: { + 'vector.tokens': { + model_id: '.elser_model_2', + model_text: + 'Generate an ES|QL query that will count the number of connections made to external IP addresses, broken down by user. If the count is greater than 100 for a specific user, add a new field called "follow_up" that contains a value of "true", otherwise, it should contain "false". The user names should also be enriched with their respective group names.', + }, + }, + }, + ], + }, +} as QueryDslQueryContainer; diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/README.md b/x-pack/plugins/elastic_assistant/server/knowledge_base/README.md index 9965a1624f7986..54c9c885b51893 100644 --- a/x-pack/plugins/elastic_assistant/server/knowledge_base/README.md +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/README.md @@ -3,12 +3,13 @@ This directory contains assets for the Knowledge Base feature. The assets are used by the Elastic AI Assistant to answer questions about content that the underlying model may not have been trained on. Initial assets are provided for the following categories: * ES|QL - * General Documentation as from: https://github.com/elastic/elasticsearch/tree/main/docs/reference/esql + * General Documentation as from: * Excluding `functions/signature/*.svg` - * ANTLR Language Definitions as from: https://github.com/elastic/elasticsearch/tree/main/x-pack/plugin/esql/src/main/antlr + * ANTLR Language Definitions as from: + * Sample queries that represent valid (and invalid) ES|QL queries, curated manually from a variety of sources The assets are stored in their original source format, so `.asciidoc` for documentation, and `.g4` and `.tokens` for the ANTLR language definitions. File names have been updated to be snake_case to satisfy Kibana linting rules. ### Future -Once asset format and chunking strategies are finalized, we may want to either move the assets to a shared package so they can be consumed by other plugins, or potentially ship the pre-packaged ELSER embeddings as part of a Fleet Integration. For now though, the assets will be included in their source format within the plugin, and can then be processed and embedded at runtime. \ No newline at end of file +Once asset format and chunking strategies are finalized, we may want to either move the assets to a shared package so they can be consumed by other plugins, or potentially ship the pre-packaged ELSER embeddings as part of a Fleet Integration. For now though, the assets will be included in their source format within the plugin, and can then be processed and embedded at runtime. diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0001.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0001.asciidoc new file mode 100644 index 00000000000000..a9373d4eec246c --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0001.asciidoc @@ -0,0 +1,16 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +FROM logs-* +| WHERE NOT CIDR_MATCH(destination.ip, "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16") +| STATS destcount = COUNT(destination.ip) by user.name, host.name +| ENRICH ldap_lookup_new ON user.name +| WHERE group.name IS NOT NULL +| EVAL follow_up = CASE( + destcount >= 100, "true", + "false") +| SORT destcount desc +| KEEP destcount, host.name, user.name, group.name, follow_up +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0002.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0002.asciidoc new file mode 100644 index 00000000000000..cb4e25ba9e0c3d --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0002.asciidoc @@ -0,0 +1,11 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +from logs-* +| grok dns.question.name "%{DATA}\\.%{GREEDYDATA:dns.question.registered_domain:string}" +| stats unique_queries = count_distinct(dns.question.name) by dns.question.registered_domain, process.name +| where unique_queries > 5 +| sort unique_queries desc +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0003.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0003.asciidoc new file mode 100644 index 00000000000000..61d4c48a810c56 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0003.asciidoc @@ -0,0 +1,14 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +from logs-* +| where event.code is not null +| stats event_code_count = count(event.code) by event.code,host.name +| enrich win_events on event.code with EVENT_DESCRIPTION +| where EVENT_DESCRIPTION is not null and host.name is not null +| rename EVENT_DESCRIPTION as event.description +| sort event_code_count desc +| keep event_code_count,event.code,host.name,event.description +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0004.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0004.asciidoc new file mode 100644 index 00000000000000..3a66208bfa1583 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0004.asciidoc @@ -0,0 +1,15 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +from logs-* +| where event.category == "file" and event.action == "creation" +| stats filecount = count(file.name) by process.name,host.name +| dissect process.name "%{process}.%{extension}" +| eval proclength = length(process.name) +| where proclength > 10 +| sort filecount,proclength desc +| limit 10 +| keep host.name,process.name,filecount,process,extension,fullproc,proclength +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0005.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0005.asciidoc new file mode 100644 index 00000000000000..d5a42c7ce21fd1 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0005.asciidoc @@ -0,0 +1,13 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +from logs-* +| where process.name == "curl.exe" +| stats bytes = sum(destination.bytes) by destination.address +| eval kb = bytes/1024 +| sort kb desc +| limit 10 +| keep kb,destination.address +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0006.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0006.asciidoc new file mode 100644 index 00000000000000..26009eccaf4a97 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0006.asciidoc @@ -0,0 +1,10 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +FROM metrics-apm* +| WHERE metricset.name == "transaction" AND metricset.interval == "1m" +| EVAL bucket = AUTO_BUCKET(transaction.duration.histogram, 50, , ) +| STATS avg_duration = AVG(transaction.duration.histogram) BY bucket +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0007.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0007.asciidoc new file mode 100644 index 00000000000000..88e0b2260ff11d --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0007.asciidoc @@ -0,0 +1,10 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +FROM packetbeat-* +| STATS doc_count = COUNT(destination.domain) BY destination.domain +| SORT doc_count DESC +| LIMIT 10 +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0008.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0008.asciidoc new file mode 100644 index 00000000000000..333ae968c020c0 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0008.asciidoc @@ -0,0 +1,11 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +FROM employees +| EVAL hire_date_formatted = DATE_FORMAT(hire_date, "MMMM yyyy") +| SORT hire_date +| KEEP emp_no, hire_date_formatted +| LIMIT 5 +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0009.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0009.asciidoc new file mode 100644 index 00000000000000..f9762b0f695be8 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0009.asciidoc @@ -0,0 +1,7 @@ +[[esql-example-queries]] + +The following is NOT an example of an ES|QL query: + +``` +Pagination is not supported +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0010.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0010.asciidoc new file mode 100644 index 00000000000000..ee361169eecf0d --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0010.asciidoc @@ -0,0 +1,11 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +FROM logs-* +| WHERE @timestamp >= NOW() - 15 minutes +| EVAL bucket = DATE_TRUNC(1 minute, @timestamp) +| STATS avg_cpu = AVG(system.cpu.total.norm.pct) BY bucket, host.name +| LIMIT 10 +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0011.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0011.asciidoc new file mode 100644 index 00000000000000..0e3cf73139ff99 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0011.asciidoc @@ -0,0 +1,13 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +FROM traces-apm* +| WHERE @timestamp >= NOW() - 24 hours +| EVAL successful = CASE(event.outcome == "success", 1, 0), + failed = CASE(event.outcome == "failure", 1, 0) +| STATS success_rate = AVG(successful), + avg_duration = AVG(transaction.duration), + total_requests = COUNT(transaction.id) BY service.name +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0012.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0012.asciidoc new file mode 100644 index 00000000000000..e940b57368fbff --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0012.asciidoc @@ -0,0 +1,9 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +FROM metricbeat* +| EVAL cpu_pct_normalized = (system.cpu.user.pct + system.cpu.system.pct) / system.cpu.cores +| STATS AVG(cpu_pct_normalized) BY host.name +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0013.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0013.asciidoc new file mode 100644 index 00000000000000..657b5e7397ab53 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0013.asciidoc @@ -0,0 +1,10 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +FROM postgres-logs +| DISSECT message "%{} duration: %{query_duration} ms" +| EVAL query_duration_num = TO_DOUBLE(query_duration) +| STATS avg_duration = AVG(query_duration_num) +``` diff --git a/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0014.asciidoc b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0014.asciidoc new file mode 100644 index 00000000000000..d303642641aa3e --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0014.asciidoc @@ -0,0 +1,9 @@ +[[esql-example-queries]] + +The following is an example ES|QL query: + +``` +FROM nyc_taxis +| WHERE DATE_EXTRACT(drop_off_time, "hour") >= 6 AND DATE_EXTRACT(drop_off_time, "hour") < 10 +| LIMIT 10 +``` diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/add_required_kb_resource_metadata.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/add_required_kb_resource_metadata.test.ts new file mode 100644 index 00000000000000..b77e20a1030ff4 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/add_required_kb_resource_metadata.test.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 { addRequiredKbResourceMetadata } from './add_required_kb_resource_metadata'; +import { mockExampleQueryDocsFromDirectoryLoader } from '../../../__mocks__/docs_from_directory_loader'; + +describe('addRequiredKbResourceMetadata', () => { + const kbResource = 'esql'; + + test('it includes the original metadata properties', () => { + const EXPECTED_ADDITIONAL_KEYS_COUNT = 2; // two keys, `kbResource` and `required` + + const transformedDocs = addRequiredKbResourceMetadata({ + docs: mockExampleQueryDocsFromDirectoryLoader, + kbResource, + }); + + transformedDocs.forEach((doc, i) => { + expect(Object.keys(doc.metadata).length).toEqual( + Object.keys(mockExampleQueryDocsFromDirectoryLoader[i].metadata).length + + EXPECTED_ADDITIONAL_KEYS_COUNT + ); + }); + }); + + test('it adds the expected `kbResource` metadata to each document', () => { + const transformedDocs = addRequiredKbResourceMetadata({ + docs: mockExampleQueryDocsFromDirectoryLoader, + kbResource, + }); + + transformedDocs.forEach((doc) => { + expect(doc.metadata).toHaveProperty('kbResource', kbResource); + }); + }); + + test('it adds the expected `required` metadata to each document', () => { + const transformedDocs = addRequiredKbResourceMetadata({ + docs: mockExampleQueryDocsFromDirectoryLoader, + kbResource, + }); + + transformedDocs.forEach((doc) => { + expect(doc.metadata).toHaveProperty('required', true); + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/add_required_kb_resource_metadata.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/add_required_kb_resource_metadata.ts new file mode 100644 index 00000000000000..43804cc344f5b0 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/add_required_kb_resource_metadata.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 { Document } from 'langchain/document'; + +/** + * Transforms a set of documents by adding metadata that indicates those documents are required + * + * An additional property, `metadata`, is added to each document if it doesn't already exist. + * + * The `metadata` property is an object that contains the following properties: + * - the original metadata properties of the document (when they exist) + * - `kbResource`: The name of the Knowledge Base resource that the document belongs to + * - `required`: A boolean indicating whether the document is required for searches on the kbResource topic + * + * @returns A transformed set of documents, such that each document has the required metadata + */ +export const addRequiredKbResourceMetadata = ({ + docs, + kbResource, +}: { + docs: Array>>; + kbResource: string; +}): Array>> => + docs.map((doc) => ({ + ...doc, + metadata: { + ...doc.metadata, + kbResource, + required: true, // indicates that the document is required for searches on the kbResource topic + }, + })); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.test.ts new file mode 100644 index 00000000000000..307f5fc3055bb0 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.test.ts @@ -0,0 +1,112 @@ +/* + * 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 { Logger } from '@kbn/core/server'; + +import { addRequiredKbResourceMetadata } from './add_required_kb_resource_metadata'; +import { ElasticsearchStore } from '../elasticsearch_store/elasticsearch_store'; +import { loadESQL } from './esql_loader'; +import { + mockEsqlDocsFromDirectoryLoader, + mockEsqlLanguageDocsFromDirectoryLoader, + mockExampleQueryDocsFromDirectoryLoader, +} from '../../../__mocks__/docs_from_directory_loader'; +import { ESQL_RESOURCE } from '../../../routes/knowledge_base/constants'; + +let mockLoad = jest.fn(); + +jest.mock('langchain/document_loaders/fs/directory', () => ({ + DirectoryLoader: jest.fn().mockImplementation(() => ({ + load: mockLoad, + })), +})); + +jest.mock('langchain/document_loaders/fs/text', () => ({ + TextLoader: jest.fn().mockImplementation(() => ({})), +})); + +const esStore = { + addDocuments: jest.fn().mockResolvedValue(['1', '2', '3', '4', '5']), +} as unknown as ElasticsearchStore; + +const logger = { + info: jest.fn(), + error: jest.fn(), +} as unknown as Logger; + +describe('loadESQL', () => { + beforeEach(() => { + jest.clearAllMocks(); + + mockLoad = jest + .fn() + .mockReturnValueOnce(mockEsqlDocsFromDirectoryLoader) + .mockReturnValueOnce(mockEsqlLanguageDocsFromDirectoryLoader) + .mockReturnValueOnce(mockExampleQueryDocsFromDirectoryLoader); + }); + + describe('loadESQL', () => { + beforeEach(async () => { + await loadESQL(esStore, logger); + }); + + it('loads ES|QL docs, language files, and example queries into the Knowledge Base', async () => { + expect(esStore.addDocuments).toHaveBeenCalledWith([ + ...mockEsqlDocsFromDirectoryLoader, + ...mockEsqlLanguageDocsFromDirectoryLoader, + ...addRequiredKbResourceMetadata({ + docs: mockExampleQueryDocsFromDirectoryLoader, + kbResource: ESQL_RESOURCE, + }), + ]); + }); + + it('logs the expected (distinct) counts for each category of documents', async () => { + expect((logger.info as jest.Mock).mock.calls[0][0]).toEqual( + 'Loading 1 ES|QL docs, 2 language docs, and 3 example queries into the Knowledge Base' + ); + }); + + it('logs the expected total of all documents loaded', async () => { + expect((logger.info as jest.Mock).mock.calls[1][0]).toEqual( + 'Loaded 5 ES|QL docs, language docs, and example queries into the Knowledge Base' + ); + }); + + it('does NOT log an error in the happy path', async () => { + expect(logger.error).not.toHaveBeenCalled(); + }); + }); + + it('returns true if documents were loaded', async () => { + (esStore.addDocuments as jest.Mock).mockResolvedValueOnce(['this is a response']); + + const result = await loadESQL(esStore, logger); + + expect(result).toBe(true); + }); + + it('returns false if documents were NOT loaded', async () => { + (esStore.addDocuments as jest.Mock).mockResolvedValueOnce([]); + + const result = await loadESQL(esStore, logger); + + expect(result).toBe(false); + }); + + it('logs the expected error if loading fails', async () => { + const error = new Error('Failed to load documents'); + (esStore.addDocuments as jest.Mock).mockRejectedValueOnce(error); + + await loadESQL(esStore, logger); + + expect(logger.error).toHaveBeenCalledWith( + 'Failed to load ES|QL docs, language docs, and example queries into the Knowledge Base', + error + ); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.ts index 5b7388be2ca093..33310183e3d109 100644 --- a/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.ts +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/content_loaders/esql_loader.ts @@ -6,11 +6,13 @@ */ import { Logger } from '@kbn/core/server'; - import { DirectoryLoader } from 'langchain/document_loaders/fs/directory'; import { TextLoader } from 'langchain/document_loaders/fs/text'; import { resolve } from 'path'; + import { ElasticsearchStore } from '../elasticsearch_store/elasticsearch_store'; +import { addRequiredKbResourceMetadata } from './add_required_kb_resource_metadata'; +import { ESQL_RESOURCE } from '../../../routes/knowledge_base/constants'; /** * Loads the ESQL docs and language files into the Knowledge Base. @@ -37,22 +39,46 @@ export const loadESQL = async (esStore: ElasticsearchStore, logger: Logger): Pro true ); + const exampleQueriesLoader = new DirectoryLoader( + resolve(__dirname, '../../../knowledge_base/esql/example_queries'), + { + '.asciidoc': (path) => new TextLoader(path), + }, + true + ); + const docs = await docsLoader.load(); const languageDocs = await languageLoader.load(); + const rawExampleQueries = await exampleQueriesLoader.load(); + + // Add additional metadata to the example queries that indicates they are required KB documents: + const requiredExampleQueries = addRequiredKbResourceMetadata({ + docs: rawExampleQueries, + kbResource: ESQL_RESOURCE, + }); logger.info( - `Loading ${docs.length} ESQL docs and ${languageDocs.length} language docs into the Knowledge Base` + `Loading ${docs.length} ES|QL docs, ${languageDocs.length} language docs, and ${requiredExampleQueries.length} example queries into the Knowledge Base` ); - const response = await esStore.addDocuments([...docs, ...languageDocs]); + const response = await esStore.addDocuments([ + ...docs, + ...languageDocs, + ...requiredExampleQueries, + ]); logger.info( - `Loaded ${response?.length ?? 0} ESQL docs and language docs into the Knowledge Base` + `Loaded ${ + response?.length ?? 0 + } ES|QL docs, language docs, and example queries into the Knowledge Base` ); return response.length > 0; } catch (e) { - logger.error(`Failed to load ESQL docs and language docs into the Knowledge Base`, e); + logger.error( + `Failed to load ES|QL docs, language docs, and example queries into the Knowledge Base`, + e + ); return false; } }; diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.test.ts index 94ac161d7abb1a..9d563e240064a6 100644 --- a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.test.ts +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.test.ts @@ -5,14 +5,21 @@ * 2.0. */ -import { Document } from 'langchain/document'; -import { ElasticsearchStore } from './elasticsearch_store'; import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; import { IndicesCreateResponse, MlGetTrainedModelsResponse, } from '@elastic/elasticsearch/lib/api/types'; +import { Document } from 'langchain/document'; + +import { + ElasticsearchStore, + FALLBACK_SIMILARITY_SEARCH_SIZE, + TERMS_QUERY_SIZE, +} from './elasticsearch_store'; +import { mockMsearchResponse } from '../../../__mocks__/msearch_response'; +import { mockQueryText } from '../../../__mocks__/query_text'; jest.mock('uuid', () => ({ v4: jest.fn(), @@ -63,7 +70,18 @@ describe('ElasticsearchStore', () => { expect(created).toBe(true); expect(mockEsClient.indices.create).toHaveBeenCalledWith({ index: KB_INDEX, - mappings: { properties: { vector: { properties: { tokens: { type: 'rank_features' } } } } }, + mappings: { + properties: { + metadata: { + properties: { + kbResource: { type: 'keyword' }, + required: { type: 'boolean' }, + source: { type: 'keyword' }, + }, + }, + vector: { properties: { tokens: { type: 'rank_features' } } }, + }, + }, settings: { default_pipeline: '.kibana-elastic-ai-assistant-kb-ingest-pipeline' }, }); }); @@ -197,59 +215,152 @@ describe('ElasticsearchStore', () => { describe('similaritySearch', () => { it('Checks if documents are found', async () => { - const query = 'find the docs!'; - mockEsClient.search.mockResolvedValue({ - took: 3, - timed_out: false, - _shards: { total: 1, successful: 1, skipped: 0, failed: 0 }, - hits: { - total: { value: 129, relation: 'eq' }, - max_score: 17.86367, - hits: [ - { - _index: '.kibana-elastic-ai-assistant-kb', - _id: 'b71ea007-8b46-4e02-81b4-485faad06e79', - _score: 9.308316, - _ignored: ['text.keyword'], - _source: { - metadata: { - source: '/found/in/test/land', - }, - vector: { - tokens: {}, - model_id: '.elser_model_2', - }, - text: 'documents', + mockEsClient.msearch.mockResolvedValue(mockMsearchResponse); + + const searchResults = await esStore.similaritySearch(mockQueryText); + + expect(searchResults).toStrictEqual([ + { + pageContent: + "[[esql-from]]\n=== `FROM`\n\nThe `FROM` source command returns a table with up to 10,000 documents from a\ndata stream, index, or alias. Each row in the resulting table represents a\ndocument. Each column corresponds to a field, and can be accessed by the name\nof that field.\n\n[source,esql]\n----\nFROM employees\n----\n\nYou can use <> to refer to indices, aliases\nand data streams. This can be useful for time series data, for example to access\ntoday's index:\n\n[source,esql]\n----\nFROM \n----\n\nUse comma-separated lists or wildcards to query multiple data streams, indices,\nor aliases:\n\n[source,esql]\n----\nFROM employees-00001,employees-*\n----\n", + metadata: { + source: + '/Users/andrew.goldstein/Projects/forks/andrew-goldstein/kibana/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/docs/source_commands/from.asciidoc', + }, + }, + { + pageContent: + '[[esql-example-queries]]\n\nThe following is an example an ES|QL query:\n\n```\nFROM logs-*\n| WHERE NOT CIDR_MATCH(destination.ip, "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16")\n| STATS destcount = COUNT(destination.ip) by user.name, host.name\n| ENRICH ldap_lookup_new ON user.name\n| WHERE group.name IS NOT NULL\n| EVAL follow_up = CASE(\n destcount >= 100, "true",\n "false")\n| SORT destcount desc\n| KEEP destcount, host.name, user.name, group.name, follow_up\n```\n', + metadata: { + source: + '/Users/andrew.goldstein/Projects/forks/andrew-goldstein/kibana/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/example_queries/esql_example_query_0001.asciidoc', + }, + }, + ]); + + expect(mockEsClient.msearch).toHaveBeenCalledWith({ + body: [ + { + index: '.elastic-assistant-kb', + }, + { + query: { + bool: { + must_not: [ + { + term: { + 'metadata.kbResource': 'esql', + }, + }, + { + term: { + 'metadata.required': true, + }, + }, + ], + must: [ + { + text_expansion: { + 'vector.tokens': { + model_id: '.elser_model_2', + model_text: mockQueryText, + }, + }, + }, + ], }, }, - ], - }, + size: FALLBACK_SIMILARITY_SEARCH_SIZE, // <-- `FALLBACK_SIMILARITY_SEARCH_SIZE` is used when `k` is not provided + }, + { + index: '.elastic-assistant-kb', + }, + { + query: { + bool: { + must: [ + { + term: { + 'metadata.kbResource': 'esql', + }, + }, + { + term: { + 'metadata.required': true, + }, + }, + ], + }, + }, + size: TERMS_QUERY_SIZE, + }, + ], }); + }); - const searchResults = await esStore.similaritySearch(query); + it('uses the value of `k` instead of the `FALLBACK_SIMILARITY_SEARCH_SIZE` when `k` is provided', async () => { + mockEsClient.msearch.mockResolvedValue(mockMsearchResponse); - expect(searchResults).toStrictEqual([ - new Document({ - pageContent: 'documents', - metadata: { source: '/found/in/test/land' }, - }), - ]); - expect(mockEsClient.search).toHaveBeenCalledWith({ - index: KB_INDEX, - query: { - bool: { - must: [ - { - text_expansion: { - 'vector.tokens': { - model_id: '.elser_model_2', - model_text: query, + const k = 4; + await esStore.similaritySearch(mockQueryText, k); + + expect(mockEsClient.msearch).toHaveBeenCalledWith({ + body: [ + { + index: '.elastic-assistant-kb', + }, + { + query: { + bool: { + must_not: [ + { + term: { + 'metadata.kbResource': 'esql', + }, + }, + { + term: { + 'metadata.required': true, + }, }, - }, + ], + must: [ + { + text_expansion: { + 'vector.tokens': { + model_id: '.elser_model_2', + model_text: mockQueryText, + }, + }, + }, + ], }, - ], + }, + size: k, // <-- `k` is used instead of `FALLBACK_SIMILARITY_SEARCH_SIZE` }, - }, + { + index: '.elastic-assistant-kb', + }, + { + query: { + bool: { + must: [ + { + term: { + 'metadata.kbResource': 'esql', + }, + }, + { + term: { + 'metadata.required': true, + }, + }, + ], + }, + }, + size: TERMS_QUERY_SIZE, + }, + ], }); }); }); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts index 99ce5fd39439d9..d135ffb734bd46 100644 --- a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts @@ -5,23 +5,26 @@ * 2.0. */ -import { Document } from 'langchain/document'; -import { Callbacks } from 'langchain/callbacks'; -import { VectorStore } from 'langchain/vectorstores/base'; import { ElasticsearchClient, Logger } from '@kbn/core/server'; - -import { - MappingTypeMapping, - QueryDslTextExpansionQuery, -} from '@elastic/elasticsearch/lib/api/types'; +import { MappingTypeMapping } from '@elastic/elasticsearch/lib/api/types'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; - +import { Callbacks } from 'langchain/callbacks'; +import { Document } from 'langchain/document'; +import { VectorStore } from 'langchain/vectorstores/base'; import * as uuid from 'uuid'; + import { ElasticsearchEmbeddings } from '../embeddings/elasticsearch_embeddings'; +import { FlattenedHit, getFlattenedHits } from './helpers/get_flattened_hits'; +import { getMsearchQueryBody } from './helpers/get_msearch_query_body'; +import { getTermsSearchQuery } from './helpers/get_terms_search_query'; +import { getVectorSearchQuery } from './helpers/get_vector_search_query'; +import type { MsearchResponse } from './helpers/types'; import { + ESQL_RESOURCE, KNOWLEDGE_BASE_INDEX_PATTERN, KNOWLEDGE_BASE_INGEST_PIPELINE, } from '../../../routes/knowledge_base/constants'; +import { getRequiredKbDocsTermsQueryDsl } from './helpers/get_required_kb_docs_terms_query_dsl'; interface CreatePipelineParams { id?: string; @@ -33,6 +36,19 @@ interface CreateIndexParams { pipeline?: string; } +/** + * A fallback for the the query `size` that determines how many documents to + * return from Elasticsearch when performing a similarity search. + * + * The size is typically determined by the implementation of LangChain's + * `VectorStoreRetriever._getRelevantDocuments` function, so this fallback is + * only required when using the `ElasticsearchStore` directly. + */ +export const FALLBACK_SIMILARITY_SEARCH_SIZE = 10; + +/** The maximum number of hits to return from a `terms` query, via the `size` parameter */ +export const TERMS_QUERY_SIZE = 10000; + /** * Basic ElasticsearchStore implementation only leveraging ELSER for storage and retrieval. */ @@ -44,17 +60,25 @@ export class ElasticsearchStore extends VectorStore { private readonly index: string; private readonly logger: Logger; private readonly model: string; + private readonly kbResource: string; _vectorstoreType(): string { return 'elasticsearch'; } - constructor(esClient: ElasticsearchClient, index: string, logger: Logger, model?: string) { + constructor( + esClient: ElasticsearchClient, + index: string, + logger: Logger, + model?: string, + kbResource?: string | undefined + ) { super(new ElasticsearchEmbeddings(logger), { esClient, index }); this.esClient = esClient; this.index = index ?? KNOWLEDGE_BASE_INDEX_PATTERN; this.logger = logger; this.model = model ?? '.elser_model_2'; + this.kbResource = kbResource ?? ESQL_RESOURCE; } /** @@ -150,6 +174,9 @@ export class ElasticsearchStore extends VectorStore { * @param filter Optional filter to apply to the search * @param _callbacks Optional callbacks * + * Fun facts: + * - This function is called by LangChain's `VectorStoreRetriever._getRelevantDocuments` + * - The `k` parameter is typically determined by LangChain's `VectorStoreRetriever._getRelevantDocuments`, and has been observed to default to `4` in the wild (see langchain/dist/vectorstores/base.ts) * @returns Promise of similar documents */ similaritySearch = async ( @@ -158,42 +185,42 @@ export class ElasticsearchStore extends VectorStore { filter?: this['FilterType'] | undefined, _callbacks?: Callbacks | undefined ): Promise => { - const queryBody: QueryDslQueryContainer = { - bool: { - must: [ - { - text_expansion: { - 'vector.tokens': { - model_id: this.model, - model_text: query, - }, - } as unknown as QueryDslTextExpansionQuery, - }, - ], - filter, - }, - }; + // requiredDocs is an array of filters that can be used in a `bool` Elasticsearch DSL query to filter in/out required KB documents: + const requiredDocs = getRequiredKbDocsTermsQueryDsl(this.kbResource); + + // The `k` parameter is typically provided by LangChain's `VectorStoreRetriever._getRelevantDocuments`, which calls this function: + const vectorSearchQuerySize = k ?? FALLBACK_SIMILARITY_SEARCH_SIZE; + + // build a vector search query: + const vectorSearchQuery = getVectorSearchQuery({ + filter, + modelId: this.model, + mustNotTerms: requiredDocs, + query, + }); + + // build a (separate) terms search query: + const termsSearchQuery = getTermsSearchQuery(requiredDocs); + + // combine the vector search query and the terms search queries into a single multi-search query: + const mSearchQueryBody = getMsearchQueryBody({ + index: this.index, + termsSearchQuery, + termsSearchQuerySize: TERMS_QUERY_SIZE, + vectorSearchQuery, + vectorSearchQuerySize, + }); try { - const result = await this.esClient.search<{ - text: string; - metadata: Record; - }>({ - index: this.index, - size: k, - query: queryBody, - }); + // execute both queries via a single multi-search request: + const result = await this.esClient.msearch(mSearchQueryBody); - const results = result.hits.hits.map( - (hit) => - new Document({ - pageContent: hit?._source?.text ?? '', - metadata: hit?._source?.metadata, - }) - ); + // flatten the results of the combined queries into a single array of hits: + const results: FlattenedHit[] = result.responses.flatMap((response) => { + const maybeEsqlMsearchResponse: MsearchResponse = response as MsearchResponse; - this.logger.debug(`Similarity Search Query:\n ${JSON.stringify(queryBody)}`); - this.logger.debug(`Similarity Search Results:\n ${JSON.stringify(results)}`); + return getFlattenedHits(maybeEsqlMsearchResponse); + }); return results; } catch (e) { @@ -223,6 +250,16 @@ export class ElasticsearchStore extends VectorStore { createIndex = async ({ index, pipeline }: CreateIndexParams = {}): Promise => { const mappings: MappingTypeMapping = { properties: { + metadata: { + properties: { + /** the category of knowledge, e.g. `esql` */ + kbResource: { type: 'keyword' }, + /** when `true`, return this document in all searches for the `kbResource` */ + required: { type: 'boolean' }, + /** often a file path when the document was created via a LangChain `DirectoryLoader`, this metadata describes the origin of the document */ + source: { type: 'keyword' }, + }, + }, vector: { properties: { tokens: { type: 'rank_features' } }, }, diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_flattened_hits.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_flattened_hits.test.ts new file mode 100644 index 00000000000000..4ceda3904d4206 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_flattened_hits.test.ts @@ -0,0 +1,81 @@ +/* + * 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 { getFlattenedHits } from './get_flattened_hits'; +import { mockMsearchResponse } from '../../../../__mocks__/msearch_response'; +import type { MsearchResponse } from './types'; + +describe('getFlattenedHits', () => { + it('returns an empty array when the response is undefined', () => { + const result = getFlattenedHits(undefined); + + expect(result).toEqual([]); + }); + + it('returns an empty array when hits > hits is empty', () => { + const result = getFlattenedHits({ hits: { hits: [] } }); + + expect(result).toEqual([]); + }); + + it('returns the expected flattened hits given a non-empty `MsearchResponse`', () => { + const expected = [ + { + pageContent: + "[[esql-from]]\n=== `FROM`\n\nThe `FROM` source command returns a table with up to 10,000 documents from a\ndata stream, index, or alias. Each row in the resulting table represents a\ndocument. Each column corresponds to a field, and can be accessed by the name\nof that field.\n\n[source,esql]\n----\nFROM employees\n----\n\nYou can use <> to refer to indices, aliases\nand data streams. This can be useful for time series data, for example to access\ntoday's index:\n\n[source,esql]\n----\nFROM \n----\n\nUse comma-separated lists or wildcards to query multiple data streams, indices,\nor aliases:\n\n[source,esql]\n----\nFROM employees-00001,employees-*\n----\n", + metadata: { + source: + '/Users/andrew.goldstein/Projects/forks/andrew-goldstein/kibana/x-pack/plugins/elastic_assistant/server/knowledge_base/esql/docs/source_commands/from.asciidoc', + }, + }, + ]; + + const result = getFlattenedHits(mockMsearchResponse.responses[0] as MsearchResponse); + + expect(result).toEqual(expected); + }); + + it('returns an array of FlattenedHits with empty strings when given an MsearchResponse with missing fields', () => { + const msearchResponse = { + hits: { + hits: [ + { + _source: { + metadata: { + source: '/source/1', + }, + }, + }, + { + _source: { + text: 'Source 2 text', + }, + }, + ], + }, + }; + + const expected = [ + { + pageContent: '', // <-- missing text field + metadata: { + source: '/source/1', + }, + }, + { + pageContent: 'Source 2 text', + metadata: { + source: '', // <-- missing source field + }, + }, + ]; + + const result = getFlattenedHits(msearchResponse); + + expect(result).toEqual(expected); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_flattened_hits.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_flattened_hits.ts new file mode 100644 index 00000000000000..f6c3a3ef0e9fab --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_flattened_hits.ts @@ -0,0 +1,37 @@ +/* + * 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 { MsearchKbHit, MsearchResponse } from './types'; + +/** + * Represents a flattened hit from an Elasticsearch Msearch response + * + * It contains the page content and metadata source of a KB document + */ +export interface FlattenedHit { + pageContent: string; + metadata: { + source: string; + }; +} + +/** + * Returns an array of flattened hits from the specified Msearch response + * that contain the page content and metadata source of KB documents + * + * @param maybeMsearchResponse An Elasticsearch Msearch response, which returns the results of multiple searches in a single request + * @returns Returns an array of flattened hits from the specified Msearch response that contain the page content and metadata source of KB documents + */ +export const getFlattenedHits = ( + maybeMsearchResponse: MsearchResponse | undefined +): FlattenedHit[] => + maybeMsearchResponse?.hits?.hits?.flatMap((hit: MsearchKbHit) => ({ + pageContent: hit?._source?.text ?? '', + metadata: { + source: hit?._source?.metadata?.source ?? '', + }, + })) ?? []; diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_msearch_query_body.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_msearch_query_body.test.ts new file mode 100644 index 00000000000000..2697aaf76a0859 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_msearch_query_body.test.ts @@ -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 { TERMS_QUERY_SIZE } from '../elasticsearch_store'; +import { getMsearchQueryBody } from './get_msearch_query_body'; +import { mockTermsSearchQuery } from '../../../../__mocks__/terms_search_query'; +import { mockVectorSearchQuery } from '../../../../__mocks__/vector_search_query'; + +describe('getMsearchQueryBody', () => { + it('returns the expected multi-search request body', () => { + const index = '.kibana-elastic-ai-assistant-kb'; + + const vectorSearchQuery = mockVectorSearchQuery; + const vectorSearchQuerySize = 4; + + const termsSearchQuery = mockTermsSearchQuery; + const termsSearchQuerySize = TERMS_QUERY_SIZE; + + const result = getMsearchQueryBody({ + index, + termsSearchQuery, + termsSearchQuerySize, + vectorSearchQuery, + vectorSearchQuerySize, + }); + + expect(result).toEqual({ + body: [ + { index }, + { + query: mockVectorSearchQuery, + size: vectorSearchQuerySize, + }, + { index }, + { + query: mockTermsSearchQuery, + size: TERMS_QUERY_SIZE, + }, + ], + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_msearch_query_body.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_msearch_query_body.ts new file mode 100644 index 00000000000000..c93c3f2e309543 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_msearch_query_body.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 type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; + +/** + * Represents an entry in a multi-search request body that specifies the name of an index to search + */ +export interface MsearchQueryBodyIndexEntry { + index: string; +} + +/** + * Represents an entry in a multi-search request body that specifies a query to execute + */ +export interface MsearchQueryBodyQueryEntry { + query: QueryDslQueryContainer; + size: number; +} + +/** + * Represents a multi-search request body, which returns the results of multiple searches in a single request + */ +export interface MsearchQueryBody { + body: Array; +} + +/** + * Returns a multi-search request body, which returns the results of multiple searches in a single request + * + * @param index The KB index to search, e.g. `.kibana-elastic-ai-assistant-kb` + * @param termsSearchQuery An Elasticsearch DSL query that performs a terms search, typically used to search for required KB documents + * @param termsSearchQuerySize The maximum number of required KB documents to return + * @param vectorSearchQuery An Elasticsearch DSL query that performs a vector search, typically used to search for similar KB documents + * @param vectorSearchQuerySize The maximum number of similar KB documents to return + * @returns A multi-search request body, which returns the results of multiple searches in a single request + */ +export const getMsearchQueryBody = ({ + index, + termsSearchQuery, + termsSearchQuerySize, + vectorSearchQuery, + vectorSearchQuerySize, +}: { + index: string; + termsSearchQuery: QueryDslQueryContainer; + termsSearchQuerySize: number; + vectorSearchQuery: QueryDslQueryContainer; + vectorSearchQuerySize: number; +}): MsearchQueryBody => ({ + body: [ + { index }, + { + query: vectorSearchQuery, + size: vectorSearchQuerySize, + }, + { index }, + { + query: termsSearchQuery, + size: termsSearchQuerySize, + }, + ], +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_required_kb_docs_terms_query_dsl.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_required_kb_docs_terms_query_dsl.test.ts new file mode 100644 index 00000000000000..5c4f944e83178e --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_required_kb_docs_terms_query_dsl.test.ts @@ -0,0 +1,21 @@ +/* + * 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 { getRequiredKbDocsTermsQueryDsl } from './get_required_kb_docs_terms_query_dsl'; + +const kbResource = 'esql'; + +describe('getRequiredKbDocsTermsQueryDsl', () => { + it('returns the expected terms query DSL', () => { + const result = getRequiredKbDocsTermsQueryDsl(kbResource); + + expect(result).toEqual([ + { term: { 'metadata.kbResource': 'esql' } }, + { term: { 'metadata.required': true } }, + ]); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_required_kb_docs_terms_query_dsl.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_required_kb_docs_terms_query_dsl.ts new file mode 100644 index 00000000000000..ba5af8c3bfef77 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_required_kb_docs_terms_query_dsl.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 type { Field, FieldValue, QueryDslTermQuery } from '@elastic/elasticsearch/lib/api/types'; + +/** + * For the specified topic, returns an array of filters that can be used in a + * `bool` Elasticsearch DSL query to filter in/out required KB documents. + * + * The returned filters can be used in different types of queries to, for example: + * - To filter out required KB documents from a vector search + * - To filter in required KB documents in a terms query + * + * @param kbResource Search for required KB documents for this topic + * + * @returns An array of `term`s that may be used in a `bool` Elasticsearch DSL query to filter in/out required KB documents + */ +export const getRequiredKbDocsTermsQueryDsl = ( + kbResource: string +): Array>> => [ + { + term: { + 'metadata.kbResource': kbResource, + }, + }, + { + term: { + 'metadata.required': true, + }, + }, +]; diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_terms_search_query.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_terms_search_query.test.ts new file mode 100644 index 00000000000000..98d3b2c5d36c2d --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_terms_search_query.test.ts @@ -0,0 +1,21 @@ +/* + * 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 { getTermsSearchQuery } from './get_terms_search_query'; +import { mockTerms } from '../../../../__mocks__/terms'; + +describe('getTermsSearchQuery', () => { + it('returns the expected Elasticsearch query DSL', () => { + const query = getTermsSearchQuery(mockTerms); + + expect(query).toEqual({ + bool: { + must: mockTerms, + }, + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_terms_search_query.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_terms_search_query.ts new file mode 100644 index 00000000000000..8fcc7b3b208513 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_terms_search_query.ts @@ -0,0 +1,29 @@ +/* + * 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 { + Field, + FieldValue, + QueryDslTermQuery, + QueryDslQueryContainer, +} from '@elastic/elasticsearch/lib/api/types'; + +/** + * Returns an Elasticsearch DSL query that performs a terms search, + * such that all of the specified terms must be present in the search results. + * + * @param mustTerms All of the specified terms must be present in the search results + * + * @returns An Elasticsearch DSL query that performs a terms search, such that all of the specified terms must be present in the search results + */ +export const getTermsSearchQuery = ( + mustTerms: Array>> +): QueryDslQueryContainer => ({ + bool: { + must: [...mustTerms], // all of the specified terms must be present in the search results + }, +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_vector_search_query.test.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_vector_search_query.test.ts new file mode 100644 index 00000000000000..da6a7227953f28 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_vector_search_query.test.ts @@ -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 type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; + +import { getVectorSearchQuery } from './get_vector_search_query'; +import { mockTerms } from '../../../../__mocks__/terms'; +import { mockQueryText } from '../../../../__mocks__/query_text'; + +describe('getVectorSearchQuery', () => { + it('returns the expected query when mustNotTerms is empty', () => { + const result = getVectorSearchQuery({ + filter: undefined, + modelId: '.elser_model_2', + mustNotTerms: [], // <--- empty + query: mockQueryText, + }); + + expect(result).toEqual({ + bool: { + filter: undefined, + must: [ + { + text_expansion: { + 'vector.tokens': { + model_id: '.elser_model_2', + model_text: + 'Generate an ES|QL query that will count the number of connections made to external IP addresses, broken down by user. If the count is greater than 100 for a specific user, add a new field called follow_up that contains a value of true, otherwise, it should contain false. The user names should also be enriched with their respective group names.', + }, + }, + }, + ], + must_not: [], + }, + }); + }); + + it('returns the expected query when mustNotTerms are provided', () => { + const result = getVectorSearchQuery({ + filter: undefined, + modelId: '.elser_model_2', + mustNotTerms: mockTerms, // <--- mock terms + query: mockQueryText, + }); + + expect(result).toEqual({ + bool: { + filter: undefined, + must: [ + { + text_expansion: { + 'vector.tokens': { + model_id: '.elser_model_2', + model_text: + 'Generate an ES|QL query that will count the number of connections made to external IP addresses, broken down by user. If the count is greater than 100 for a specific user, add a new field called follow_up that contains a value of true, otherwise, it should contain false. The user names should also be enriched with their respective group names.', + }, + }, + }, + ], + must_not: [ + { + term: { + 'metadata.kbResource': 'esql', + }, + }, + { + term: { + 'metadata.required': true, + }, + }, + ], + }, + }); + }); + + it('returns the expected results when a filter is provided', () => { + const filter: QueryDslQueryContainer = { + bool: { + must: [ + { + term: { + 'some.field': 'value', + }, + }, + ], + }, + }; + + const result = getVectorSearchQuery({ + filter, + modelId: '.elser_model_2', + mustNotTerms: mockTerms, // <--- mock terms + query: mockQueryText, + }); + + expect(result).toEqual({ + bool: { + filter, + must: [ + { + text_expansion: { + 'vector.tokens': { + model_id: '.elser_model_2', + model_text: + 'Generate an ES|QL query that will count the number of connections made to external IP addresses, broken down by user. If the count is greater than 100 for a specific user, add a new field called follow_up that contains a value of true, otherwise, it should contain false. The user names should also be enriched with their respective group names.', + }, + }, + }, + ], + must_not: [ + { + term: { + 'metadata.kbResource': 'esql', + }, + }, + { + term: { + 'metadata.required': true, + }, + }, + ], + }, + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_vector_search_query.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_vector_search_query.ts new file mode 100644 index 00000000000000..b80038cea2a92a --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/get_vector_search_query.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 type { + Field, + FieldValue, + QueryDslQueryContainer, + QueryDslTermQuery, + QueryDslTextExpansionQuery, +} from '@elastic/elasticsearch/lib/api/types'; + +/** + * Returns an Elasticsearch query DSL that performs a vector search + * that excludes a set of documents from the search results. + * + * @param filter Optional filter to apply to the search + * @param modelId ID of the model to search with, e.g. `.elser_model_2` + * @param mustNotTerms Array of objects that may be used in a `bool` Elasticsearch DSL query to, for example, exclude the required KB docs from the vector search, so there's no overlap + * @param query The search query provided by the user + * @returns + */ +export const getVectorSearchQuery = ({ + filter, + modelId, + mustNotTerms, + query, +}: { + filter: QueryDslQueryContainer | undefined; + modelId: string; + mustNotTerms: Array>>; + query: string; +}): QueryDslQueryContainer => ({ + bool: { + must_not: [...mustNotTerms], + must: [ + { + text_expansion: { + 'vector.tokens': { + model_id: modelId, + model_text: query, + }, + } as unknown as QueryDslTextExpansionQuery, + }, + ], + filter, + }, +}); diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/types.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/types.ts new file mode 100644 index 00000000000000..a0f549a00ab263 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/helpers/types.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/** + * A hit from the response to an Elasticsearch multi-search request, + * which returns the results of multiple searches in a single request. + * + * Search hits may contain the following properties that may be present in + * knowledge base documents: + * + * 1) the `metadata` property, an object that may have the following properties: + * - `kbResource`: The name of the Knowledge Base resource that the document belongs to, e.g. `esql` + * - `required`: A boolean indicating whether the document is required for searches on the `kbResource` topic + * - `source`: Describes the origin of the document, sometimes a file path via a LangChain DirectoryLoader + * 2) the `text` property, a string containing the text of the document + * 3) the `vector` property, containing the document's embeddings + */ +export interface MsearchKbHit { + _id?: string; + _ignored?: string[]; + _index?: string; + _score?: number; + _source?: { + metadata?: { + kbResource?: string; + required?: boolean; + source?: string; + }; + text?: string; + vector?: { + tokens?: Record; + }; + }; +} + +/** + * A Response from an Elasticsearch multi-search request, which returns the + * results of multiple searches in a single request. + */ +export interface MsearchResponse { + hits?: { + hits?: MsearchKbHit[]; + }; +} 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 index d9e301d5571901..e63da9257aa367 100644 --- 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 @@ -5,16 +5,17 @@ * 2.0. */ -import { KibanaRequest } from '@kbn/core/server'; import { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { KibanaRequest } from '@kbn/core/server'; +import { loggerMock } from '@kbn/logging-mocks'; -import { ResponseBody } from '../types'; import { ActionsClientLlm } from '../llm/actions_client_llm'; import { mockActionResponse } from '../../../__mocks__/action_result_data'; import { langChainMessages } from '../../../__mocks__/lang_chain_messages'; +import { ESQL_RESOURCE } from '../../../routes/knowledge_base/constants'; +import { ResponseBody } from '../types'; import { callAgentExecutor } from '.'; -import { loggerMock } from '@kbn/logging-mocks'; -import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; jest.mock('../llm/actions_client_llm'); @@ -66,6 +67,7 @@ describe('callAgentExecutor', () => { langChainMessages, logger: mockLogger, request: mockRequest, + kbResource: ESQL_RESOURCE, }); expect(ActionsClientLlm).toHaveBeenCalledWith({ @@ -84,6 +86,7 @@ describe('callAgentExecutor', () => { langChainMessages, logger: mockLogger, request: mockRequest, + kbResource: ESQL_RESOURCE, }); expect(mockCall).toHaveBeenCalledWith({ @@ -101,6 +104,7 @@ describe('callAgentExecutor', () => { langChainMessages: onlyOneMessage, logger: mockLogger, request: mockRequest, + kbResource: ESQL_RESOURCE, }); expect(mockCall).toHaveBeenCalledWith({ @@ -116,6 +120,7 @@ describe('callAgentExecutor', () => { langChainMessages, logger: mockLogger, request: mockRequest, + kbResource: ESQL_RESOURCE, }); expect(result).toEqual({ 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 index e1f0ed100e5acf..694bd44bfd471f 100644 --- 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 @@ -24,6 +24,7 @@ export const callAgentExecutor = async ({ logger, request, elserId, + kbResource, }: AgentExecutorParams): AgentExecutorResponse => { const llm = new ActionsClientLlm({ actions, connectorId, request, llmType, logger }); @@ -39,7 +40,13 @@ export const callAgentExecutor = async ({ }); // ELSER backed ElasticsearchStore for Knowledge Base - const esStore = new ElasticsearchStore(esClient, KNOWLEDGE_BASE_INDEX_PATTERN, logger, elserId); + const esStore = new ElasticsearchStore( + esClient, + KNOWLEDGE_BASE_INDEX_PATTERN, + logger, + elserId, + kbResource + ); const chain = RetrievalQAChain.fromLLM(llm, esStore.asRetriever()); const tools: Tool[] = [ diff --git a/x-pack/plugins/elastic_assistant/server/lib/langchain/executors/types.ts b/x-pack/plugins/elastic_assistant/server/lib/langchain/executors/types.ts index e1e2817ee17a19..1c15ff8c97da49 100644 --- a/x-pack/plugins/elastic_assistant/server/lib/langchain/executors/types.ts +++ b/x-pack/plugins/elastic_assistant/server/lib/langchain/executors/types.ts @@ -16,6 +16,7 @@ export interface AgentExecutorParams { actions: ActionsPluginStart; connectorId: string; esClient: ElasticsearchClient; + kbResource: string | undefined; langChainMessages: BaseMessage[]; llmType?: string; logger: Logger; diff --git a/x-pack/plugins/elastic_assistant/server/routes/evaluate/post_evaluate.ts b/x-pack/plugins/elastic_assistant/server/routes/evaluate/post_evaluate.ts index ed3ff729b623e5..b65822524f1cd9 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/evaluate/post_evaluate.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/evaluate/post_evaluate.ts @@ -7,11 +7,11 @@ import { IRouter, KibanaRequest, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; - import { v4 as uuidv4 } from 'uuid'; + +import { ESQL_RESOURCE } from '../knowledge_base/constants'; import { buildResponse } from '../../lib/build_response'; import { buildRouteValidation } from '../../schemas/common'; - import { ElasticAssistantRequestHandlerContext, GetElser } from '../../types'; import { EVALUATE } from '../../../common/constants'; import { PostEvaluateBody, PostEvaluatePathQuery } from '../../schemas/evaluate/post_evaluate'; @@ -126,6 +126,7 @@ export const postEvaluateRoute = ( llmType, logger, request: skeletonRequest, + kbResource: ESQL_RESOURCE, }) ); }); diff --git a/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/get_kb_resource.test.ts b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/get_kb_resource.test.ts new file mode 100644 index 00000000000000..7c4a9058e7df72 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/get_kb_resource.test.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 { getKbResource } from './get_kb_resource'; + +describe('getKbResource', () => { + it('returns undefined when the request is undefined', () => { + const result = getKbResource(undefined); + + expect(result).toBeUndefined(); + }); + + it('returns undefined when params is undefined', () => { + const request = { params: undefined }; + + const result = getKbResource(request); + + expect(result).toBeUndefined(); + }); + + it('returns undefined when resource is undefined', () => { + const request = { params: { resource: undefined } }; + + const result = getKbResource(request); + + expect(result).toBeUndefined(); + }); + + it('returns the decoded resource', () => { + const request = { params: { resource: 'esql%20query' } }; + + const result = getKbResource(request); + + expect(result).toEqual('esql query'); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/get_kb_resource.ts b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/get_kb_resource.ts new file mode 100644 index 00000000000000..a238a8f55d6158 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/get_kb_resource.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/** + * A knowledge base REST request + */ +interface KbRequest { + params?: { + resource?: string; + }; +} + +/** + * Returns the optional resource, e.g. `esql` from the request params, or undefined if it doesn't exist + * + * @param request A REST request + * + * @returns Returns the optional resource, e.g. `esql` from the request params, or undefined if it doesn't exist + */ +export const getKbResource = (request: KbRequest | undefined): string | undefined => { + if (request?.params?.resource != null) { + return decodeURIComponent(request.params.resource); + } else { + return undefined; + } +}; diff --git a/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/get_knowledge_base_status.ts b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/get_knowledge_base_status.ts index 3bb1961bd0956a..c2c616939677d5 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/get_knowledge_base_status.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/get_knowledge_base_status.ts @@ -8,6 +8,8 @@ import { IRouter } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import type { GetKnowledgeBaseStatusResponse } from '@kbn/elastic-assistant'; + +import { getKbResource } from './get_kb_resource'; import { buildResponse } from '../../lib/build_response'; import { buildRouteValidation } from '../../schemas/common'; import { ElasticAssistantRequestHandlerContext, GetElser } from '../../types'; @@ -42,17 +44,16 @@ export const getKnowledgeBaseStatusRoute = ( const logger = (await context.elasticAssistant).logger; try { - const kbResource = - request.params.resource != null ? decodeURIComponent(request.params.resource) : undefined; - // Get a scoped esClient for finding the status of the Knowledge Base index, pipeline, and documents const esClient = (await context.core).elasticsearch.client.asCurrentUser; const elserId = await getElser(request, (await context.core).savedObjects.getClient()); + const kbResource = getKbResource(request); const esStore = new ElasticsearchStore( esClient, KNOWLEDGE_BASE_INDEX_PATTERN, logger, - elserId + elserId, + kbResource ); const indexExists = await esStore.indexExists(); diff --git a/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/post_knowledge_base.ts b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/post_knowledge_base.ts index 580c03e23a0cc3..2ac938d3db45aa 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/post_knowledge_base.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/knowledge_base/post_knowledge_base.ts @@ -7,12 +7,14 @@ import { IRouter } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; + import { buildResponse } from '../../lib/build_response'; import { buildRouteValidation } from '../../schemas/common'; import { ElasticAssistantRequestHandlerContext, GetElser } from '../../types'; import { KNOWLEDGE_BASE } from '../../../common/constants'; import { ElasticsearchStore } from '../../lib/langchain/elasticsearch_store/elasticsearch_store'; import { ESQL_DOCS_LOADED_QUERY, ESQL_RESOURCE, KNOWLEDGE_BASE_INDEX_PATTERN } from './constants'; +import { getKbResource } from './get_kb_resource'; import { PostKnowledgeBasePathParams } from '../../schemas/knowledge_base/post_knowledge_base'; import { loadESQL } from '../../lib/langchain/content_loaders/esql_loader'; @@ -41,17 +43,16 @@ export const postKnowledgeBaseRoute = ( const logger = (await context.elasticAssistant).logger; try { - const kbResource = - request.params.resource != null ? decodeURIComponent(request.params.resource) : undefined; - // Get a scoped esClient for creating the Knowledge Base index, pipeline, and documents const esClient = (await context.core).elasticsearch.client.asCurrentUser; const elserId = await getElser(request, (await context.core).savedObjects.getClient()); + const kbResource = getKbResource(request); const esStore = new ElasticsearchStore( esClient, KNOWLEDGE_BASE_INDEX_PATTERN, logger, - elserId + elserId, + kbResource ); // Pre-check on index/pipeline 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 index 8f620dac06faa9..5303796d1c983c 100644 --- 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 @@ -16,6 +16,7 @@ import { PostActionsConnectorExecutePathParams, } from '../schemas/post_actions_connector_execute'; import { ElasticAssistantRequestHandlerContext, GetElser } from '../types'; +import { ESQL_RESOURCE } from './knowledge_base/constants'; import { callAgentExecutor } from '../lib/langchain/execute_custom_llm_chain'; export const postActionsConnectorExecuteRoute = ( @@ -58,6 +59,7 @@ export const postActionsConnectorExecuteRoute = ( logger, request, elserId, + kbResource: ESQL_RESOURCE, }); return response.ok({ diff --git a/x-pack/plugins/security_solution/public/assistant/content/prompts/system/translations.ts b/x-pack/plugins/security_solution/public/assistant/content/prompts/system/translations.ts index 90c75a74055265..63fcd9c9995a9f 100644 --- a/x-pack/plugins/security_solution/public/assistant/content/prompts/system/translations.ts +++ b/x-pack/plugins/security_solution/public/assistant/content/prompts/system/translations.ts @@ -41,7 +41,7 @@ export const FORMAT_OUTPUT_CORRECTLY = i18n.translate( 'xpack.securitySolution.assistant.content.prompts.system.outputFormatting', { defaultMessage: - 'If you answer a question related to KQL or EQL, it should be immediately usable within an Elastic Security timeline; please always format the output correctly with back ticks. Any answer provided for Query DSL should also be usable in a security timeline. This means you should only ever include the "filter" portion of the query.', + 'If you answer a question related to KQL, EQL, or ES|QL, it should be immediately usable within an Elastic Security timeline; please always format the output correctly with back ticks. Any answer provided for Query DSL should also be usable in a security timeline. This means you should only ever include the "filter" portion of the query.', } ); From 6fdd1f177ab461606368ca3042c3b27919eb931e Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 17 Oct 2023 05:42:28 +0200 Subject: [PATCH 32/87] [Ops] create-deploy-tag workflow: Improve speed (#168907) --- .github/workflows/create-deploy-tag.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/create-deploy-tag.yml b/.github/workflows/create-deploy-tag.yml index 028eb9e5cc33c4..6488aa0dc64175 100644 --- a/.github/workflows/create-deploy-tag.yml +++ b/.github/workflows/create-deploy-tag.yml @@ -12,6 +12,9 @@ on: inputs: commit: description: "Commit to promote (default: latest commit on main)" + depth: + description: "Fetch depth (0 = everything)" + default: "500" concurrency: group: ${{ github.workflow }} @@ -25,9 +28,10 @@ jobs: contents: write steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: - fetch-depth: 0 + fetch-depth: ${{ github.event.inputs.depth }} + fetch-tags: true - name: Select commit to be tagged run: | commit="${{ github.event.inputs.commit || github.sha }}" @@ -100,10 +104,9 @@ jobs: [ "*Useful links:*\\n", "", - "", "", " (use Elastic Cloud Staging VPN)", - "", + "", "", "" ] From 4d4ff51e96d3b7f2d1461faecf0a74be0ed82f3a Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:07:46 -0400 Subject: [PATCH 33/87] [api-docs] 2023-10-17 Daily api_docs build (#169059) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/493 --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.devdocs.json | 2 +- api_docs/alerting.mdx | 2 +- api_docs/apm.mdx | 2 +- 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_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 | 212 ++----- api_docs/data.mdx | 4 +- api_docs/data_query.mdx | 4 +- api_docs/data_search.mdx | 4 +- 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 | 368 +++-------- api_docs/data_views.mdx | 4 +- 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.mdx | 2 +- 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_annotation_listing.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.devdocs.json | 111 +++- api_docs/fleet.mdx | 4 +- 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 | 5 +- api_docs/index_management.mdx | 2 +- 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 +- api_docs/kbn_core_elasticsearch_server.mdx | 2 +- ...kbn_core_elasticsearch_server_internal.mdx | 2 +- .../kbn_core_elasticsearch_server_mocks.mdx | 2 +- .../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 | 4 + 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 | 3 +- .../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 +- ...aved_objects_migration_server_internal.mdx | 2 +- ...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 +- api_docs/kbn_core_test_helpers_kbn_server.mdx | 2 +- .../kbn_core_test_helpers_model_versions.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_custom_integrations.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.devdocs.json | 4 +- 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.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_field_utils.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 +- .../kbn_management_settings_application.mdx | 2 +- ...ent_settings_components_field_category.mdx | 2 +- ...gement_settings_components_field_input.mdx | 2 +- ...nagement_settings_components_field_row.mdx | 2 +- ...bn_management_settings_components_form.mdx | 2 +- ...n_management_settings_field_definition.mdx | 2 +- api_docs/kbn_management_settings_ids.mdx | 2 +- ...n_management_settings_section_registry.mdx | 2 +- api_docs/kbn_management_settings_types.mdx | 2 +- .../kbn_management_settings_utilities.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 +- api_docs/kbn_ml_chi2test.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_openapi_generator.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_profiling_utils.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_resizable_layout.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.mdx | 2 +- api_docs/kbn_search_connectors.devdocs.json | 596 +++++++++++++++++- api_docs/kbn_search_connectors.mdx | 4 +- api_docs/kbn_search_response_warnings.mdx | 2 +- api_docs/kbn_security_solution_features.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_common_settings.mdx | 2 +- .../kbn_serverless_observability_settings.mdx | 2 +- api_docs/kbn_serverless_project_switcher.mdx | 2 +- api_docs/kbn_serverless_search_settings.mdx | 2 +- api_docs/kbn_serverless_security_settings.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 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- 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 +- .../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 +- 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.mdx | 2 +- 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_subscription_tracking.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_data_table.mdx | 2 +- api_docs/kbn_unified_doc_viewer.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_xstate_utils.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/links.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/log_explorer.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/metrics_data_access.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.mdx | 2 +- api_docs/notifications.mdx | 2 +- api_docs/observability.mdx | 2 +- api_docs/observability_a_i_assistant.mdx | 2 +- api_docs/observability_log_explorer.mdx | 2 +- api_docs/observability_onboarding.mdx | 2 +- api_docs/observability_shared.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/painless_lab.mdx | 2 +- api_docs/plugin_directory.mdx | 16 +- api_docs/presentation_util.mdx | 2 +- api_docs/profiling.mdx | 2 +- api_docs/profiling_data_access.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.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.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.devdocs.json | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_doc_viewer.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 +- 607 files changed, 1474 insertions(+), 1055 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 02a173fc12ed96..e8d53a7a433ed6 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-10-16 +date: 2023-10-17 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 120774eb8af0ef..e8641d2346733e 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-10-16 +date: 2023-10-17 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 0dc4119e369025..4fc83fdc3737d7 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.devdocs.json b/api_docs/alerting.devdocs.json index d92d8b3859a2b6..60198b50b16623 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -3645,7 +3645,7 @@ "section": "def-common.FieldSpec", "text": "FieldSpec" }, - "[]>; getExistingIndices: (indices: string[]) => Promise; getFieldsForIndexPattern: (indexPattern: ", + "[]>; getFieldsForIndexPattern: (indexPattern: ", { "pluginId": "dataViews", "scope": "common", diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index d0b7f097d8490a..c1c6ba03ac3637 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index a4162a8b9474cf..07798b2d7d44c9 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx index ea1c59df4e5cdd..8e21775b0d20bb 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-10-16 +date: 2023-10-17 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 08106abfb2a0bd..a79aa72f869d76 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-10-16 +date: 2023-10-17 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 0771bd378592ed..4033d8c8c47605 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-10-16 +date: 2023-10-17 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 3255c0f66ae684..f323de530edf31 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-10-16 +date: 2023-10-17 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 460f5fe5908322..085a8951878644 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-10-16 +date: 2023-10-17 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 3cd9a27751c4b3..28259ee380be98 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-10-16 +date: 2023-10-17 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 fafbfa25cef9ee..d4bf1e7a9e3704 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-10-16 +date: 2023-10-17 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 cc3d2d8103019c..a9a30caf1a4478 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index b21f4f6b3e761f..87b7551a39131f 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-10-16 +date: 2023-10-17 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 3d8628300a4605..bd261cb318035a 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-10-16 +date: 2023-10-17 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 5ba408c46f2605..ca9b201336552a 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-10-16 +date: 2023-10-17 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 a2e8dbf2307422..a94173f5e5c007 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-10-16 +date: 2023-10-17 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 cc00d1a3822d1e..a1129f4e782453 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-10-16 +date: 2023-10-17 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 dafd936416ad2f..df4af236d41677 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-10-16 +date: 2023-10-17 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 601040eeba4574..c10fcafd5449d3 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-10-16 +date: 2023-10-17 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 a742cf4a9b9e0a..7cceeeae873380 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-10-16 +date: 2023-10-17 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 b466360ca1ab9b..e1e2e6f161749e 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-10-16 +date: 2023-10-17 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 976dc794e74b0d..6dae7ddb65e9d2 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-10-16 +date: 2023-10-17 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 3bfacc60372646..1438cc10b17eb3 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -7805,20 +7805,6 @@ "path": "src/plugins/data_views/common/types.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-public.GetFieldsOptions.allowHidden", - "type": "CompoundType", - "tags": [], - "label": "allowHidden", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data_views/common/types.ts", - "deprecated": false, - "trackAdoption": false } ], "initialIsOpen": false @@ -14258,22 +14244,6 @@ "index pattern string" ] }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getAllowHidden", - "type": "Function", - "tags": [], - "label": "getAllowHidden", - "description": [], - "signature": [ - "() => boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, { "parentPluginId": "data", "id": "def-server.DataView.setIndexPattern", @@ -16197,44 +16167,6 @@ "FieldSpec[]" ] }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getExistingIndices", - "type": "Function", - "tags": [], - "label": "getExistingIndices", - "description": [ - "\nGet existing index pattern list by providing string array index pattern list." - ], - "signature": [ - "(indices: string[]) => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getExistingIndices.$1", - "type": "Array", - "tags": [], - "label": "indices", - "description": [ - "index pattern list" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [ - "index pattern list" - ] - }, { "parentPluginId": "data", "id": "def-server.DataViewsService.getFieldsForIndexPattern", @@ -17265,7 +17197,7 @@ "signature": [ "(options: { pattern: string | string[]; metaFields?: string[] | undefined; fieldCapsOptions?: { allow_no_indices: boolean; includeUnmapped?: boolean | undefined; } | undefined; type?: string | undefined; rollupIndex?: string | undefined; indexFilter?: ", "QueryDslQueryContainer", - " | undefined; fields?: string[] | undefined; allowHidden?: boolean | undefined; }) => Promise<{ fields: ", + " | undefined; fields?: string[] | undefined; }) => Promise<{ fields: ", { "pluginId": "dataViews", "scope": "server", @@ -17388,25 +17320,49 @@ "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.allowHidden", - "type": "CompoundType", - "tags": [], - "label": "allowHidden", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false } ] } ], "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.getExistingIndices", + "type": "Function", + "tags": [], + "label": "getExistingIndices", + "description": [ + "\nGet existing index pattern list by providing string array index pattern list." + ], + "signature": [ + "(indices: string[]) => Promise" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.getExistingIndices.$1", + "type": "Array", + "tags": [], + "label": "indices", + "description": [ + "- index pattern list" + ], + "signature": [ + "string[]" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [ + "index pattern list of index patterns that match indices" + ] } ], "initialIsOpen": false @@ -22047,22 +22003,6 @@ "index pattern string" ] }, - { - "parentPluginId": "data", - "id": "def-common.DataView.getAllowHidden", - "type": "Function", - "tags": [], - "label": "getAllowHidden", - "description": [], - "signature": [ - "() => boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, { "parentPluginId": "data", "id": "def-common.DataView.setIndexPattern", @@ -24857,44 +24797,6 @@ "FieldSpec[]" ] }, - { - "parentPluginId": "data", - "id": "def-common.DataViewsService.getExistingIndices", - "type": "Function", - "tags": [], - "label": "getExistingIndices", - "description": [ - "\nGet existing index pattern list by providing string array index pattern list." - ], - "signature": [ - "(indices: string[]) => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-common.DataViewsService.getExistingIndices.$1", - "type": "Array", - "tags": [], - "label": "indices", - "description": [ - "index pattern list" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [ - "index pattern list" - ] - }, { "parentPluginId": "data", "id": "def-common.DataViewsService.getFieldsForIndexPattern", @@ -26965,22 +26867,6 @@ "path": "src/plugins/data_views/common/types.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-common.DataViewAttributes.allowHidden", - "type": "CompoundType", - "tags": [], - "label": "allowHidden", - "description": [ - "\nAllow hidden and system indices when loading field list" - ], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data_views/common/types.ts", - "deprecated": false, - "trackAdoption": false } ], "initialIsOpen": false @@ -27230,20 +27116,6 @@ "path": "src/plugins/data_views/common/types.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-common.GetFieldsOptions.allowHidden", - "type": "CompoundType", - "tags": [], - "label": "allowHidden", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data_views/common/types.ts", - "deprecated": false, - "trackAdoption": false } ], "initialIsOpen": false @@ -27421,7 +27293,7 @@ "section": "def-common.FieldAttrs", "text": "FieldAttrs" }, - " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; allowHidden?: boolean | undefined; }" + " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; }" ], "path": "src/plugins/data_views/common/expressions/load_index_pattern.ts", "deprecated": false, @@ -28331,7 +28203,7 @@ "section": "def-common.FieldSpec", "text": "FieldSpec" }, - "[]>; getExistingIndices: (indices: string[]) => Promise; getFieldsForIndexPattern: (indexPattern: ", + "[]>; getFieldsForIndexPattern: (indexPattern: ", { "pluginId": "dataViews", "scope": "common", @@ -28548,7 +28420,7 @@ "section": "def-common.FieldAttrs", "text": "FieldAttrs" }, - " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; allowHidden?: boolean | undefined; }" + " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; }" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 36f38886235f18..a1240cf855d3c6 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3290 | 33 | 2554 | 24 | +| 3282 | 33 | 2549 | 24 | ## Client diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 8fa593404cf866..2bf79e7f68ce3f 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3290 | 33 | 2554 | 24 | +| 3282 | 33 | 2549 | 24 | ## Client diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index b3d92f1f8bdb8f..c378df00f6d587 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3290 | 33 | 2554 | 24 | +| 3282 | 33 | 2549 | 24 | ## Client diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index c61754c59a02a1..f96edd39eccef2 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-10-16 +date: 2023-10-17 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 72786354569724..f075eb62cdd6fc 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-10-16 +date: 2023-10-17 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 cd0ece04e34d97..d5bbc3317608e6 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-10-16 +date: 2023-10-17 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 872458d9a15e34..1bca8693a366ec 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -1225,22 +1225,6 @@ "index pattern string" ] }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getAllowHidden", - "type": "Function", - "tags": [], - "label": "getAllowHidden", - "description": [], - "signature": [ - "() => boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, { "parentPluginId": "dataViews", "id": "def-public.DataView.setIndexPattern", @@ -4456,44 +4440,6 @@ "FieldSpec[]" ] }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewsService.getExistingIndices", - "type": "Function", - "tags": [], - "label": "getExistingIndices", - "description": [ - "\nGet existing index pattern list by providing string array index pattern list." - ], - "signature": [ - "(indices: string[]) => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewsService.getExistingIndices.$1", - "type": "Array", - "tags": [], - "label": "indices", - "description": [ - "index pattern list" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [ - "index pattern list" - ] - }, { "parentPluginId": "dataViews", "id": "def-public.DataViewsService.getFieldsForIndexPattern", @@ -5602,6 +5548,46 @@ "trackAdoption": false, "children": [], "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewsServicePublic.getExistingIndices", + "type": "Function", + "tags": [], + "label": "getExistingIndices", + "description": [ + "\nGet existing index pattern list by providing string array index pattern list." + ], + "signature": [ + "(indices: string[]) => Promise<", + "ExistingIndicesResponse", + ">" + ], + "path": "src/plugins/data_views/public/data_views_service_public.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewsServicePublic.getExistingIndices.$1", + "type": "Array", + "tags": [], + "label": "indices", + "description": [ + "- index pattern list" + ], + "signature": [ + "string[]" + ], + "path": "src/plugins/data_views/public/data_views_service_public.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [ + "index pattern list of index patterns that match indices" + ] } ], "initialIsOpen": false @@ -6142,22 +6128,6 @@ "path": "src/plugins/data_views/common/types.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewAttributes.allowHidden", - "type": "CompoundType", - "tags": [], - "label": "allowHidden", - "description": [ - "\nAllow hidden and system indices when loading field list" - ], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data_views/common/types.ts", - "deprecated": false, - "trackAdoption": false } ], "initialIsOpen": false @@ -6618,6 +6588,26 @@ "path": "src/plugins/data_views/public/data_views_service_public.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewsServicePublicDeps.http", + "type": "Object", + "tags": [], + "label": "http", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-browser", + "scope": "common", + "docId": "kibKbnCoreHttpBrowserPluginApi", + "section": "def-common.HttpSetup", + "text": "HttpSetup" + } + ], + "path": "src/plugins/data_views/public/data_views_service_public.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -7814,7 +7804,7 @@ "section": "def-common.FieldAttrs", "text": "FieldAttrs" }, - " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; allowHidden?: boolean | undefined; }" + " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; }" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, @@ -9264,22 +9254,6 @@ "index pattern string" ] }, - { - "parentPluginId": "dataViews", - "id": "def-server.DataView.getAllowHidden", - "type": "Function", - "tags": [], - "label": "getAllowHidden", - "description": [], - "signature": [ - "() => boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, { "parentPluginId": "dataViews", "id": "def-server.DataView.setIndexPattern", @@ -11497,44 +11471,6 @@ "FieldSpec[]" ] }, - { - "parentPluginId": "dataViews", - "id": "def-server.DataViewsService.getExistingIndices", - "type": "Function", - "tags": [], - "label": "getExistingIndices", - "description": [ - "\nGet existing index pattern list by providing string array index pattern list." - ], - "signature": [ - "(indices: string[]) => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "dataViews", - "id": "def-server.DataViewsService.getExistingIndices.$1", - "type": "Array", - "tags": [], - "label": "indices", - "description": [ - "index pattern list" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [ - "index pattern list" - ] - }, { "parentPluginId": "dataViews", "id": "def-server.DataViewsService.getFieldsForIndexPattern", @@ -12565,7 +12501,7 @@ "signature": [ "(options: { pattern: string | string[]; metaFields?: string[] | undefined; fieldCapsOptions?: { allow_no_indices: boolean; includeUnmapped?: boolean | undefined; } | undefined; type?: string | undefined; rollupIndex?: string | undefined; indexFilter?: ", "QueryDslQueryContainer", - " | undefined; fields?: string[] | undefined; allowHidden?: boolean | undefined; }) => Promise<{ fields: ", + " | undefined; fields?: string[] | undefined; }) => Promise<{ fields: ", { "pluginId": "dataViews", "scope": "server", @@ -12688,25 +12624,49 @@ "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.allowHidden", - "type": "CompoundType", - "tags": [], - "label": "allowHidden", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false } ] } ], "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-server.IndexPatternsFetcher.getExistingIndices", + "type": "Function", + "tags": [], + "label": "getExistingIndices", + "description": [ + "\nGet existing index pattern list by providing string array index pattern list." + ], + "signature": [ + "(indices: string[]) => Promise" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-server.IndexPatternsFetcher.getExistingIndices.$1", + "type": "Array", + "tags": [], + "label": "indices", + "description": [ + "- index pattern list" + ], + "signature": [ + "string[]" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [ + "index pattern list of index patterns that match indices" + ] } ], "initialIsOpen": false @@ -16362,22 +16322,6 @@ "index pattern string" ] }, - { - "parentPluginId": "dataViews", - "id": "def-common.DataView.getAllowHidden", - "type": "Function", - "tags": [], - "label": "getAllowHidden", - "description": [], - "signature": [ - "() => boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, { "parentPluginId": "dataViews", "id": "def-common.DataView.setIndexPattern", @@ -19259,44 +19203,6 @@ "FieldSpec[]" ] }, - { - "parentPluginId": "dataViews", - "id": "def-common.DataViewsService.getExistingIndices", - "type": "Function", - "tags": [], - "label": "getExistingIndices", - "description": [ - "\nGet existing index pattern list by providing string array index pattern list." - ], - "signature": [ - "(indices: string[]) => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "dataViews", - "id": "def-common.DataViewsService.getExistingIndices.$1", - "type": "Array", - "tags": [], - "label": "indices", - "description": [ - "index pattern list" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [ - "index pattern list" - ] - }, { "parentPluginId": "dataViews", "id": "def-common.DataViewsService.getFieldsForIndexPattern", @@ -20801,22 +20707,6 @@ "path": "src/plugins/data_views/common/types.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-common.DataViewAttributes.allowHidden", - "type": "CompoundType", - "tags": [], - "label": "allowHidden", - "description": [ - "\nAllow hidden and system indices when loading field list" - ], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data_views/common/types.ts", - "deprecated": false, - "trackAdoption": false } ], "initialIsOpen": false @@ -22442,44 +22332,6 @@ ], "returnComment": [] }, - { - "parentPluginId": "dataViews", - "id": "def-common.DataViewsServicePublicMethods.getExistingIndices", - "type": "Function", - "tags": [], - "label": "getExistingIndices", - "description": [ - "\nGet existing index pattern list by providing string array index pattern list." - ], - "signature": [ - "(indices: string[]) => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "dataViews", - "id": "def-common.DataViewsServicePublicMethods.getExistingIndices.$1", - "type": "Array", - "tags": [], - "label": "indices", - "description": [ - "- index pattern list" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [ - "index pattern list of index patterns that match indices" - ] - }, { "parentPluginId": "dataViews", "id": "def-common.DataViewsServicePublicMethods.getIds", @@ -23149,20 +23001,6 @@ "path": "src/plugins/data_views/common/types.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-common.GetFieldsOptions.allowHidden", - "type": "CompoundType", - "tags": [], - "label": "allowHidden", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data_views/common/types.ts", - "deprecated": false, - "trackAdoption": false } ], "initialIsOpen": false @@ -23845,7 +23683,7 @@ "section": "def-common.FieldAttrs", "text": "FieldAttrs" }, - " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; allowHidden?: boolean | undefined; }" + " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; }" ], "path": "src/plugins/data_views/common/expressions/load_index_pattern.ts", "deprecated": false, @@ -25351,7 +25189,7 @@ "section": "def-common.FieldSpec", "text": "FieldSpec" }, - "[]>; getExistingIndices: (indices: string[]) => Promise; getFieldsForIndexPattern: (indexPattern: ", + "[]>; getFieldsForIndexPattern: (indexPattern: ", { "pluginId": "dataViews", "scope": "common", @@ -25568,7 +25406,7 @@ "section": "def-common.FieldAttrs", "text": "FieldAttrs" }, - " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; allowHidden?: boolean | undefined; }" + " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; }" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 60c227f73d38f2..5cbdc172a2aa09 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1048 | 0 | 262 | 2 | +| 1038 | 0 | 258 | 3 | ## Client diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 2617bfe9dcc8e8..ba391b2c566394 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-10-16 +date: 2023-10-17 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 685b039a4a7672..0d5461d79b79a9 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 76b58797359940..fbc91a3023b2b4 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 88c85793f503ba..a589030f4624ed 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 7a264a5af132e5..031af628232af4 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-10-16 +date: 2023-10-17 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 39d5d32e4e648a..80bbfd1f0fe0c5 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-10-16 +date: 2023-10-17 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 c38060e7d1d053..6350dba94d9cb5 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-10-16 +date: 2023-10-17 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 6dd92fa085843b..0f66a0e731515e 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx index 4dcf948b321830..b3f95de80246fa 100644 --- a/api_docs/elastic_assistant.mdx +++ b/api_docs/elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/elasticAssistant title: "elasticAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the elasticAssistant plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant'] --- import elasticAssistantObj from './elastic_assistant.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index cfb99c994084b0..d8bd9acd9204b4 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-10-16 +date: 2023-10-17 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 8fe3ea014673fb..b3a2c58b2c0fd9 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-10-16 +date: 2023-10-17 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 f81e66ec955adf..71bbbf05e67acd 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-10-16 +date: 2023-10-17 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 9b332c975c3631..7b62a57120c537 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-10-16 +date: 2023-10-17 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 b8ffe348d9ba68..e9b4556666441d 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-10-16 +date: 2023-10-17 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 82cb16d5842d28..5814fc1d333385 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_annotation_listing.mdx b/api_docs/event_annotation_listing.mdx index 17287d9316e8a3..17908b8f15b291 100644 --- a/api_docs/event_annotation_listing.mdx +++ b/api_docs/event_annotation_listing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotationListing title: "eventAnnotationListing" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotationListing plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotationListing'] --- import eventAnnotationListingObj from './event_annotation_listing.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index cd35f2b641e1a4..3a7324323f21c5 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-10-16 +date: 2023-10-17 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 51ee00757e282b..2a62155db9b326 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-10-16 +date: 2023-10-17 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 0a151648b62e37..ec8c08805ba558 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-10-16 +date: 2023-10-17 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 c59e2ab78ed8f6..18579b82493940 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-10-16 +date: 2023-10-17 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 3a367687943904..131b7e5bfd8518 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-10-16 +date: 2023-10-17 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 61708668f245e2..734652e90107ce 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-10-16 +date: 2023-10-17 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 3bb76659b5d28e..180dcc1332a96b 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-10-16 +date: 2023-10-17 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 75ffff92d9061b..ad9e58cea41b37 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-10-16 +date: 2023-10-17 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 776f7071f61657..38a0810324684b 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-10-16 +date: 2023-10-17 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 dd7e434ce1d1a6..56abea0e5d6859 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-10-16 +date: 2023-10-17 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 9c52d0df22115d..8ce94ac16fcee7 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-10-16 +date: 2023-10-17 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 eb1464eaa4a9c4..7a361f276babf5 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-10-16 +date: 2023-10-17 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 fb171d78b6329a..fa2dbd98221323 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-10-16 +date: 2023-10-17 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 a3b0c82f024da3..508ae3b8536839 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-10-16 +date: 2023-10-17 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 d61407753deb49..75aca7f07e7a02 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-10-16 +date: 2023-10-17 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 c6a74b5d7d5349..197c8b9e9bc26e 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-10-16 +date: 2023-10-17 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 619e97c4d63909..9605228ce6245d 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-10-16 +date: 2023-10-17 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 0226d1d60ac98b..99531d9ab062c9 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-10-16 +date: 2023-10-17 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 f8f823203cb474..bfca0d86473657 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-10-16 +date: 2023-10-17 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 bd6927e3c1dee4..22b0eb553905ba 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-10-16 +date: 2023-10-17 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 0b1c090034ba82..31ab7e90df4464 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 31816829e27e91..6ef62450ad3449 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -3269,6 +3269,52 @@ ], "returnComment": [] }, + { + "parentPluginId": "fleet", + "id": "def-public.pagePathGetters.integration_details_configs", + "type": "Function", + "tags": [], + "label": "integration_details_configs", + "description": [], + "signature": [ + "({ pkgkey, integration }: ", + { + "pluginId": "fleet", + "scope": "public", + "docId": "kibFleetPluginApi", + "section": "def-public.DynamicPagePathValues", + "text": "DynamicPagePathValues" + }, + ") => [string, string]" + ], + "path": "x-pack/plugins/fleet/public/constants/page_paths.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-public.pagePathGetters.integration_details_configs.$1", + "type": "Object", + "tags": [], + "label": "{ pkgkey, integration }", + "description": [], + "signature": [ + { + "pluginId": "fleet", + "scope": "public", + "docId": "kibFleetPluginApi", + "section": "def-public.DynamicPagePathValues", + "text": "DynamicPagePathValues" + } + ], + "path": "x-pack/plugins/fleet/public/constants/page_paths.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "fleet", "id": "def-public.pagePathGetters.integration_details_custom", @@ -17781,6 +17827,20 @@ "path": "x-pack/plugins/fleet/common/types/models/agent_policy.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "fleet", + "id": "def-common.AgentPolicy.keep_monitoring_alive", + "type": "CompoundType", + "tags": [], + "label": "keep_monitoring_alive", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/agent_policy.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -19431,7 +19491,9 @@ "label": "agent", "description": [], "signature": [ - "{ monitoring: { namespace?: string | undefined; use_output?: string | undefined; enabled: boolean; metrics: boolean; logs: boolean; }; download: { sourceURI: string; }; features: Record; protection?: { enabled: boolean; uninstall_token_hash: string; signing_key: string; } | undefined; } | undefined" + "{ monitoring: ", + "FullAgentPolicyMonitoring", + "; download: { sourceURI: string; }; features: Record; protection?: { enabled: boolean; uninstall_token_hash: string; signing_key: string; } | undefined; } | undefined" ], "path": "x-pack/plugins/fleet/common/types/models/agent_policy.ts", "deprecated": false, @@ -27601,6 +27663,53 @@ "trackAdoption": false, "children": [], "returnComment": [] + }, + { + "parentPluginId": "fleet", + "id": "def-common.epmRouteService.getInputsTemplatesPath", + "type": "Function", + "tags": [], + "label": "getInputsTemplatesPath", + "description": [], + "signature": [ + "(pkgName: string, pkgVersion: string) => string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-common.epmRouteService.getInputsTemplatesPath.$1", + "type": "string", + "tags": [], + "label": "pkgName", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "fleet", + "id": "def-common.epmRouteService.getInputsTemplatesPath.$2", + "type": "string", + "tags": [], + "label": "pkgVersion", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 02ed3c16942654..e10ba0c2c95ab4 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1202 | 3 | 1084 | 42 | +| 1208 | 3 | 1090 | 43 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index a04076c6a281bd..294043c0b4e0af 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-10-16 +date: 2023-10-17 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 05cf43c1e714b1..7ee2c22aea6457 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-10-16 +date: 2023-10-17 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 e92f5b3d1ab9f8..e201218f8b108d 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-10-16 +date: 2023-10-17 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 20979791622d58..bedcf9289117f3 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-10-16 +date: 2023-10-17 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 d393024f11bd8e..4a16cc47b8562e 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-10-16 +date: 2023-10-17 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 7635bfc96eb3ba..6e81bfa83cbffd 100644 --- a/api_docs/index_management.devdocs.json +++ b/api_docs/index_management.devdocs.json @@ -1526,13 +1526,14 @@ { "parentPluginId": "indexManagement", "id": "def-common.DataStream.lifecycle", - "type": "Object", + "type": "CompoundType", "tags": [], "label": "lifecycle", "description": [], "signature": [ + "(", "IndicesDataLifecycleWithRollover", - " | undefined" + " & { enabled?: boolean | undefined; }) | undefined" ], "path": "x-pack/plugins/index_management/common/types/data_streams.ts", "deprecated": false, diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 8b364acc2fdf4c..34fa5b65248dd8 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index e92b8e63be5379..28a86837a07038 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-10-16 +date: 2023-10-17 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 3d6b2868bf4e6a..607f101785afaf 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-10-16 +date: 2023-10-17 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 5f68c8ba978c7c..b861084bc6f8d9 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-10-16 +date: 2023-10-17 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 ec551aa93720c4..f24d13ad3c1baf 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-10-16 +date: 2023-10-17 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 2ee6f9b7963106..7f111b27796d2f 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-10-16 +date: 2023-10-17 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 e7f86e6ac1b766..21ce788f458c02 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-10-16 +date: 2023-10-17 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 c780f49b436133..bdfb82934e148f 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-10-16 +date: 2023-10-17 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 aa7af341685766..17552883bb50f5 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-10-16 +date: 2023-10-17 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 937ef4eb0b34b5..c10933a2e584ca 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-10-16 +date: 2023-10-17 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 07f9af265aa087..37c648f26df25b 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-10-16 +date: 2023-10-17 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 235261cafececf..b45f523dcf0754 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-10-16 +date: 2023-10-17 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 c689d9e90a584e..1bea59f569db61 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-10-16 +date: 2023-10-17 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 8947f4f2d79db5..f1b840c8cf083b 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-10-16 +date: 2023-10-17 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 6e46476771688f..4fcd800fa08905 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-10-16 +date: 2023-10-17 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 609e7048fd7d4c..8f785a129d754c 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-10-16 +date: 2023-10-17 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 1105dcffcf960b..c61cf4706338f7 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-10-16 +date: 2023-10-17 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 eb6033495b6bfd..d58bc1e0b85dff 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-10-16 +date: 2023-10-17 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 33a1fa60ffab69..125cee1ce451a4 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-10-16 +date: 2023-10-17 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 fc04c18ad6df06..aa921476251dc4 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-10-16 +date: 2023-10-17 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 321996700884fc..2c3f57d91dab85 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-10-16 +date: 2023-10-17 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 9014bb355f5cee..f6c6dc10457810 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-10-16 +date: 2023-10-17 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 fe4aa453204a2c..e0d4804415547b 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-10-16 +date: 2023-10-17 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 cda82805b6629c..301d820ee903ea 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-10-16 +date: 2023-10-17 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 957da597bbe222..d7d64e7666a9c7 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-10-16 +date: 2023-10-17 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 29d0075d5b5d8b..bb1ae0ffd5a384 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-10-16 +date: 2023-10-17 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 1225e4f2ee8d97..3456b88d4f68c4 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-10-16 +date: 2023-10-17 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 b0d4d982f3e2b8..ed7a7345362ea2 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-10-16 +date: 2023-10-17 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 d48aab93d9e61e..857415c537340a 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-10-16 +date: 2023-10-17 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 72e8321ad61258..30540e5bad7332 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-10-16 +date: 2023-10-17 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 50df06c013c77c..69be9d21ab639e 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-10-16 +date: 2023-10-17 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 8f524597cf0a4e..f506f43cc73704 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-10-16 +date: 2023-10-17 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 9d9c29db5ac950..605001160837fe 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-10-16 +date: 2023-10-17 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 aac4ad27d45c82..28eb5f07578a96 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-10-16 +date: 2023-10-17 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 7077a1a0255163..5edc888e9d7652 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-10-16 +date: 2023-10-17 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 7351b9c05fcb84..a7d3218217ef1d 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-10-16 +date: 2023-10-17 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 4ac0ff8f19a6a1..792061cd1c9924 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-10-16 +date: 2023-10-17 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 25e88da08a90ca..91133fcbce883f 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-10-16 +date: 2023-10-17 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 fd3c483e75ccfd..57a5dc416bebd2 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-10-16 +date: 2023-10-17 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 5b69279df63678..cc87df2d731127 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-10-16 +date: 2023-10-17 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 063df01ba4edc1..62e3f75d209182 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-10-16 +date: 2023-10-17 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 3a8e5cb87cfebf..c80de7f136a3d4 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-10-16 +date: 2023-10-17 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 3cd3125ab493e1..5676843336ff6c 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-10-16 +date: 2023-10-17 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 82a125e513553c..71514053b44197 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-10-16 +date: 2023-10-17 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 c6920f72a31340..f373c880d7ea5c 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-10-16 +date: 2023-10-17 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 00bc996e293252..56c92d4b375f02 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-10-16 +date: 2023-10-17 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 fe9063f64cf2a3..590486afd0b1e9 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-10-16 +date: 2023-10-17 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 5485e3700f843f..523eea43000ef9 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-10-16 +date: 2023-10-17 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 4e121a0202be92..b362faa3d45964 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-10-16 +date: 2023-10-17 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 315da2cd036dc3..cdb6efd28345d1 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-10-16 +date: 2023-10-17 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 a2b3e15379011a..c514789c3612dd 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-10-16 +date: 2023-10-17 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 3eb12df2a96767..8a3f93eaa59ecc 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-10-16 +date: 2023-10-17 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 05e7bf7754fb06..4813860f00f826 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-10-16 +date: 2023-10-17 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 57d137fb0fec4b..c8f892aa525994 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-10-16 +date: 2023-10-17 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 f2d28f856a98f7..eca63186b26343 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-10-16 +date: 2023-10-17 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 b0eec5a4af374f..d2a3372d95c3ef 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-10-16 +date: 2023-10-17 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 1bad44ae2cdc55..9e816e4abe7390 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-10-16 +date: 2023-10-17 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 2f360400c5f860..5ffa0c34f72605 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-10-16 +date: 2023-10-17 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 7aafeb1e050338..f4ffec00592b06 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-10-16 +date: 2023-10-17 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 3e5281a82d196c..257222a9dda68c 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-10-16 +date: 2023-10-17 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 5a2e9033536dfa..436d38caefeadc 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-10-16 +date: 2023-10-17 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 aaa18d2fdc686d..211bbdbc8039b9 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-10-16 +date: 2023-10-17 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 3cac10066ef680..adbe60b8d8e71a 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-10-16 +date: 2023-10-17 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 f036d6d2082533..3ba5de16dc3140 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-10-16 +date: 2023-10-17 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 c42f7676c913e1..a9e4d04eb2c8b5 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-10-16 +date: 2023-10-17 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 2497797159de62..cf9affc14ad04a 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-10-16 +date: 2023-10-17 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 02e53c58ce3743..f26b7a1c36060e 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-10-16 +date: 2023-10-17 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 e1c21c2d4478e3..76964b6badf6ae 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-10-16 +date: 2023-10-17 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 48da918642a632..2a6f36235af7bb 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-10-16 +date: 2023-10-17 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 ed1d65f37c8e0b..e24461f250ad1e 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-10-16 +date: 2023-10-17 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 814301bc1531ee..baca4ef57edf66 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-10-16 +date: 2023-10-17 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 ecf12445c2a894..ce67d8ade40423 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-10-16 +date: 2023-10-17 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 e003df0b6cd241..8b9bb43e8b4194 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-10-16 +date: 2023-10-17 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 23b723b1c5575b..6e36721e6a7418 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-10-16 +date: 2023-10-17 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 dadb6931dd14bc..03b2a4c824ab39 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-10-16 +date: 2023-10-17 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 63d783e0a8967d..52d72fd33b80e6 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-10-16 +date: 2023-10-17 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 fccfb2f6fcac08..ff79fc108cfc81 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-10-16 +date: 2023-10-17 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 562568dfbf56b2..63bd4fa4a0b867 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-10-16 +date: 2023-10-17 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 37f1cfdf744ea4..b03523b67392f3 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-10-16 +date: 2023-10-17 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 ca98c79bbb050a..ef26be8adf1917 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-10-16 +date: 2023-10-17 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 0eed7981fe2a92..79d8624097c8d0 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-10-16 +date: 2023-10-17 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 091dedaf8f1834..f1574aa8174816 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-10-16 +date: 2023-10-17 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 cb179a925865f8..31078d04b6cb0a 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-10-16 +date: 2023-10-17 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 275377e6e46f1f..11b17a2f10728a 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-10-16 +date: 2023-10-17 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 60eed9dbe4ba74..b95bf2a78edb5d 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-10-16 +date: 2023-10-17 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 f81fab3b16a497..18aa1651327691 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-10-16 +date: 2023-10-17 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.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index ecbbc111882ef5..7b4d0093c0a16b 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 1d4d67d43d9319..73b8ac4a3686d6 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 64826635697a8d..5c2cff85031131 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 54fd698da013cf..1cbdf72a18e5d9 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-10-16 +date: 2023-10-17 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 ff2214ac484c1f..6e0d9e9b46d19f 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-10-16 +date: 2023-10-17 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 4c4183cbc6af9d..bc1f09b82e11be 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-10-16 +date: 2023-10-17 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 f32ef3ceeea7cb..879d622e5b6fa5 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-10-16 +date: 2023-10-17 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 5976d20798c8a7..a842e3ea692460 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-10-16 +date: 2023-10-17 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 7cdac601fb0b23..88e0567d1d09d7 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-10-16 +date: 2023-10-17 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 3be65c0d8ccba1..26c773de8c2d3b 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-10-16 +date: 2023-10-17 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 c57df615c38a66..b7f505748ec077 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-10-16 +date: 2023-10-17 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 6cc14ca40d8ae6..0183854b9ac497 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-10-16 +date: 2023-10-17 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 356ea2ec840199..aa9569680a5610 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-10-16 +date: 2023-10-17 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 d94d8d35f146f1..c12a97bcd3a13a 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-10-16 +date: 2023-10-17 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 e74373b828bd0a..891801aee23b48 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-10-16 +date: 2023-10-17 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 d43205bc6bab81..6aa0f2e5d54cd4 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-10-16 +date: 2023-10-17 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 c8184fde36da54..0734c13b6f495b 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-10-16 +date: 2023-10-17 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 8f3ecc0e07cce4..47e399d99f0483 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-10-16 +date: 2023-10-17 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 cb39bb3805fd78..d2e55a61a6cb35 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-10-16 +date: 2023-10-17 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 c32feb28d39d6a..e4fad9d5997738 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-10-16 +date: 2023-10-17 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 350bdb076b4ec6..2d401393b92b7e 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-10-16 +date: 2023-10-17 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 a714f73163fa94..66f6027212e58d 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-10-16 +date: 2023-10-17 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 4831b14a96f0a9..9712e2de2b2f10 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-10-16 +date: 2023-10-17 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 197367fe2e91db..8f84f1d22417bc 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-10-16 +date: 2023-10-17 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 1f3f5eac955569..70a77351b3ab21 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-10-16 +date: 2023-10-17 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 46eb209956b1fc..d88d8a1fd7250b 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -12893,6 +12893,10 @@ "plugin": "dataViews", "path": "src/plugins/data_views/server/rest_api_routes/public/has_user_data_view.ts" }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts" + }, { "plugin": "dataViews", "path": "src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts" diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index ca3dcfb8872e13..784d53314f9aed 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-10-16 +date: 2023-10-17 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 c0e253ff28ecca..c779d59a4f22fa 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-10-16 +date: 2023-10-17 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 cbf313cb079069..08946f1a35c9ea 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-10-16 +date: 2023-10-17 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 3193d20175b6ac..c319f22f8188be 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-10-16 +date: 2023-10-17 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 4650f03c182799..e80328a76f3545 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-10-16 +date: 2023-10-17 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 532002fba3e113..cc0f4898db7d0a 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-10-16 +date: 2023-10-17 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 6799f662bb0dd1..d3f000f64098f3 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-10-16 +date: 2023-10-17 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 304d1082a1fb38..e0ef09c6faec53 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-10-16 +date: 2023-10-17 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 a98020173db1cf..a7417dca1aaa1a 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-10-16 +date: 2023-10-17 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 493b2c4bb3feb0..3e478d6f4b53bf 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-10-16 +date: 2023-10-17 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 01fd1a84853c20..bf7fd3ad464366 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-10-16 +date: 2023-10-17 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 c5edc9234b348d..618b28c43e99cf 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-10-16 +date: 2023-10-17 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 5f3ff98bd39aa0..2bd868e8f8311a 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-10-16 +date: 2023-10-17 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 29bd12e94523c5..92639f54ab8f39 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-10-16 +date: 2023-10-17 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 101068313b1f55..32101dc9c54aa1 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-10-16 +date: 2023-10-17 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 36896a3ef5d3e2..dfb374ec51d079 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-10-16 +date: 2023-10-17 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 ad3e3de4b948fe..210e8423bb0e6d 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-10-16 +date: 2023-10-17 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 e8734722031927..03cf1bb25a3399 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-10-16 +date: 2023-10-17 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 1f97e30bda4872..aee479ea687584 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-10-16 +date: 2023-10-17 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 2d585ad885b0fa..ff6c63e72cb042 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-10-16 +date: 2023-10-17 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 e6e46973bd6a85..de421df3dd8a7a 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-10-16 +date: 2023-10-17 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 d315f7a17c3901..60a4a04ea56b04 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-10-16 +date: 2023-10-17 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 abf17ce0da48dd..b0a0207307e9a6 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-10-16 +date: 2023-10-17 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 5569420888d4ee..8ac0e295d30102 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-10-16 +date: 2023-10-17 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 73f2d545a7b154..1af25d7acbd1f8 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-10-16 +date: 2023-10-17 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 db8b8b7c159483..98ae0b69dd6cef 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-10-16 +date: 2023-10-17 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 8c312aea792852..ed033f477fc7d0 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-10-16 +date: 2023-10-17 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 e0dc9e7a50bced..9d5ad1f479b108 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-10-16 +date: 2023-10-17 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 1052a2c97ea578..bd67e074c83277 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-10-16 +date: 2023-10-17 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 b578688efe7db7..15d358cfc2952c 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-10-16 +date: 2023-10-17 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 d440777cf50c0f..e6fe2e8ecb17d0 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-10-16 +date: 2023-10-17 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 c344bada51e299..2f7ec4415c6c79 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-10-16 +date: 2023-10-17 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 14a2dc32932355..beedf8d4e58f47 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-10-16 +date: 2023-10-17 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 f289ed664b3c69..6367a14852e116 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-10-16 +date: 2023-10-17 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 23c911546e8e6a..b8bb68a2cfd9c0 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-10-16 +date: 2023-10-17 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 5464caa2ac3473..66111a0f7d6579 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-10-16 +date: 2023-10-17 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 5c633b6242ed71..838daf6d8e1d03 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-10-16 +date: 2023-10-17 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 6148030a9ed49a..fe89389e84e94c 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-10-16 +date: 2023-10-17 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 a7991bc66cd603..aa7575c38a2ad4 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-10-16 +date: 2023-10-17 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 f606f93c6b1a01..5720a448ebb240 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-10-16 +date: 2023-10-17 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 ed6117020c0fc2..56a260ff8ebcd2 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-10-16 +date: 2023-10-17 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 cf3be58a5185d4..bad727a256176a 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-10-16 +date: 2023-10-17 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 7f32ad19cb2296..e54cb36eb21bce 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-10-16 +date: 2023-10-17 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 13c3cbb2ebe1f6..72ae780f7db927 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-10-16 +date: 2023-10-17 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 1f2da43b5e026d..a0a41359baad4a 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-10-16 +date: 2023-10-17 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 29f3be2031a1bb..6eb8522aafbf2c 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-10-16 +date: 2023-10-17 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 4047fe32a2f08e..8ac098e14dffbc 100644 --- a/api_docs/kbn_core_saved_objects_api_server.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_server.devdocs.json @@ -5857,7 +5857,8 @@ "Optional purpose used to determine filtering and authorization checks; default is 'collectMultiNamespaceReferences'" ], "signature": [ - "\"collectMultiNamespaceReferences\" | \"updateObjectsSpaces\" | undefined" + "SavedObjectsCollectMultiNamespaceReferencesPurpose", + " | undefined" ], "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/collect_multinamespace_references.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 6020cabc1b8ec2..f35bc7f40cf524 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-10-16 +date: 2023-10-17 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 | |-------------------|-----------|------------------------|-----------------| -| 352 | 1 | 5 | 1 | +| 352 | 1 | 5 | 2 | ## 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 33eefae0e038f4..1f3eda2b9f1b38 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-10-16 +date: 2023-10-17 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 402fb39f805775..02637ce1468c88 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-10-16 +date: 2023-10-17 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 2249c29b5ab847..cb99f7a5dde39f 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-10-16 +date: 2023-10-17 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 4be8337f368046..94469755b93b09 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-10-16 +date: 2023-10-17 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 a5d8205ade38a2..8591454a5f9548 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-10-16 +date: 2023-10-17 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 67971673ea0f04..1578ff9692585e 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-10-16 +date: 2023-10-17 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 9ef9823515cb9d..d2c740366d2312 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-10-16 +date: 2023-10-17 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 22d97abdd20f6b..56bc9e2f1c5054 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-10-16 +date: 2023-10-17 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 d1a97d5dab6261..ad8e13a8a91322 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-10-16 +date: 2023-10-17 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.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index 2ab99c2f92c342..0e1271923ccfd4 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; 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 4e64806e388c9a..30382ecaab6e43 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-10-16 +date: 2023-10-17 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 10c99eb797109c..cf5c89f57edf20 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-10-16 +date: 2023-10-17 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 fe0a8c100dd9b7..d34b7c64e736a6 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-10-16 +date: 2023-10-17 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 319e699c4ea987..115eea47a436c8 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-10-16 +date: 2023-10-17 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 6f4aad8004728c..79845354a5f192 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-10-16 +date: 2023-10-17 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 b14e63761844b9..ade68aee40e817 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-10-16 +date: 2023-10-17 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 3ba07fe2813e62..d234c9506c7793 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-10-16 +date: 2023-10-17 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 1e25708e4fe567..e51f2cfe24ba88 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-10-16 +date: 2023-10-17 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 8b7e1bfa5c81df..cd8255edd256ca 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-10-16 +date: 2023-10-17 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 753e7e48dd1270..965bbab2e503ed 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-10-16 +date: 2023-10-17 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 1c63557bfa8249..5329336b9544b8 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-10-16 +date: 2023-10-17 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 bf0093070e4943..5532f33ab2e4e4 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-10-16 +date: 2023-10-17 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.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index adc8e8eef25fc8..6b29d8a99554ed 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-10-16 +date: 2023-10-17 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_model_versions.mdx b/api_docs/kbn_core_test_helpers_model_versions.mdx index 85533c5d6181c5..03770ea48bacdf 100644 --- a/api_docs/kbn_core_test_helpers_model_versions.mdx +++ b/api_docs/kbn_core_test_helpers_model_versions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-model-versions title: "@kbn/core-test-helpers-model-versions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-model-versions plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-model-versions'] --- import kbnCoreTestHelpersModelVersionsObj from './kbn_core_test_helpers_model_versions.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 c0412ac840a827..6a2c4514eb72b7 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-10-16 +date: 2023-10-17 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 8bc49543e34d37..d6f23a203c5661 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-10-16 +date: 2023-10-17 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 e65cac93ea077f..ce2024bb5248f9 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-10-16 +date: 2023-10-17 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 f09c587333a06a..c965febf4fb079 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-10-16 +date: 2023-10-17 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 6ff5edbf3a58eb..a8d9bb4f3ac0c1 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-10-16 +date: 2023-10-17 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 ced93ecc2fefc3..ee728910e42f9e 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-10-16 +date: 2023-10-17 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 4420a4598f97e2..dbe2bc10d74ce6 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-10-16 +date: 2023-10-17 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 e6d637da6ac7a7..5a25486e525182 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-10-16 +date: 2023-10-17 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 9cd54f6f60053c..9fe6627c325cd5 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-10-16 +date: 2023-10-17 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 0a9fcf8f4ae1c5..838fcb1aae3568 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-10-16 +date: 2023-10-17 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 b505df20fdce0f..cc2c366472b93f 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-10-16 +date: 2023-10-17 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 f7da18c6ddbffc..ecdc9f63d3f231 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-10-16 +date: 2023-10-17 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 697c81e5085e9b..b67f94f44acd68 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-10-16 +date: 2023-10-17 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 77f45a60d4a0f7..e6a92a1ee0e102 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-10-16 +date: 2023-10-17 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 077727b2f9222d..121fa189456ca9 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-10-16 +date: 2023-10-17 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 25be6c576897b6..fd8537dc850bca 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-10-16 +date: 2023-10-17 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 6492cc8e8ffcbb..4922f6c1ac14a9 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-10-16 +date: 2023-10-17 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 8ba8a187b414db..00ac9bcfa92b9a 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-10-16 +date: 2023-10-17 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 2a66c46ec9639b..dc7836b73f9e17 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_custom_integrations.mdx b/api_docs/kbn_custom_integrations.mdx index 9dcda0273936a8..8f43e186748924 100644 --- a/api_docs/kbn_custom_integrations.mdx +++ b/api_docs/kbn_custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-integrations title: "@kbn/custom-integrations" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-integrations plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-integrations'] --- import kbnCustomIntegrationsObj from './kbn_custom_integrations.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index a4484f1cef7fd0..c6d5cc7e2a2f36 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-10-16 +date: 2023-10-17 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 57a3c95464d882..c8608795376d4f 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-10-16 +date: 2023-10-17 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 4f3c04a720eb8d..052febf795a119 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-10-16 +date: 2023-10-17 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 80cd90fb516ad6..439e3851d53e68 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-10-16 +date: 2023-10-17 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 9eff7dfdd4ea27..79f2b1056fd0af 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-10-16 +date: 2023-10-17 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 9824c4194ebc7f..8c0a413406b99a 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-10-16 +date: 2023-10-17 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 98da60e812f4c7..1395ae3325cab8 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-10-16 +date: 2023-10-17 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 ddfb2445d51fb2..0e3a433971632a 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-10-16 +date: 2023-10-17 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 e6a38eda98e74e..4a49fb66d54178 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-10-16 +date: 2023-10-17 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 c825f742c61616..9ae22cb5eb77b4 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-10-16 +date: 2023-10-17 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 a0dca38a23f1a2..a89ef9ace78abb 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-10-16 +date: 2023-10-17 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 f51d792f0dadc4..72711c81df54d2 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-10-16 +date: 2023-10-17 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 87679fe0aef810..2a493255e4aea6 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-10-16 +date: 2023-10-17 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 d23ab5a5b1629f..208bc76cf1809e 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-10-16 +date: 2023-10-17 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 f0b8ca10bd6f76..c446ea3a3da6f0 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-10-16 +date: 2023-10-17 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 83657569027836..8b3593fa76a154 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-10-16 +date: 2023-10-17 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 a1bc9ae340896c..69a6c8203e9324 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-10-16 +date: 2023-10-17 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 ef16b507146ed6..5794ae515afd7e 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.devdocs.json b/api_docs/kbn_doc_links.devdocs.json index a2b80377475658..75a7a05e00db54 100644 --- a/api_docs/kbn_doc_links.devdocs.json +++ b/api_docs/kbn_doc_links.devdocs.json @@ -300,7 +300,7 @@ "label": "enterpriseSearch", "description": [], "signature": [ - "{ readonly aiSearchDoc: string; readonly aiSearchHelp: string; readonly apiKeys: string; readonly behavioralAnalytics: string; readonly behavioralAnalyticsCORS: string; readonly behavioralAnalyticsEvents: string; readonly buildConnector: string; readonly bulkApi: string; readonly configuration: string; readonly connectors: string; readonly connectorsAzureBlobStorage: string; readonly connectorsBox: string; readonly connectorsClients: string; readonly connectorsConfluence: string; readonly connectorsContentExtraction: string; readonly connectorsDropbox: string; readonly connectorsGithub: string; readonly connectorsGoogleCloudStorage: string; readonly connectorsGoogleDrive: string; readonly connectorsGmail: string; readonly connectorsJira: string; readonly connectorsMicrosoftSQL: string; readonly connectorsMongoDB: string; readonly connectorsMySQL: string; readonly connectorsNative: string; readonly connectorsNetworkDrive: string; readonly connectorsOneDrive: string; readonly connectorsOracle: string; readonly connectorsOutlook: string; readonly connectorsPostgreSQL: string; readonly connectorsS3: string; readonly connectorsSalesforce: string; readonly connectorsServiceNow: string; readonly connectorsSharepoint: string; readonly connectorsSharepointOnline: string; readonly connectorsTeams: string; readonly connectorsSlack: string; readonly connectorsWorkplaceSearch: string; readonly connectorsZoom: string; readonly crawlerExtractionRules: string; readonly crawlerManaging: string; readonly crawlerOverview: string; readonly deployTrainedModels: string; readonly documentLevelSecurity: string; readonly elser: string; readonly engines: string; readonly indexApi: string; readonly ingestionApis: string; readonly ingestPipelines: string; readonly knnSearch: string; readonly knnSearchCombine: string; readonly languageAnalyzers: string; readonly languageClients: string; readonly licenseManagement: string; readonly machineLearningStart: string; readonly mailService: string; readonly mlDocumentEnrichment: string; readonly mlDocumentEnrichmentUpdateMappings: string; readonly searchApplicationsTemplates: string; readonly searchApplicationsSearchApi: string; readonly searchApplications: string; readonly searchApplicationsSearch: string; readonly searchLabs: string; readonly searchLabsRepo: string; readonly searchTemplates: string; readonly start: string; readonly supportedNlpModels: string; readonly syncRules: string; readonly trainedModels: string; readonly textEmbedding: string; readonly troubleshootSetup: string; readonly usersAccess: string; }" + "{ readonly aiSearchDoc: string; readonly aiSearchHelp: string; readonly apiKeys: string; readonly behavioralAnalytics: string; readonly behavioralAnalyticsCORS: string; readonly behavioralAnalyticsEvents: string; readonly buildConnector: string; readonly bulkApi: string; readonly configuration: string; readonly connectors: string; readonly connectorsAzureBlobStorage: string; readonly connectorsBox: string; readonly connectorsClients: string; readonly connectorsConfluence: string; readonly connectorsContentExtraction: string; readonly connectorsDropbox: string; readonly connectorsGithub: string; readonly connectorsGoogleCloudStorage: string; readonly connectorsGoogleDrive: string; readonly connectorsGmail: string; readonly connectorsJira: string; readonly connectorsMicrosoftSQL: string; readonly connectorsMongoDB: string; readonly connectorsMySQL: string; readonly connectorsNative: string; readonly connectorsNetworkDrive: string; readonly connectorsOneDrive: string; readonly connectorsOracle: string; readonly connectorsOutlook: string; readonly connectorsPostgreSQL: string; readonly connectorsS3: string; readonly connectorsSalesforce: string; readonly connectorsServiceNow: string; readonly connectorsSharepoint: string; readonly connectorsSharepointOnline: string; readonly connectorsTeams: string; readonly connectorsSlack: string; readonly connectorsZoom: string; readonly crawlerExtractionRules: string; readonly crawlerManaging: string; readonly crawlerOverview: string; readonly deployTrainedModels: string; readonly documentLevelSecurity: string; readonly elser: string; readonly engines: string; readonly indexApi: string; readonly ingestionApis: string; readonly ingestPipelines: string; readonly knnSearch: string; readonly knnSearchCombine: string; readonly languageAnalyzers: string; readonly languageClients: string; readonly licenseManagement: string; readonly machineLearningStart: string; readonly mailService: string; readonly mlDocumentEnrichment: string; readonly mlDocumentEnrichmentUpdateMappings: string; readonly searchApplicationsTemplates: string; readonly searchApplicationsSearchApi: string; readonly searchApplications: string; readonly searchApplicationsSearch: string; readonly searchLabs: string; readonly searchLabsRepo: string; readonly searchTemplates: string; readonly start: string; readonly supportedNlpModels: string; readonly syncRules: string; readonly trainedModels: string; readonly textEmbedding: string; readonly troubleshootSetup: string; readonly usersAccess: string; }" ], "path": "packages/kbn-doc-links/src/types.ts", "deprecated": false, @@ -840,7 +840,7 @@ "label": "fleet", "description": [], "signature": [ - "{ readonly beatsAgentComparison: string; readonly guide: string; readonly fleetServer: string; readonly fleetServerAddFleetServer: string; readonly esSettings: string; readonly settings: string; readonly logstashSettings: string; readonly kafkaSettings: string; readonly settingsFleetServerHostSettings: string; readonly settingsFleetServerProxySettings: string; readonly troubleshooting: string; readonly elasticAgent: string; readonly datastreams: string; readonly datastreamsILM: string; readonly datastreamsNamingScheme: string; readonly datastreamsManualRollover: string; readonly datastreamsTSDS: string; readonly datastreamsTSDSMetrics: string; readonly installElasticAgent: string; readonly installElasticAgentStandalone: string; readonly packageSignatures: string; readonly upgradeElasticAgent: string; readonly learnMoreBlog: string; readonly apiKeysLearnMore: string; readonly onPremRegistry: string; readonly secureLogstash: string; readonly agentPolicy: string; readonly api: string; readonly uninstallAgent: string; readonly installAndUninstallIntegrationAssets: string; }" + "{ readonly beatsAgentComparison: string; readonly guide: string; readonly fleetServer: string; readonly fleetServerAddFleetServer: string; readonly esSettings: string; readonly settings: string; readonly logstashSettings: string; readonly kafkaSettings: string; readonly settingsFleetServerHostSettings: string; readonly settingsFleetServerProxySettings: string; readonly troubleshooting: string; readonly elasticAgent: string; readonly datastreams: string; readonly datastreamsILM: string; readonly datastreamsNamingScheme: string; readonly datastreamsManualRollover: string; readonly datastreamsTSDS: string; readonly datastreamsTSDSMetrics: string; readonly installElasticAgent: string; readonly installElasticAgentStandalone: string; readonly packageSignatures: string; readonly upgradeElasticAgent: string; readonly learnMoreBlog: string; readonly apiKeysLearnMore: string; readonly onPremRegistry: string; readonly secureLogstash: string; readonly agentPolicy: string; readonly api: string; readonly uninstallAgent: string; readonly installAndUninstallIntegrationAssets: string; readonly elasticAgentInputConfiguration: string; }" ], "path": "packages/kbn-doc-links/src/types.ts", "deprecated": false, diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index ad30c71e18cadf..42369cbd064a91 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-10-16 +date: 2023-10-17 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 66e5b5ab046380..077724c079f350 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-10-16 +date: 2023-10-17 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 c1243158ec503c..d8e78c4e7ed190 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-10-16 +date: 2023-10-17 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 6b086f32b908f8..d2a41664d99633 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-10-16 +date: 2023-10-17 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 68cf71de5abcef..7e19bf2b752c40 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-10-16 +date: 2023-10-17 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 4ae2207818e403..b4bbfc4268b87f 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-10-16 +date: 2023-10-17 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.mdx b/api_docs/kbn_elastic_assistant.mdx index a37a1935ff08fe..4a6e9ec026c93d 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-10-16 +date: 2023-10-17 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 f9371046745b66..6d8467150869d1 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-10-16 +date: 2023-10-17 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 1c2850e560cf58..45b31d05190d86 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-10-16 +date: 2023-10-17 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 e5efeb8c15c708..ca836e5a68fa52 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-10-16 +date: 2023-10-17 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 fb48376da0b66d..6984a273d3af63 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-10-16 +date: 2023-10-17 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 ddadfe3d86efc2..1122fe1ce34775 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-10-16 +date: 2023-10-17 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 426bf896091621..b4eb28b97ce35e 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-10-16 +date: 2023-10-17 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 ea0d58d6cc4464..778bd22ea1f3ca 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-10-16 +date: 2023-10-17 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 f234d4a0f2eac1..40ff5c5b4c6001 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-10-16 +date: 2023-10-17 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 b3a8b5265956f3..be3eb2206755e3 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-10-16 +date: 2023-10-17 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 22c95b5d45bd7e..2c858b2235f654 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_field_utils.mdx b/api_docs/kbn_field_utils.mdx index cd03b222a1bd46..74e00a5d67edd9 100644 --- a/api_docs/kbn_field_utils.mdx +++ b/api_docs/kbn_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-utils title: "@kbn/field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-utils plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-utils'] --- import kbnFieldUtilsObj from './kbn_field_utils.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index f799a209c84774..72e5fac960de53 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-10-16 +date: 2023-10-17 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 4b3606d88e274d..9ee48740b5764d 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-10-16 +date: 2023-10-17 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 55707e5ea80494..b99f419b543478 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-10-16 +date: 2023-10-17 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 bb88307a5038f1..fcc83b8376c8fb 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-10-16 +date: 2023-10-17 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 c791a996a6c1b6..bb4533189accb5 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-10-16 +date: 2023-10-17 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 44e5fc2f1696d3..69eccfe98f8353 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-10-16 +date: 2023-10-17 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 7d3ccbee88f217..daba723741ac9e 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-10-16 +date: 2023-10-17 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 d46faa6058672f..1796d99213e7ea 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-10-16 +date: 2023-10-17 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 766c43d3f508f2..c835b7449e29ba 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-10-16 +date: 2023-10-17 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 c531cd5cf3e944..6e2bbcdaa7d267 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-10-16 +date: 2023-10-17 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 276ed63a9b7059..802384e5daf271 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-10-16 +date: 2023-10-17 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 ffa9af97445429..531e5dcc8bfed4 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-10-16 +date: 2023-10-17 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 9751305dff6230..7c76d20f12ede5 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-10-16 +date: 2023-10-17 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 3033ea9f09e6c1..9b9086ffd45ddb 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-10-16 +date: 2023-10-17 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 a70b07ccede1b4..0cdf73959282da 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-10-16 +date: 2023-10-17 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 792f3c7149e94d..43674dae39aaf4 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-10-16 +date: 2023-10-17 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 1846ac148f7a3d..b9127f2abfb627 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-10-16 +date: 2023-10-17 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 83c209acf919c8..807f4284217f97 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-10-16 +date: 2023-10-17 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 f6e8428fb8cc07..0fd78170433ef4 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-10-16 +date: 2023-10-17 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 4ba9d023401078..7a81141e28b125 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-10-16 +date: 2023-10-17 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 5153baafc9ed36..e1ab9a890e3c07 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-10-16 +date: 2023-10-17 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 b5a6dccb8a7494..222e4c77b7a3cc 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-10-16 +date: 2023-10-17 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 d703c9b0e953a4..8c96c2f07fdd5f 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-10-16 +date: 2023-10-17 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 2b6c35c07ea883..ffaf394dbc42cb 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-10-16 +date: 2023-10-17 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 42645ded452a93..680ad1778fa9c1 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-10-16 +date: 2023-10-17 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 d3b4d089690b85..19156a0ee662df 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-10-16 +date: 2023-10-17 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 da1edd6557aada..4c5a8a0670f4eb 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-10-16 +date: 2023-10-17 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 788d3c511f82db..33600c2a5e444b 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-10-16 +date: 2023-10-17 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_application.mdx b/api_docs/kbn_management_settings_application.mdx index 3634915dcf97ed..775e1bd10c9f19 100644 --- a/api_docs/kbn_management_settings_application.mdx +++ b/api_docs/kbn_management_settings_application.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-application title: "@kbn/management-settings-application" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-application plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-application'] --- import kbnManagementSettingsApplicationObj from './kbn_management_settings_application.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_category.mdx b/api_docs/kbn_management_settings_components_field_category.mdx index 0f8fa389c07d46..607b8416872d8f 100644 --- a/api_docs/kbn_management_settings_components_field_category.mdx +++ b/api_docs/kbn_management_settings_components_field_category.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-category title: "@kbn/management-settings-components-field-category" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-category plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-category'] --- import kbnManagementSettingsComponentsFieldCategoryObj from './kbn_management_settings_components_field_category.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_input.mdx b/api_docs/kbn_management_settings_components_field_input.mdx index 9e27e65b8f8075..69d7cda180831f 100644 --- a/api_docs/kbn_management_settings_components_field_input.mdx +++ b/api_docs/kbn_management_settings_components_field_input.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-input title: "@kbn/management-settings-components-field-input" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-input plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-input'] --- import kbnManagementSettingsComponentsFieldInputObj from './kbn_management_settings_components_field_input.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_row.mdx b/api_docs/kbn_management_settings_components_field_row.mdx index 0a1240291a10d9..cbbbef37dcd8bc 100644 --- a/api_docs/kbn_management_settings_components_field_row.mdx +++ b/api_docs/kbn_management_settings_components_field_row.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-row title: "@kbn/management-settings-components-field-row" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-row plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-row'] --- import kbnManagementSettingsComponentsFieldRowObj from './kbn_management_settings_components_field_row.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_form.mdx b/api_docs/kbn_management_settings_components_form.mdx index 896089ef528b5e..4ec1cde8b5c293 100644 --- a/api_docs/kbn_management_settings_components_form.mdx +++ b/api_docs/kbn_management_settings_components_form.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-form title: "@kbn/management-settings-components-form" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-form plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-form'] --- import kbnManagementSettingsComponentsFormObj from './kbn_management_settings_components_form.devdocs.json'; diff --git a/api_docs/kbn_management_settings_field_definition.mdx b/api_docs/kbn_management_settings_field_definition.mdx index 5207dd4a023352..05abf0dbe9b381 100644 --- a/api_docs/kbn_management_settings_field_definition.mdx +++ b/api_docs/kbn_management_settings_field_definition.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-field-definition title: "@kbn/management-settings-field-definition" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-field-definition plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-field-definition'] --- import kbnManagementSettingsFieldDefinitionObj from './kbn_management_settings_field_definition.devdocs.json'; diff --git a/api_docs/kbn_management_settings_ids.mdx b/api_docs/kbn_management_settings_ids.mdx index 050b6408326a9b..c880732b72c95e 100644 --- a/api_docs/kbn_management_settings_ids.mdx +++ b/api_docs/kbn_management_settings_ids.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-ids title: "@kbn/management-settings-ids" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-ids plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-ids'] --- import kbnManagementSettingsIdsObj from './kbn_management_settings_ids.devdocs.json'; diff --git a/api_docs/kbn_management_settings_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index a2bdfca15da791..3b9e1a218084e4 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-10-16 +date: 2023-10-17 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_settings_types.mdx b/api_docs/kbn_management_settings_types.mdx index 4e5bcdab898215..4bb988419f4107 100644 --- a/api_docs/kbn_management_settings_types.mdx +++ b/api_docs/kbn_management_settings_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-types title: "@kbn/management-settings-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-types plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-types'] --- import kbnManagementSettingsTypesObj from './kbn_management_settings_types.devdocs.json'; diff --git a/api_docs/kbn_management_settings_utilities.mdx b/api_docs/kbn_management_settings_utilities.mdx index 477c0d0f680d8b..b01ebdbac230a0 100644 --- a/api_docs/kbn_management_settings_utilities.mdx +++ b/api_docs/kbn_management_settings_utilities.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-utilities title: "@kbn/management-settings-utilities" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-utilities plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-utilities'] --- import kbnManagementSettingsUtilitiesObj from './kbn_management_settings_utilities.devdocs.json'; diff --git a/api_docs/kbn_management_storybook_config.mdx b/api_docs/kbn_management_storybook_config.mdx index b00a63ff992e92..95d94828b5db2f 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-10-16 +date: 2023-10-17 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 64f2c7d7df3660..0a86e03917f784 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-10-16 +date: 2023-10-17 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 18ca1cfcc109fa..45ff4ac5d2a415 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-10-16 +date: 2023-10-17 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 7ed7490128132a..bfae56ba74719c 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-10-16 +date: 2023-10-17 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 18c8bdf30ce5ba..8c8e2328183c79 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-10-16 +date: 2023-10-17 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 38a8925ab4effe..c30458b0acf950 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-10-16 +date: 2023-10-17 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_chi2test.mdx b/api_docs/kbn_ml_chi2test.mdx index d5fb6904b1dba4..c0276887534e97 100644 --- a/api_docs/kbn_ml_chi2test.mdx +++ b/api_docs/kbn_ml_chi2test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-chi2test title: "@kbn/ml-chi2test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-chi2test plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-chi2test'] --- import kbnMlChi2testObj from './kbn_ml_chi2test.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 2ee6627c4cdd0f..e794e82dfed8d0 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-10-16 +date: 2023-10-17 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 2192b4fe34cf40..f07e1df7384354 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-10-16 +date: 2023-10-17 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 e0147872426e33..f62e4d8528a360 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-10-16 +date: 2023-10-17 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 572cadef739291..2b875575da69ed 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-10-16 +date: 2023-10-17 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 45782862469b8f..27d414c534ce93 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-10-16 +date: 2023-10-17 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 bfcdeb05b7ed93..03f6cbceb182a9 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-10-16 +date: 2023-10-17 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 d765ae037a24cc..e93465d920b962 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-10-16 +date: 2023-10-17 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 9adeafc1b3df80..00eb220d3e6f5f 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-10-16 +date: 2023-10-17 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 383662d55ee1bc..a377d6146b0388 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-10-16 +date: 2023-10-17 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 38e0a194e0dd28..679fac32be272e 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-10-16 +date: 2023-10-17 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 65cb08e371ae0c..8289bff3f047d9 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-10-16 +date: 2023-10-17 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 72b398912435fc..db521752afb3e1 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-10-16 +date: 2023-10-17 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 bc587b109e7b4e..b2a95944145373 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-10-16 +date: 2023-10-17 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 925720699807f0..82d819de0bbbd9 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-10-16 +date: 2023-10-17 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 c94d6e4eb594db..161312d725bc05 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-10-16 +date: 2023-10-17 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 141bf74361b65b..ff10f9ce450d31 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-10-16 +date: 2023-10-17 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 56b8cd19d8d7b8..9c6b8a5cfbdbd2 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-10-16 +date: 2023-10-17 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 cf7f286ec0de36..8ce19c2badec48 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-10-16 +date: 2023-10-17 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 b5f4b8e13a15a5..e72e78edc2bffa 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-10-16 +date: 2023-10-17 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 83015c42eda2f9..a83806f0da4d59 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-10-16 +date: 2023-10-17 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 f811ba6dc4cf96..3694965ad35bab 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-10-16 +date: 2023-10-17 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 71580bb416f3db..9e6872b77b9bda 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; diff --git a/api_docs/kbn_openapi_generator.mdx b/api_docs/kbn_openapi_generator.mdx index af4684ea2aba95..adb1d9df859cb4 100644 --- a/api_docs/kbn_openapi_generator.mdx +++ b/api_docs/kbn_openapi_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-generator title: "@kbn/openapi-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-generator plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-generator'] --- import kbnOpenapiGeneratorObj from './kbn_openapi_generator.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 3150479d50f884..16c7c62b140f65 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-10-16 +date: 2023-10-17 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 5546bd4f437c32..50f92353f385d9 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-10-16 +date: 2023-10-17 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 e3537851375aa2..34d61d993372e5 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-10-16 +date: 2023-10-17 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 17266efbd3e0c5..621b9bc05229e3 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-10-16 +date: 2023-10-17 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 8f579953f5b533..27f9fdd17416e4 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-10-16 +date: 2023-10-17 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 b9401a58144db6..9409382c8f1699 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index 0fa343fd0a65a6..135e886dc76032 100644 --- a/api_docs/kbn_profiling_utils.mdx +++ b/api_docs/kbn_profiling_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-profiling-utils title: "@kbn/profiling-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/profiling-utils plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/profiling-utils'] --- import kbnProfilingUtilsObj from './kbn_profiling_utils.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index 8c87dcf8327159..ef6b5637e8be10 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-10-16 +date: 2023-10-17 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 8832f38d83bbfd..5d2455c7bba87b 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-10-16 +date: 2023-10-17 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 9b0128ce234c72..03245f883d8df3 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-10-16 +date: 2023-10-17 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 2b1f6689d6709f..62c70b80a207b8 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-10-16 +date: 2023-10-17 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 150f1025d8763f..64506e753ceac3 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-10-16 +date: 2023-10-17 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 d22f5e8549c562..e3bbe44bc18b6c 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-10-16 +date: 2023-10-17 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 b374838bc39043..7e3fa558c9c2b1 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-10-16 +date: 2023-10-17 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 80485e49b36abe..ad9cd22db6fc8b 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-10-16 +date: 2023-10-17 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 8ea326bc9670e4..c2c863ac898a3d 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-10-16 +date: 2023-10-17 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 4c9ce0b27c3ddb..1c83c5a7e7495c 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-10-16 +date: 2023-10-17 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 44d0b7936edb73..ef76acadbcecac 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-10-16 +date: 2023-10-17 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 0dd06b97f2bee4..bcdb0b1bf55a3c 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-10-16 +date: 2023-10-17 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 ef80718eb7871a..f29edb9bf49ef1 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_resizable_layout.mdx b/api_docs/kbn_resizable_layout.mdx index b8441bd2c41946..556bbb8ca4c141 100644 --- a/api_docs/kbn_resizable_layout.mdx +++ b/api_docs/kbn_resizable_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-resizable-layout title: "@kbn/resizable-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/resizable-layout plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/resizable-layout'] --- import kbnResizableLayoutObj from './kbn_resizable_layout.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index 0e6606ec9e729f..f1c2c6a3cb803f 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-10-16 +date: 2023-10-17 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 45adea99a728d4..f743a6c7a333aa 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-10-16 +date: 2023-10-17 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 b76ebbc599505a..4c5c244cbaef4f 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-10-16 +date: 2023-10-17 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 ce5fa17716c8aa..290cfe4a3d9d2c 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-10-16 +date: 2023-10-17 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.mdx b/api_docs/kbn_search_api_panels.mdx index c9deefd5d50d0d..7d0b1f461c57a0 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; diff --git a/api_docs/kbn_search_connectors.devdocs.json b/api_docs/kbn_search_connectors.devdocs.json index d3794619ffb6b4..df053f0d16c45d 100644 --- a/api_docs/kbn_search_connectors.devdocs.json +++ b/api_docs/kbn_search_connectors.devdocs.json @@ -12059,6 +12059,600 @@ } ] }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync", + "type": "Object", + "tags": [], + "label": "use_domain_wide_delegation_for_sync", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.default_value", + "type": "Uncategorized", + "tags": [], + "label": "default_value", + "description": [], + "signature": [ + "null" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.depends_on", + "type": "Array", + "tags": [], + "label": "depends_on", + "description": [], + "signature": [ + "never[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.display", + "type": "string", + "tags": [], + "label": "display", + "description": [], + "signature": [ + { + "pluginId": "@kbn/search-connectors", + "scope": "common", + "docId": "kibKbnSearchConnectorsPluginApi", + "section": "def-common.DisplayType", + "text": "DisplayType" + }, + ".TOGGLE" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.label", + "type": "string", + "tags": [], + "label": "label", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.options", + "type": "Array", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "never[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.order", + "type": "number", + "tags": [], + "label": "order", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.required", + "type": "boolean", + "tags": [], + "label": "required", + "description": [], + "signature": [ + "true" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.sensitive", + "type": "boolean", + "tags": [], + "label": "sensitive", + "description": [], + "signature": [ + "false" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.tooltip", + "type": "string", + "tags": [], + "label": "tooltip", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + { + "pluginId": "@kbn/search-connectors", + "scope": "common", + "docId": "kibKbnSearchConnectorsPluginApi", + "section": "def-common.FieldType", + "text": "FieldType" + }, + ".BOOLEAN" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.ui_restrictions", + "type": "Array", + "tags": [], + "label": "ui_restrictions", + "description": [], + "signature": [ + "never[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.validations", + "type": "Array", + "tags": [], + "label": "validations", + "description": [], + "signature": [ + "never[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_domain_wide_delegation_for_sync.value", + "type": "boolean", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "false" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync", + "type": "Object", + "tags": [], + "label": "google_workspace_admin_email_for_data_sync", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.default_value", + "type": "Uncategorized", + "tags": [], + "label": "default_value", + "description": [], + "signature": [ + "null" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.depends_on", + "type": "Array", + "tags": [], + "label": "depends_on", + "description": [], + "signature": [ + "{ field: string; value: true; }[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.display", + "type": "string", + "tags": [], + "label": "display", + "description": [], + "signature": [ + { + "pluginId": "@kbn/search-connectors", + "scope": "common", + "docId": "kibKbnSearchConnectorsPluginApi", + "section": "def-common.DisplayType", + "text": "DisplayType" + }, + ".TEXTBOX" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.label", + "type": "string", + "tags": [], + "label": "label", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.options", + "type": "Array", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "never[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.order", + "type": "number", + "tags": [], + "label": "order", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.required", + "type": "boolean", + "tags": [], + "label": "required", + "description": [], + "signature": [ + "true" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.sensitive", + "type": "boolean", + "tags": [], + "label": "sensitive", + "description": [], + "signature": [ + "false" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.tooltip", + "type": "string", + "tags": [], + "label": "tooltip", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + { + "pluginId": "@kbn/search-connectors", + "scope": "common", + "docId": "kibKbnSearchConnectorsPluginApi", + "section": "def-common.FieldType", + "text": "FieldType" + }, + ".STRING" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.ui_restrictions", + "type": "Array", + "tags": [], + "label": "ui_restrictions", + "description": [], + "signature": [ + "never[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.validations", + "type": "Array", + "tags": [], + "label": "validations", + "description": [], + "signature": [ + "{ type: string; constraint: string; }[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_admin_email_for_data_sync.value", + "type": "string", + "tags": [], + "label": "value", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync", + "type": "Object", + "tags": [], + "label": "google_workspace_email_for_shared_drives_sync", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.default_value", + "type": "Uncategorized", + "tags": [], + "label": "default_value", + "description": [], + "signature": [ + "null" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.depends_on", + "type": "Array", + "tags": [], + "label": "depends_on", + "description": [], + "signature": [ + "{ field: string; value: true; }[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.display", + "type": "string", + "tags": [], + "label": "display", + "description": [], + "signature": [ + { + "pluginId": "@kbn/search-connectors", + "scope": "common", + "docId": "kibKbnSearchConnectorsPluginApi", + "section": "def-common.DisplayType", + "text": "DisplayType" + }, + ".TEXTBOX" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.label", + "type": "string", + "tags": [], + "label": "label", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.options", + "type": "Array", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "never[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.order", + "type": "number", + "tags": [], + "label": "order", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.required", + "type": "boolean", + "tags": [], + "label": "required", + "description": [], + "signature": [ + "true" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.sensitive", + "type": "boolean", + "tags": [], + "label": "sensitive", + "description": [], + "signature": [ + "false" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.tooltip", + "type": "string", + "tags": [], + "label": "tooltip", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + { + "pluginId": "@kbn/search-connectors", + "scope": "common", + "docId": "kibKbnSearchConnectorsPluginApi", + "section": "def-common.FieldType", + "text": "FieldType" + }, + ".STRING" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.ui_restrictions", + "type": "Array", + "tags": [], + "label": "ui_restrictions", + "description": [], + "signature": [ + "never[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.validations", + "type": "Array", + "tags": [], + "label": "validations", + "description": [], + "signature": [ + "{ type: string; constraint: string; }[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.google_workspace_email_for_shared_drives_sync.value", + "type": "string", + "tags": [], + "label": "value", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, { "parentPluginId": "@kbn/search-connectors", "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.google_drive.configuration.use_document_level_security", @@ -12292,7 +12886,7 @@ "label": "depends_on", "description": [], "signature": [ - "{ field: string; value: true; }[]" + "({ field: string; value: true; } | { field: string; value: false; })[]" ], "path": "packages/kbn-search-connectors/types/native_connectors.ts", "deprecated": false, diff --git a/api_docs/kbn_search_connectors.mdx b/api_docs/kbn_search_connectors.mdx index c29e668a03e59c..2d754ac3a65c39 100644 --- a/api_docs/kbn_search_connectors.mdx +++ b/api_docs/kbn_search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-connectors title: "@kbn/search-connectors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-connectors plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.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 | |-------------------|-----------|------------------------|-----------------| -| 2055 | 0 | 2055 | 0 | +| 2097 | 0 | 2097 | 0 | ## Common diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index c83de04173b533..c23e1ec58533fe 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-10-16 +date: 2023-10-17 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_features.mdx b/api_docs/kbn_security_solution_features.mdx index b317970f87c486..c3a5bd57d8f47b 100644 --- a/api_docs/kbn_security_solution_features.mdx +++ b/api_docs/kbn_security_solution_features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-features title: "@kbn/security-solution-features" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-features plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-features'] --- import kbnSecuritySolutionFeaturesObj from './kbn_security_solution_features.devdocs.json'; diff --git a/api_docs/kbn_security_solution_navigation.mdx b/api_docs/kbn_security_solution_navigation.mdx index 27f3fc9ff5baf3..691f1ba65ec66c 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-10-16 +date: 2023-10-17 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 dd24c3c7a09b39..588ca64dfff181 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-10-16 +date: 2023-10-17 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 c2ab04c62040b2..adfc46027aa27f 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-10-16 +date: 2023-10-17 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 b707d92fd17085..76ee327c99b686 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-10-16 +date: 2023-10-17 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 38cf816615b2f8..dbb193fe468de6 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-10-16 +date: 2023-10-17 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 013739f3d94945..76a6fe0f6f57f1 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-10-16 +date: 2023-10-17 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 e4793e91256dec..7d0fe4828ba419 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-10-16 +date: 2023-10-17 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 c080a8833a74c7..d06c75f34eb459 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-10-16 +date: 2023-10-17 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 84c5b47985927a..df4bcaa7c63588 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-10-16 +date: 2023-10-17 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 903b28c9e28522..5c7065c3f06526 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-10-16 +date: 2023-10-17 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 82afa8f7416382..17034c5f9cb7d0 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-10-16 +date: 2023-10-17 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 a614bbe812052a..9f7126511b9b68 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-10-16 +date: 2023-10-17 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 800df376102df8..d65f324dc265a4 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-10-16 +date: 2023-10-17 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 f3ef52dcde56a5..1812401ae1cb08 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-10-16 +date: 2023-10-17 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 e8f419ff4e5208..9dd34102854b43 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-10-16 +date: 2023-10-17 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 3679b2ca915a3a..22a1f04ea67325 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-10-16 +date: 2023-10-17 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 4235a819e1ead7..f8e7c545d0509e 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-10-16 +date: 2023-10-17 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 32cdf149ff10fe..a6fde3d181fc04 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-10-16 +date: 2023-10-17 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 ad2dbb9c32a105..5b6422e02ce861 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-10-16 +date: 2023-10-17 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 6a1f1c78ef1a4d..b91036b3309ef4 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-10-16 +date: 2023-10-17 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 5ae786dab9d93c..dceae2c956a1fc 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-10-16 +date: 2023-10-17 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 80efe6a0b8dcbc..f0200a83cd4bc4 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-10-16 +date: 2023-10-17 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 e9e3da4b0a2a7d..5d3f4fe785c9c6 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-10-16 +date: 2023-10-17 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_common_settings.mdx b/api_docs/kbn_serverless_common_settings.mdx index 6ff2c6b8e70dc0..84b45e474c565a 100644 --- a/api_docs/kbn_serverless_common_settings.mdx +++ b/api_docs/kbn_serverless_common_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-common-settings title: "@kbn/serverless-common-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-common-settings plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-common-settings'] --- import kbnServerlessCommonSettingsObj from './kbn_serverless_common_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_observability_settings.mdx b/api_docs/kbn_serverless_observability_settings.mdx index dba5546cd143a3..f38b714bd8ec2c 100644 --- a/api_docs/kbn_serverless_observability_settings.mdx +++ b/api_docs/kbn_serverless_observability_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-observability-settings title: "@kbn/serverless-observability-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-observability-settings plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-observability-settings'] --- import kbnServerlessObservabilitySettingsObj from './kbn_serverless_observability_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_project_switcher.mdx b/api_docs/kbn_serverless_project_switcher.mdx index 150400daa080f1..bc06e82df30a74 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-10-16 +date: 2023-10-17 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_search_settings.mdx b/api_docs/kbn_serverless_search_settings.mdx index 7b5454756ffacf..a3dff22f7988bc 100644 --- a/api_docs/kbn_serverless_search_settings.mdx +++ b/api_docs/kbn_serverless_search_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-search-settings title: "@kbn/serverless-search-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-search-settings plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-search-settings'] --- import kbnServerlessSearchSettingsObj from './kbn_serverless_search_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_security_settings.mdx b/api_docs/kbn_serverless_security_settings.mdx index 1674057e6f59c7..6e2eae9c6cadc3 100644 --- a/api_docs/kbn_serverless_security_settings.mdx +++ b/api_docs/kbn_serverless_security_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-security-settings title: "@kbn/serverless-security-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-security-settings plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-security-settings'] --- import kbnServerlessSecuritySettingsObj from './kbn_serverless_security_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_storybook_config.mdx b/api_docs/kbn_serverless_storybook_config.mdx index 8b9b9890a1932d..1717d3a5400318 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-10-16 +date: 2023-10-17 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 d1300665f7451d..2bd4dd85d9954d 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-10-16 +date: 2023-10-17 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 00a8e186be153a..b64eccc7c315fe 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-10-16 +date: 2023-10-17 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 8eba286136149c..ecde095896f1ff 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-10-16 +date: 2023-10-17 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 0e170b965b7fdc..30a31ed84ce1a6 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-10-16 +date: 2023-10-17 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 2121eee66e97ac..07e325309bfe9c 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-10-16 +date: 2023-10-17 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 dfb6e2e88dd85c..a82f82657435a6 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-10-16 +date: 2023-10-17 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.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 979a2cd8146f4a..44d38d6db1852a 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-10-16 +date: 2023-10-17 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.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 2af0319da959d9..ead25f95a88c76 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-10-16 +date: 2023-10-17 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 cd009b6f6eca29..3ac3a5e2d7c0bd 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-10-16 +date: 2023-10-17 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 26ecb85858f244..f642bcc0f9c5e4 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-10-16 +date: 2023-10-17 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 fcd5f95f0e9a59..c8114f2050fac0 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-10-16 +date: 2023-10-17 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 e047f0799ed08c..c42e9e64f4a35b 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-10-16 +date: 2023-10-17 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 7a2e1eae8a40bd..6581fdff9a1682 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-10-16 +date: 2023-10-17 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 f9e2608025996c..acf32839a22092 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-10-16 +date: 2023-10-17 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 a52870876556b7..b071e2b160fb24 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-10-16 +date: 2023-10-17 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 ad2daa13431d38..e039e5689a9a6b 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-10-16 +date: 2023-10-17 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 224150b0a51194..da0d2597221699 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-10-16 +date: 2023-10-17 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 0938f59fee4f5c..4d4ece316f2db0 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-10-16 +date: 2023-10-17 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 03b1c582a6e64f..50622d414b2133 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-10-16 +date: 2023-10-17 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 9aa91943236f6c..791ec1a5912f5f 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-10-16 +date: 2023-10-17 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 8937ad127cd479..50243ceda1a692 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-10-16 +date: 2023-10-17 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.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index d41a4d0fc784d0..7cafff329d8b4b 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-10-16 +date: 2023-10-17 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 360b75d1d8606f..9c14e596038514 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-10-16 +date: 2023-10-17 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 08e0ca879e7f63..312e486e73de77 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-10-16 +date: 2023-10-17 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 8d73687c2ed3c8..a4f249b88185bd 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-10-16 +date: 2023-10-17 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 a1e1311c3e5002..d41b2264c5e67d 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-10-16 +date: 2023-10-17 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 3f1e9f778c09d1..77a323a3acae0e 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-10-16 +date: 2023-10-17 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.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index c2d546e8230a7c..a03749c4d291a2 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-10-16 +date: 2023-10-17 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 4e1e05ee791c50..a1cb9bd43c550d 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-10-16 +date: 2023-10-17 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 8ee06145f1d048..66bafb7b368666 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-10-16 +date: 2023-10-17 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 5a45bc096d8300..12c573676072c3 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-10-16 +date: 2023-10-17 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 c2182f953ee404..acb6fed5da0b72 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-10-16 +date: 2023-10-17 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 3d871b66d786d6..ad7e3f154d5252 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-10-16 +date: 2023-10-17 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 4cfb2459eae972..1a31f4c29b68c5 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-10-16 +date: 2023-10-17 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 8e678811ddc6b4..8be35ce8e8d360 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-10-16 +date: 2023-10-17 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 db5d96c35d8129..6805131f657fce 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-10-16 +date: 2023-10-17 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 aca92e2d3fc5ec..96f78ab04d97c7 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-10-16 +date: 2023-10-17 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 1bdba74a6d099b..321893a4c6f4a9 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-10-16 +date: 2023-10-17 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 60b62b0882530b..e4d9b70139befe 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-10-16 +date: 2023-10-17 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 8c6ceeca637acb..5de8387bb91808 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-10-16 +date: 2023-10-17 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.mdx b/api_docs/kbn_slo_schema.mdx index 7c55b3b00cff54..e33b5fc5d55e96 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 8afa04770e852d..601f701aba6def 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-10-16 +date: 2023-10-17 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 16b9ace49d06af..360f59651ac4e2 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-10-16 +date: 2023-10-17 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 abf6976ec1fb43..f80241b8a7b1b6 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-10-16 +date: 2023-10-17 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 e4820e28b7f81f..60534bcecd03c5 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_subscription_tracking.mdx b/api_docs/kbn_subscription_tracking.mdx index 7caeb5d887b6b5..b22526243451f0 100644 --- a/api_docs/kbn_subscription_tracking.mdx +++ b/api_docs/kbn_subscription_tracking.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-subscription-tracking title: "@kbn/subscription-tracking" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/subscription-tracking plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/subscription-tracking'] --- import kbnSubscriptionTrackingObj from './kbn_subscription_tracking.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 0bebffeee58983..e72a754c578681 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-10-16 +date: 2023-10-17 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 2dcc16b166adbd..763603520c30ab 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-10-16 +date: 2023-10-17 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 2765cc3eb58769..6a4bb94b31940a 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-10-16 +date: 2023-10-17 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 f16e5f0b127b5c..b305e38ed3e9ff 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-10-16 +date: 2023-10-17 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 017269ec0c4000..998985e2fe1e18 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-10-16 +date: 2023-10-17 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 6db1b043000a6b..e498dc4f106da0 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-10-16 +date: 2023-10-17 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 f1d03e539483a3..982d3770d95189 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-10-16 +date: 2023-10-17 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 48205c9dfaa3d9..3deb9c6c6f737c 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-10-16 +date: 2023-10-17 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 7137e70b6686d5..1a5640c3cf5a24 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-10-16 +date: 2023-10-17 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 b2f2efb61d86c0..84387ccfad6ca6 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-10-16 +date: 2023-10-17 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 59860a71c14aa6..d2ae1c8cbd95e6 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_unified_data_table.mdx b/api_docs/kbn_unified_data_table.mdx index 832ddeaf2a6fa7..d339227876a37d 100644 --- a/api_docs/kbn_unified_data_table.mdx +++ b/api_docs/kbn_unified_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-data-table title: "@kbn/unified-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-data-table plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-data-table'] --- import kbnUnifiedDataTableObj from './kbn_unified_data_table.devdocs.json'; diff --git a/api_docs/kbn_unified_doc_viewer.mdx b/api_docs/kbn_unified_doc_viewer.mdx index 2f2581c5cea4e6..8d9953d71987b1 100644 --- a/api_docs/kbn_unified_doc_viewer.mdx +++ b/api_docs/kbn_unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-doc-viewer title: "@kbn/unified-doc-viewer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-doc-viewer plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-doc-viewer'] --- import kbnUnifiedDocViewerObj from './kbn_unified_doc_viewer.devdocs.json'; diff --git a/api_docs/kbn_unified_field_list.mdx b/api_docs/kbn_unified_field_list.mdx index 410850819f55d1..0f353e7b39a1f1 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-10-16 +date: 2023-10-17 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 378d32050c3b83..7ee704edbc2a92 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-10-16 +date: 2023-10-17 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 6580390847c6a4..113aa81acd6853 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-10-16 +date: 2023-10-17 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 c8b595f919cf55..6f321aa90f9cbb 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-10-16 +date: 2023-10-17 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 492bd4a1bbff41..d394b4e205e93a 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-10-16 +date: 2023-10-17 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 b70692732b0b76..078bc8f8713431 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-10-16 +date: 2023-10-17 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 588836952d9b05..6a758510c95493 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-10-16 +date: 2023-10-17 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 c3f62b82736852..a5797f2ebbb34e 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; diff --git a/api_docs/kbn_xstate_utils.mdx b/api_docs/kbn_xstate_utils.mdx index 913cc5dc344bfa..39f61d949e2a3f 100644 --- a/api_docs/kbn_xstate_utils.mdx +++ b/api_docs/kbn_xstate_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-xstate-utils title: "@kbn/xstate-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/xstate-utils plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/xstate-utils'] --- import kbnXstateUtilsObj from './kbn_xstate_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index ebab782f217631..0b4c4b9c7abc4e 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-10-16 +date: 2023-10-17 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 42e9599208fb3a..990bb033de9fa2 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-10-16 +date: 2023-10-17 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 2c299a0123cee0..9f9f1f16ad3076 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-10-16 +date: 2023-10-17 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 34a08132e55db9..d4c39c3ce8559f 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-10-16 +date: 2023-10-17 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 afc9df50adc616..5e212795a610ed 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-10-16 +date: 2023-10-17 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 3fe37589216138..e6e13076d33d93 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-10-16 +date: 2023-10-17 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 8a8fde05d9447a..f9c93353a4bdaf 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-10-16 +date: 2023-10-17 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 cd653dd2b06ce1..85a8d00409ba3f 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-10-16 +date: 2023-10-17 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 ce999af1257e32..bcb050aa867b77 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/links.mdx b/api_docs/links.mdx index ef09c70daf91fd..d77ce47daed1d2 100644 --- a/api_docs/links.mdx +++ b/api_docs/links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/links title: "links" image: https://source.unsplash.com/400x175/?github description: API docs for the links plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'links'] --- import linksObj from './links.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 6881a7ae955b9e..5ecf86ee60aa6f 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/log_explorer.mdx b/api_docs/log_explorer.mdx index 7b9e288b9ff4eb..9d6d41599a2cc1 100644 --- a/api_docs/log_explorer.mdx +++ b/api_docs/log_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logExplorer title: "logExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the logExplorer plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logExplorer'] --- import logExplorerObj from './log_explorer.devdocs.json'; diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index aa966cd9646a26..36bdcdaa4fbce1 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-10-16 +date: 2023-10-17 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 5f754be8c6ed2b..1822e5225afbd2 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-10-16 +date: 2023-10-17 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 7d7a6a32daf8b8..2f4bccc5d60514 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-10-16 +date: 2023-10-17 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 1ba3cddb08725a..1b36ada3381a76 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/metrics_data_access.mdx b/api_docs/metrics_data_access.mdx index 89d00c51a18858..7842beec9380a4 100644 --- a/api_docs/metrics_data_access.mdx +++ b/api_docs/metrics_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/metricsDataAccess title: "metricsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the metricsDataAccess plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'metricsDataAccess'] --- import metricsDataAccessObj from './metrics_data_access.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 19cf9911f55295..b7909b87244076 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-10-16 +date: 2023-10-17 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 aa7e341e2dd65e..84de0f543d4c0b 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-10-16 +date: 2023-10-17 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 dc1006154e1cdc..36021747f1c4fa 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-10-16 +date: 2023-10-17 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 975a31aa6bf572..a29a276eaedf0d 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-10-16 +date: 2023-10-17 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 f49a4e303c9b0b..50862e5d7898db 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/no_data_page.mdx b/api_docs/no_data_page.mdx index 8cab97fae2de9f..42f3c067fdb432 100644 --- a/api_docs/no_data_page.mdx +++ b/api_docs/no_data_page.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/noDataPage title: "noDataPage" image: https://source.unsplash.com/400x175/?github description: API docs for the noDataPage plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'noDataPage'] --- import noDataPageObj from './no_data_page.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index 389082dbe11f2c..2375ef39afb21b 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index f5f24e8c029d1c..1f2dd6d4355111 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index 3926ac4e46d74c..2961a6a81c6cee 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; diff --git a/api_docs/observability_log_explorer.mdx b/api_docs/observability_log_explorer.mdx index 3d917e80882cf5..c54d8e6f367c76 100644 --- a/api_docs/observability_log_explorer.mdx +++ b/api_docs/observability_log_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityLogExplorer title: "observabilityLogExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityLogExplorer plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityLogExplorer'] --- import observabilityLogExplorerObj from './observability_log_explorer.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index e997751f0599c9..62bb7c343f76b0 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-10-16 +date: 2023-10-17 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 eb419ba5e0955f..1f3ea1fdcdef8a 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-10-16 +date: 2023-10-17 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 2ca20438e709f6..d2e98c6f29bc8e 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/painless_lab.mdx b/api_docs/painless_lab.mdx index b164e6242aebf1..afffae5c91e520 100644 --- a/api_docs/painless_lab.mdx +++ b/api_docs/painless_lab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/painlessLab title: "painlessLab" image: https://source.unsplash.com/400x175/?github description: API docs for the painlessLab plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'painlessLab'] --- import painlessLabObj from './painless_lab.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 1613387955af94..ff30adf2672fc1 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,13 +15,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 699 | 590 | 40 | +| 700 | 590 | 40 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 75818 | 223 | 64609 | 1580 | +| 75848 | 223 | 64648 | 1583 | ## Plugin Directory @@ -56,11 +56,11 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | Add custom data integrations so they can be displayed in the Fleet integrations app | 268 | 0 | 249 | 1 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds the Dashboard app to Kibana | 109 | 0 | 106 | 11 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | - | 54 | 0 | 51 | 0 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3290 | 33 | 2554 | 24 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3282 | 33 | 2549 | 24 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin provides the ability to create data views via a modal flyout inside Kibana apps | 35 | 0 | 25 | 5 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Reusable data view field editor across Kibana | 72 | 0 | 33 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Data view management app | 2 | 0 | 2 | 0 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 1048 | 0 | 262 | 2 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 1038 | 0 | 258 | 3 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | The Data Visualizer tools help you understand your data, by analyzing the metrics and fields in a log file or an existing Elasticsearch index. | 31 | 3 | 25 | 1 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 12 | 0 | 10 | 3 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 118 | 0 | 76 | 18 | @@ -95,7 +95,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 59 | 0 | 59 | 2 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 239 | 0 | 24 | 9 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Simple UI for managing files in Kibana | 2 | 0 | 2 | 0 | -| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1202 | 3 | 1084 | 42 | +| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1208 | 3 | 1090 | 43 | | ftrApis | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 0 | 0 | 0 | 0 | @@ -370,7 +370,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 25 | 1 | 24 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 111 | 1 | 0 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 352 | 1 | 5 | 1 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 352 | 1 | 5 | 2 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 11 | 0 | 11 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 89 | 0 | 61 | 10 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 0 | @@ -545,7 +545,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/security-detections-response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 114 | 0 | 111 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 0 | | | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 68 | 0 | 68 | 0 | -| | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 2055 | 0 | 2055 | 0 | +| | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 2097 | 0 | 2097 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 15 | 0 | 8 | 0 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 14 | 0 | 14 | 6 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 50 | 0 | 47 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 64b61e650320b7..cc37678a7e8c4d 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-10-16 +date: 2023-10-17 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 49ef172f1f527a..afd424fe7a360e 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/profiling_data_access.mdx b/api_docs/profiling_data_access.mdx index b55451cf67c0dd..5a747bb6dbd242 100644 --- a/api_docs/profiling_data_access.mdx +++ b/api_docs/profiling_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profilingDataAccess title: "profilingDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the profilingDataAccess plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profilingDataAccess'] --- import profilingDataAccessObj from './profiling_data_access.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 47ce0a2808b343..5dda7460e7b386 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-10-16 +date: 2023-10-17 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 14df5b204a9276..d41d3a8d59c9c8 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-10-16 +date: 2023-10-17 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 d664aca7987146..b7bcb9ec392bd2 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-10-16 +date: 2023-10-17 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 3ab31e7ef3ea25..c18803a2717b51 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-10-16 +date: 2023-10-17 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 2101eda6d9480a..c1277008f8005b 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-10-16 +date: 2023-10-17 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 c14ffe2f7c17f7..80d8aaedfb67c0 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-10-16 +date: 2023-10-17 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 f8abfca5e955fd..da82bb6d1b2f7d 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-10-16 +date: 2023-10-17 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 d792d02267680d..7191dcb6890cc7 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-10-16 +date: 2023-10-17 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 ccfc01ac2e9ee3..36fcc83f230761 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-10-16 +date: 2023-10-17 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 ca6f71777c8f39..31ee8d4fe7f0aa 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-10-16 +date: 2023-10-17 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 db48333d091c20..7a89810328e824 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-10-16 +date: 2023-10-17 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 1625a84df3879c..500a8534117a1d 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-10-16 +date: 2023-10-17 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 48d931e6d11add..683f642a63c8c8 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-10-16 +date: 2023-10-17 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 2af9c231e2c08e..e0914d3a0f5455 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index e7b6d6df1f9154..fa6840750f7acd 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-10-16 +date: 2023-10-17 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 126c8ef55ffc45..65204810bf06bf 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-10-16 +date: 2023-10-17 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 f4066d17158ff2..f18f68ddcd89bd 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-10-16 +date: 2023-10-17 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 3f09a79c9faf2e..9e8e39c4eff2f9 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-10-16 +date: 2023-10-17 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 bd5ff97e3c05a5..4ba9d4516947e8 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-10-16 +date: 2023-10-17 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 297b3e7f5b66b1..1c6243dd3e5e4c 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-10-16 +date: 2023-10-17 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 c80f4051d63dc9..2ec3157b94ac0e 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-10-16 +date: 2023-10-17 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 3c574f9e5cc8dd..a31883bcb18407 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-10-16 +date: 2023-10-17 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 f1814cd3db16e7..32c52eaa951b1a 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-10-16 +date: 2023-10-17 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 6d49c3dc8cf269..02ff50607c6192 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-10-16 +date: 2023-10-17 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 aa52f3adb92513..6ce70ad9b22667 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-10-16 +date: 2023-10-17 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 e6e012bc303c32..33ef37c292981f 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-10-16 +date: 2023-10-17 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 583dc1f3bbafab..fb4f7a55f8546e 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-10-16 +date: 2023-10-17 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 68f30ab93bd148..be86cc25eaee98 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-10-16 +date: 2023-10-17 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 44a7c1a7b546aa..2f08803e9e8b20 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-10-16 +date: 2023-10-17 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 e047837c56f300..47b3e7b690e4db 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-10-16 +date: 2023-10-17 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 62aa0983059186..052f6706031c6e 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-10-16 +date: 2023-10-17 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 19594771354739..1cceb7aff2261f 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-10-16 +date: 2023-10-17 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 f8ba2f16d44729..6f2fbdf049fa11 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 1dc96a8076c3d3..b6402e947711f0 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-10-16 +date: 2023-10-17 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 19d4cb756be164..5047c0facd21eb 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-10-16 +date: 2023-10-17 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 032e3fd4c5526e..a77aafebb5afd9 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.devdocs.json b/api_docs/ui_actions.devdocs.json index fc3e6efa4a21ac..8aa60c3c65f779 100644 --- a/api_docs/ui_actions.devdocs.json +++ b/api_docs/ui_actions.devdocs.json @@ -2218,7 +2218,7 @@ "section": "def-common.FieldAttrs", "text": "FieldAttrs" }, - " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; allowHidden?: boolean | undefined; }" + " | undefined; allowNoIndex?: boolean | undefined; namespaces?: string[] | undefined; name?: string | undefined; }" ], "path": "src/plugins/ui_actions/public/types.ts", "deprecated": false, diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index bf645816335656..158859e2154f3c 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-10-16 +date: 2023-10-17 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 772f905e905bad..3a22305dcc1336 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_doc_viewer.mdx b/api_docs/unified_doc_viewer.mdx index 09fe37b3923ac4..7279ef7969fb78 100644 --- a/api_docs/unified_doc_viewer.mdx +++ b/api_docs/unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedDocViewer title: "unifiedDocViewer" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedDocViewer plugin -date: 2023-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedDocViewer'] --- import unifiedDocViewerObj from './unified_doc_viewer.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 6a4073cad1f839..4f2ff48629358a 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-10-16 +date: 2023-10-17 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 401f3cbb670c16..716bf96728f177 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-10-16 +date: 2023-10-17 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 418502b01cad23..20aa367104dcf7 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-10-16 +date: 2023-10-17 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 b4352f5c02b490..7ad6d527b374be 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-10-16 +date: 2023-10-17 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 50a8d551392054..4ba133a68689c1 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-10-16 +date: 2023-10-17 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 1862d1ca287a29..e0f179e68ff102 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-10-16 +date: 2023-10-17 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 0acd5ee1523acd..490dffba1e0c29 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-10-16 +date: 2023-10-17 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 b5d7d3d185133e..eedc2c019d23e0 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-10-16 +date: 2023-10-17 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 db83a50f144b5a..15ba59a5a12754 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-10-16 +date: 2023-10-17 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 b0894842171da8..ac23e0ff4e61e5 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-10-16 +date: 2023-10-17 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 28f2417335144e..83f111c2a11900 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-10-16 +date: 2023-10-17 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 d749bacb5e20a4..4c01c8841810ac 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-10-16 +date: 2023-10-17 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 e7f127d356736a..9a6a5f5a514a80 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-10-16 +date: 2023-10-17 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 f15f3821e55eff..e0a2872da856d3 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-10-16 +date: 2023-10-17 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 9c96f9228f57f7..377733d8656301 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-10-16 +date: 2023-10-17 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 439b9d9bb4cd32..926628184f4ef6 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-10-16 +date: 2023-10-17 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 7b2003557f7518..fb9e61c42d1617 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-10-16 +date: 2023-10-17 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 a5283e3b76411c..8f0df503aa367b 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-10-16 +date: 2023-10-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 36fcdc72da5443b7a5c31f634b36e8d66b09b69f Mon Sep 17 00:00:00 2001 From: Candace Park <56409205+parkiino@users.noreply.github.com> Date: Tue, 17 Oct 2023 02:01:33 -0400 Subject: [PATCH 34/87] [Security Solution][Admin][Policy] Show policy api list error rather than onboarding screen (#167838) ## Summary - [x] Fixes a bug where the policy list page would show the onboarding screen rather than an error screen if the policy list api failed - [x] Adds related unit test # Screenshot ![policylist3](https://github.com/elastic/kibana/assets/56409205/1d1d544a-bce1-4b1f-8d47-db38fa1d57fe) --- .../integration_tests/policy_list.test.tsx | 20 +++++++- .../pages/policy/view/policy_list.tsx | 46 ++++++++++++++----- 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/integration_tests/policy_list.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/integration_tests/policy_list.test.tsx index 369df34fdff4ac..ee520a98632bc9 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/integration_tests/policy_list.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/integration_tests/policy_list.test.tsx @@ -11,7 +11,7 @@ import type { AppContextTestRender } from '../../../../../common/mock/endpoint'; import { createAppRootMockRenderer } from '../../../../../common/mock/endpoint'; import { sendGetEndpointSpecificPackagePolicies } from '../../../../services/policies/policies'; import { sendGetEndpointSpecificPackagePoliciesMock } from '../../../../services/policies/test_mock_utils'; -import { PolicyList } from '../policy_list'; +import { PolicyList, policyListErrorMessage } from '../policy_list'; import type { GetPolicyListResponse } from '../../types'; import { getEndpointListPath, getPoliciesPath } from '../../../../common/routing'; import { APP_UI_ID } from '../../../../../../common/constants'; @@ -45,6 +45,22 @@ describe('When on the policy list page', () => { jest.clearAllMocks(); }); + describe('on get policy list api failure', () => { + beforeEach(async () => { + getPackagePolicies.mockRejectedValueOnce(new Error('mock list failure')); + render(); + }); + afterEach(() => { + getPackagePolicies.mockReset(); + }); + + it('should show table with error state', async () => { + expect(renderResult.getByTestId('policyListTable')).toBeTruthy(); + await waitFor(() => { + expect(renderResult.getByText(policyListErrorMessage)).toBeTruthy(); + }); + }); + }); describe('and there are no policies', () => { beforeEach(async () => { getPackagePolicies.mockResolvedValue( @@ -86,7 +102,7 @@ describe('When on the policy list page', () => { }); beforeEach(async () => { - getPackagePolicies.mockReturnValue(policies); + getPackagePolicies.mockResolvedValue(policies); render(); await waitFor(() => { expect(sendGetEndpointSpecificPackagePolicies).toHaveBeenCalled(); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx index 1a1a76ddcf1983..0cdbd1f0fa4401 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx @@ -46,6 +46,27 @@ import { useAppUrl, useToasts } from '../../../../common/lib/kibana'; import { PolicyEndpointCount } from './components/policy_endpoint_count'; import { ManagementEmptyStateWrapper } from '../../../components/management_empty_state_wrapper'; +export const policyListErrorMessage = i18n.translate( + 'xpack.securitySolution.policy.list.errorMessage', + { + defaultMessage: 'Error while retrieving list of policies', + } +); + +const policyListErrorToastTitle = i18n.translate( + 'xpack.securitySolution.policy.list.errorMessage.toast.title', + { + defaultMessage: 'Failed to retrieve policy list', + } +); + +const policyListErrorToastText = i18n.translate( + 'xpack.securitySolution.policyList.packageVersionError', + { + defaultMessage: 'Error retrieving the endpoint package version', + } +); + export const PolicyList = memo(() => { const { canReadEndpointList, loading: authLoading } = useUserPrivileges().endpointPrivileges; const isProtectionUpdatesEnabled = useIsExperimentalFeatureEnabled('protectionUpdatesEnabled'); @@ -63,6 +84,9 @@ export const PolicyList = memo(() => { } = useGetEndpointSpecificPolicies({ page: pagination.page, perPage: pagination.pageSize, + onError: (err) => { + toasts.addDanger({ title: policyListErrorToastTitle, text: err.message }); + }, }); const { data: outdatedManifestsCountResponse, isLoading: isOutdatedManifestsCountLoading } = @@ -73,17 +97,21 @@ export const PolicyList = memo(() => { useGetEndpointSecurityPackage({ customQueryOptions: { onError: (err) => { - toasts.addDanger( - i18n.translate('xpack.securitySolution.policyList.packageVersionError', { - defaultMessage: 'Error retrieving the endpoint package version', - }) - ); + toasts.addDanger({ + title: policyListErrorToastText, + text: err.message, + }); }, }, }); const totalItemCount = useMemo(() => data?.total ?? 0, [data]); + const shouldShowOnboarding = useMemo( + () => !policyIsFetching && totalItemCount === 0 && !error, + [policyIsFetching, totalItemCount, error] + ); + const policyListPath = useMemo(() => getPoliciesPath(search), [search]); const backLink: PolicyDetailsRouteState['backLink'] = useMemo(() => { @@ -365,14 +393,10 @@ export const PolicyList = memo(() => { }; }, [totalItemCount, pageSizeOptions, pagination.page, pagination.pageSize]); - const policyListErrorMessage = i18n.translate('xpack.securitySolution.policy.list.errorMessage', { - defaultMessage: 'Error while retrieving list of policies', - }); - return ( { 'Use policies to customize endpoint and cloud workload protections and other configurations', })} > - {totalItemCount > 0 ? ( + {!shouldShowOnboarding ? ( <> Date: Tue, 17 Oct 2023 07:36:07 +0000 Subject: [PATCH 35/87] =?UTF-8?q?[Security=20solution]=20Update=20serverle?= =?UTF-8?q?ss=20roles=20to=20include=20Data=20Views=20fea=E2=80=A6=20(#169?= =?UTF-8?q?036)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …ture permissions ## Summary Align roles with project-controller --- packages/kbn-es/src/serverless_resources/roles.yml | 2 ++ .../endpoint/common/roles_users/endpoint_operations_analyst.ts | 1 - .../roles_users/serverless/es_serverless_resources/roles.yml | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/kbn-es/src/serverless_resources/roles.yml b/packages/kbn-es/src/serverless_resources/roles.yml index bde917d2f97506..c631f596a8caca 100644 --- a/packages/kbn-es/src/serverless_resources/roles.yml +++ b/packages/kbn-es/src/serverless_resources/roles.yml @@ -387,6 +387,7 @@ soc_manager: - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all + - feature_indexPatterns.all # Detections Data Views resources: "*" detections_admin: @@ -471,6 +472,7 @@ platform_engineer: - feature_fleet.all - feature_fleetv2.all - feature_osquery.all + - feature_indexPatterns.all # Detections Data Views resources: "*" endpoint_operations_analyst: diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_operations_analyst.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_operations_analyst.ts index 3b6f3a5c90424b..6880282f838764 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_operations_analyst.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/endpoint_operations_analyst.ts @@ -36,7 +36,6 @@ export const getEndpointOperationsAnalyst: () => Omit = () => { }, { names: [ - 'names:', '.alerts-security*', '.siem-signals-*', '.preview.alerts-security*', diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml b/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml index d216adc602c1a7..ace64c7570aa23 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml @@ -390,6 +390,7 @@ soc_manager: - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all + - feature_indexPatterns.all # Detections Data Views resources: "*" detections_admin: @@ -474,6 +475,7 @@ platform_engineer: - feature_fleet.all - feature_fleetv2.all - feature_osquery.all + - feature_indexPatterns.all # Detections Data Views resources: "*" endpoint_operations_analyst: From 0c1f828084915704e9774ff936c19d31a8b321a2 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Tue, 17 Oct 2023 10:21:01 +0200 Subject: [PATCH 36/87] [SOM] use aggregation for type counts (#168918) ## Summary Use an aggregation for type counts in SO management instead of scrolling through all the documents. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../server/lib/get_saved_objects_counts.ts | 45 +++++++++++++++++++ .../server/lib/index.ts | 1 + .../server/routes/scroll_count.ts | 27 +++++------ .../saved_objects_management/tsconfig.json | 1 + 4 files changed, 57 insertions(+), 17 deletions(-) create mode 100644 src/plugins/saved_objects_management/server/lib/get_saved_objects_counts.ts diff --git a/src/plugins/saved_objects_management/server/lib/get_saved_objects_counts.ts b/src/plugins/saved_objects_management/server/lib/get_saved_objects_counts.ts new file mode 100644 index 00000000000000..266c79e99c0c49 --- /dev/null +++ b/src/plugins/saved_objects_management/server/lib/get_saved_objects_counts.ts @@ -0,0 +1,45 @@ +/* + * 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 { estypes } from '@elastic/elasticsearch'; +import type { SavedObjectsFindOptions } from '@kbn/core-saved-objects-api-server'; +import type { SavedObjectsClientContract } from '@kbn/core/server'; + +export const getSavedObjectCounts = async ({ + types, + options, + client, +}: { + types: string[]; + options: SavedObjectsFindOptions; + client: SavedObjectsClientContract; +}): Promise> => { + const body = await client.find({ + ...options, + type: types, + perPage: 0, + aggs: { + types: { + terms: { + field: 'type', + size: types.length, + }, + }, + }, + }); + + const buckets = + (body.aggregations?.types?.buckets as estypes.AggregationsStringTermsBucketKeys[]) || []; + + const counts = buckets.reduce((memo, bucket) => { + memo[bucket.key] = bucket.doc_count; + return memo; + }, {} as Record); + + return counts; +}; diff --git a/src/plugins/saved_objects_management/server/lib/index.ts b/src/plugins/saved_objects_management/server/lib/index.ts index 0038152891b7cf..0cd4768934daeb 100644 --- a/src/plugins/saved_objects_management/server/lib/index.ts +++ b/src/plugins/saved_objects_management/server/lib/index.ts @@ -9,3 +9,4 @@ export { toSavedObjectWithMeta } from './to_saved_object_with_meta'; export { injectMetaAttributes } from './inject_meta_attributes'; export { findRelationships } from './find_relationships'; +export { getSavedObjectCounts } from './get_saved_objects_counts'; diff --git a/src/plugins/saved_objects_management/server/routes/scroll_count.ts b/src/plugins/saved_objects_management/server/routes/scroll_count.ts index d5649572ccbedf..5ad90dae72c6a9 100644 --- a/src/plugins/saved_objects_management/server/routes/scroll_count.ts +++ b/src/plugins/saved_objects_management/server/routes/scroll_count.ts @@ -10,6 +10,7 @@ import { schema } from '@kbn/config-schema'; import type { IRouter, SavedObjectsCreatePointInTimeFinderOptions } from '@kbn/core/server'; import { chain } from 'lodash'; import type { v1 } from '../../common'; +import { getSavedObjectCounts } from '../lib'; export const registerScrollForCountRoute = (router: IRouter) => { router.post( @@ -44,27 +45,19 @@ export const registerScrollForCountRoute = (router: IRouter) => { const client = getClient({ includedHiddenTypes }); const findOptions: SavedObjectsCreatePointInTimeFinderOptions = { type: typesToInclude, - perPage: 500, + ...(searchString ? { search: `${searchString}*`, searchFields: ['title'] } : {}), + ...(references ? { hasReference: references, hasReferenceOperator: 'OR' } : {}), }; - if (searchString) { - findOptions.search = `${searchString}*`; - findOptions.searchFields = ['title']; - } - if (references) { - findOptions.hasReference = references; - findOptions.hasReferenceOperator = 'OR'; - } + + const rawCounts = await getSavedObjectCounts({ + types: typesToInclude, + client, + options: findOptions, + }); const counts: Record = {}; for (const type of typesToInclude) { - counts[type] = 0; - } - - const finder = client.createPointInTimeFinder(findOptions); - for await (const { saved_objects: savedObjects } of finder.find()) { - for (const { type } of savedObjects) { - counts[type]++; - } + counts[type] = rawCounts[type] ?? 0; } const body: v1.ScrollCountResponseHTTP = counts; diff --git a/src/plugins/saved_objects_management/tsconfig.json b/src/plugins/saved_objects_management/tsconfig.json index 4b832a1616a85c..72eb9c29b30c8e 100644 --- a/src/plugins/saved_objects_management/tsconfig.json +++ b/src/plugins/saved_objects_management/tsconfig.json @@ -28,6 +28,7 @@ "@kbn/shared-ux-router", "@kbn/core-ui-settings-browser-mocks", "@kbn/core-ui-settings-browser", + "@kbn/core-saved-objects-api-server", ], "exclude": [ "target/**/*", From d2165f3c9b3afdb4aeca3c34dbae0d7c50e94b15 Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Tue, 17 Oct 2023 10:24:34 +0200 Subject: [PATCH 37/87] [Fleet] Add support for additional types for dynamic mappings (#168842) Add support for fields that generate dynamic mappings of the following types: - match_only_text - scaled_float - aggregate_metric_double - half_float - ip - flattened - integer (mapped as long as in other cases) - group (child fields are installed as dynamic mappings) Default `match_matching_type` has been corrected to provide always a valid value. For example for floats it was using `float`, what is invalid, for this case it is changed to `double`. When the type is not known, an error is raised now instead of silently ignoring the field definition, this helps package developers discover earlier if their mappings are not well supported. Tested with the `install_all_packages` and no current package fails because of this. Fix https://github.com/elastic/kibana/issues/168823 --- .../elasticsearch/template/template.test.ts | 99 +++++++++++++++++++ .../epm/elasticsearch/template/template.ts | 71 ++++++++++--- 2 files changed, 157 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts index e5c323de62dfdb..f0459b10c85701 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts @@ -1124,6 +1124,105 @@ describe('EPM template', () => { expect(mappings).toEqual(runtimeFieldMapping); }); + it('tests processing scaled_float fields in a dynamic template', () => { + const textWithRuntimeFieldsLiteralYml = ` +- name: numeric_labels + type: object + object_type: scaled_float +`; + const runtimeFieldMapping = { + properties: {}, + dynamic_templates: [ + { + numeric_labels: { + match_mapping_type: '*', + path_match: 'numeric_labels.*', + mapping: { + type: 'scaled_float', + scaling_factor: 1000, + }, + }, + }, + ], + }; + const fields: Field[] = safeLoad(textWithRuntimeFieldsLiteralYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(mappings).toEqual(runtimeFieldMapping); + }); + + it('tests processing aggregate_metric_double fields in a dynamic template', () => { + const textWithRuntimeFieldsLiteralYml = ` +- name: aggregate.* + type: aggregate_metric_double + metrics: ["min", "max", "sum", "value_count"] + default_metric: "max" +`; + const runtimeFieldMapping = { + properties: {}, + dynamic_templates: [ + { + 'aggregate.*': { + match_mapping_type: '*', + path_match: 'aggregate.*', + mapping: { + type: 'aggregate_metric_double', + metrics: ['min', 'max', 'sum', 'value_count'], + default_metric: 'max', + }, + }, + }, + ], + }; + const fields: Field[] = safeLoad(textWithRuntimeFieldsLiteralYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(mappings).toEqual(runtimeFieldMapping); + }); + + it('tests processing groub sub fields in a dynamic template', () => { + const textWithRuntimeFieldsLiteralYml = ` +- name: group.*.network + type: group + fields: + - name: bytes + type: integer + metric_type: counter +`; + const runtimeFieldMapping = { + properties: {}, + dynamic_templates: [ + { + 'group.*.network.bytes': { + match_mapping_type: 'long', + path_match: 'group.*.network.bytes', + mapping: { + type: 'long', + time_series_metric: 'counter', + }, + }, + }, + ], + }; + const fields: Field[] = safeLoad(textWithRuntimeFieldsLiteralYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(mappings).toEqual(runtimeFieldMapping); + }); + + it('tests unexpected type for field as dynamic template fails', () => { + const textWithRuntimeFieldsLiteralYml = ` +- name: labels.* + type: object + object_type: constant_keyword +`; + const fields: Field[] = safeLoad(textWithRuntimeFieldsLiteralYml); + expect(() => { + const processedFields = processFields(fields); + generateMappings(processedFields); + }).toThrow(); + }); + it('tests priority and index pattern for data stream without dataset_is_prefix', () => { const dataStreamDatasetIsPrefixUnset = { type: 'metrics', diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts index e55cad3f80a9cc..36e13ae331f581 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts @@ -206,7 +206,7 @@ function _generateMappings( if (type === 'object' && field.object_type) { const pathMatch = path.includes('*') ? path : `${path}.*`; - let dynProperties: Properties = getDefaultProperties(field); + const dynProperties: Properties = getDefaultProperties(field); let matchingType: string | undefined; switch (field.object_type) { case 'keyword': @@ -216,10 +216,8 @@ function _generateMappings( case 'double': case 'long': case 'boolean': - dynProperties = { - type: field.object_type, - time_series_metric: field.metric_type, - }; + dynProperties.type = field.object_type; + dynProperties.time_series_metric = field.metric_type; matchingType = field.object_type_mapping_type ?? field.object_type; default: break; @@ -258,27 +256,74 @@ function _generateMappings( dynProperties = histogram(field); matchingType = field.object_type_mapping_type ?? '*'; break; + case 'ip': + case 'keyword': + case 'match_only_text': case 'text': + case 'wildcard': dynProperties.type = field.object_type; matchingType = field.object_type_mapping_type ?? 'string'; break; - case 'keyword': + case 'scaled_float': + dynProperties = scaledFloat(field); + matchingType = field.object_type_mapping_type ?? '*'; + break; + case 'aggregate_metric_double': dynProperties.type = field.object_type; - matchingType = field.object_type_mapping_type ?? 'string'; + dynProperties.metrics = field.metrics; + dynProperties.default_metric = field.default_metric; + matchingType = field.object_type_mapping_type ?? '*'; break; - case 'byte': case 'double': case 'float': + case 'half_float': + dynProperties.type = field.object_type; + dynProperties.time_series_metric = field.metric_type; + matchingType = field.object_type_mapping_type ?? 'double'; + break; + case 'byte': case 'long': case 'short': + case 'unsigned_long': + dynProperties.type = field.object_type; + dynProperties.time_series_metric = field.metric_type; + matchingType = field.object_type_mapping_type ?? 'long'; + break; + case 'integer': + // Map integers as long, as in other cases. + dynProperties.type = 'long'; + dynProperties.time_series_metric = field.metric_type; + matchingType = field.object_type_mapping_type ?? 'long'; + break; case 'boolean': - dynProperties = { - type: field.object_type, - time_series_metric: field.metric_type, - }; + dynProperties.type = field.object_type; + dynProperties.time_series_metric = field.metric_type; matchingType = field.object_type_mapping_type ?? field.object_type; - default: break; + case 'group': + if (!field?.fields) { + break; + } + const subFields = field.fields.map((subField) => ({ + ...subField, + type: 'object', + object_type: subField.object_type ?? subField.type, + })); + _generateMappings(subFields, { + ...ctx, + groupFieldName: ctx.groupFieldName + ? `${ctx.groupFieldName}.${field.name}` + : field.name, + }); + break; + case 'flattened': + dynProperties.type = field.object_type; + matchingType = field.object_type_mapping_type ?? 'object'; + break; + default: + throw new Error( + `no dynamic mapping generated for field ${path} of type ${field.object_type}` + ); } if (dynProperties && matchingType) { From 6dfc3cccea2445332706af64206ccad848da37ac Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com> Date: Tue, 17 Oct 2023 09:38:51 +0100 Subject: [PATCH 38/87] [Security Solution][Detections] adds new feature tour for ES|QL (#168879) ## Summary - similarly to https://github.com/elastic/kibana/pull/158863, adds feature tour for 8.11 new rule type ES|QL - tour is displayed for ESS only, as in Serverless ES|QL is not supported ### Screenshot Screenshot 2023-10-16 at 11 38 45 --- .../security_solution/common/constants.ts | 2 +- .../rule_creation/hooks/index.ts | 8 ++++ .../hooks/use_is_esql_rule_type_enabled.ts | 16 +++++++ .../alternative_tour/translations.ts | 3 +- .../pages/rule_management/index.tsx | 30 +++++++++---- .../rules/select_rule_type/index.test.tsx | 43 +++---------------- .../rules/select_rule_type/index.tsx | 9 ++-- 7 files changed, 57 insertions(+), 54 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_creation/hooks/index.ts create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_creation/hooks/use_is_esql_rule_type_enabled.ts diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index b282b127f36f5e..30f84dfa04b522 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -430,7 +430,7 @@ export const RULES_TABLE_MAX_PAGE_SIZE = 100; * we will need to update these constants with the corresponding version. */ export const NEW_FEATURES_TOUR_STORAGE_KEYS = { - RULE_MANAGEMENT_PAGE: 'securitySolution.rulesManagementPage.newFeaturesTour.v8.9', + RULE_MANAGEMENT_PAGE: 'securitySolution.rulesManagementPage.newFeaturesTour.v8.11', }; export const RULE_DETAILS_EXECUTION_LOG_TABLE_SHOW_METRIC_COLUMNS_STORAGE_KEY = diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/hooks/index.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/hooks/index.ts new file mode 100644 index 00000000000000..ba849f2c85864e --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/hooks/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 { useIsEsqlRuleTypeEnabled } from './use_is_esql_rule_type_enabled'; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/hooks/use_is_esql_rule_type_enabled.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/hooks/use_is_esql_rule_type_enabled.ts new file mode 100644 index 00000000000000..1bd45eb43156fe --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/hooks/use_is_esql_rule_type_enabled.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; +import { useKibana } from '../../../common/lib/kibana'; + +export const useIsEsqlRuleTypeEnabled = (): boolean => { + const isEsqlSettingEnabled = useKibana().services.configSettings.ESQLEnabled; + const isEsqlRuleTypeEnabled = !useIsExperimentalFeatureEnabled('esqlRulesDisabled'); + + return isEsqlSettingEnabled && isEsqlRuleTypeEnabled; +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/alternative_tour/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/alternative_tour/translations.ts index 79666589d76467..aa9474121cc30b 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/alternative_tour/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/alternative_tour/translations.ts @@ -17,6 +17,7 @@ export const CREATE_RULE_TOUR_TITLE = i18n.translate( export const CREATE_RULE_TOUR_CONTENT = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.tour.createRuleTourContent.eql', { - defaultMessage: `EQL now allows you to specify events that should not occur in a sequence`, + defaultMessage: + 'Use the Elasticsearch Query Language (ES|QL) rule to find events and aggregate search results.', } ); 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 c9160c3cba1b99..3e390eb29b42d2 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 @@ -35,6 +35,8 @@ import { AllRules } from '../../components/rules_table'; import { RulesTableContextProvider } from '../../components/rules_table/rules_table/rules_table_context'; import { useInvalidateFetchCoverageOverviewQuery } from '../../../rule_management/api/hooks/use_fetch_coverage_overview_query'; import { HeaderPage } from '../../../../common/components/header_page'; +import { RulesPageTourComponent } from '../../components/rules_table/alternative_tour/tour'; +import { useIsEsqlRuleTypeEnabled } from '../../../rule_creation/hooks'; const RulesPageComponent: React.FC = () => { const [isImportModalVisible, showImportModal, hideImportModal] = useBoolState(); @@ -70,6 +72,8 @@ const RulesPageComponent: React.FC = () => { } = useListsConfig(); const loading = userInfoLoading || listsConfigLoading; + const isEsqlRuleTypeEnabled = useIsEsqlRuleTypeEnabled(); + if ( redirectToDetections( isSignalIndexExists, @@ -85,6 +89,18 @@ const RulesPageComponent: React.FC = () => { return null; } + const addNewRuleButton = ( + + {i18n.ADD_NEW_RULE} + + ); + return ( <> @@ -139,15 +155,11 @@ const RulesPageComponent: React.FC = () => { - - {i18n.ADD_NEW_RULE} - + {isEsqlRuleTypeEnabled ? ( + {addNewRuleButton} + ) : ( + addNewRuleButton + )} diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.test.tsx index 3007208f60d2b1..9bf1553dbfd189 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.test.tsx @@ -10,24 +10,12 @@ import { mount, shallow } from 'enzyme'; import { SelectRuleType } from '.'; import { TestProviders, useFormFieldMock } from '../../../../common/mock'; -import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; +import { useIsEsqlRuleTypeEnabled } from '../../../../detection_engine/rule_creation/hooks'; -jest.mock('../../../../common/lib/kibana'); - -jest.mock('../../../../common/hooks/use_experimental_features', () => ({ - useIsExperimentalFeatureEnabled: jest.fn().mockReturnValue(false), // enabled (esqlRulesDisabled = false) +jest.mock('../../../../detection_engine/rule_creation/hooks', () => ({ + useIsEsqlRuleTypeEnabled: jest.fn().mockReturnValue(true), })); -const useIsExperimentalFeatureEnabledMock = useIsExperimentalFeatureEnabled as jest.Mock; - -const mockESQLEnabled = jest.fn(() => true); -jest.mock('../../../../common/lib/kibana', () => { - const useKibana = jest.requireActual('../../../../common/lib/kibana').useKibana; - return { - useKibana: () => ({ - services: { ...useKibana().services, configSettings: { ESQLEnabled: mockESQLEnabled() } }, - }), - }; -}); +const useIsEsqlRuleTypeEnabledMock = useIsEsqlRuleTypeEnabled as jest.Mock; describe('SelectRuleType', () => { it('renders correctly', () => { @@ -197,27 +185,8 @@ describe('SelectRuleType', () => { expect(wrapper.find('[data-test-subj="esqlRuleType"]').exists()).toBeTruthy(); }); - it('should not render "esql" rule type if esql setting is disabled', () => { - mockESQLEnabled.mockReturnValueOnce(false); - const Component = () => { - const field = useFormFieldMock(); - - return ( - - ); - }; - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="esqlRuleType"]').exists()).toBeFalsy(); - }); - - it('should not render "esql" rule type if the feature flag is disabled', () => { - useIsExperimentalFeatureEnabledMock.mockReturnValue(true); // disabled (esqlRulesDisabled = true) + it('should not render "esql" rule type if esql rule is not enabled', () => { + useIsEsqlRuleTypeEnabledMock.mockReturnValueOnce(false); const Component = () => { const field = useFormFieldMock(); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.tsx index 00643c717f22ab..61ce85d8e43a7d 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.tsx @@ -22,8 +22,7 @@ import type { FieldHook } from '../../../../shared_imports'; import * as i18n from './translations'; import { MlCardDescription } from './ml_card_description'; import { TechnicalPreviewBadge } from '../technical_preview_badge'; -import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; -import { useKibana } from '../../../../common/lib/kibana'; +import { useIsEsqlRuleTypeEnabled } from '../../../../detection_engine/rule_creation/hooks'; interface SelectRuleTypeProps { describedByIds: string[]; @@ -50,9 +49,7 @@ export const SelectRuleType: React.FC = memo( const setNewTerms = useCallback(() => setType('new_terms'), [setType]); const setEsql = useCallback(() => setType('esql'), [setType]); - const isEsqlSettingEnabled = useKibana().services.configSettings.ESQLEnabled; - const isEsqlFeatureFlagEnabled = !useIsExperimentalFeatureEnabled('esqlRulesDisabled'); - const isEsqlFeatureEnabled = isEsqlSettingEnabled && isEsqlFeatureFlagEnabled; + const isEsqlRuleTypeEnabled = useIsEsqlRuleTypeEnabled(); const eqlSelectableConfig = useMemo( () => ({ @@ -198,7 +195,7 @@ export const SelectRuleType: React.FC = memo( /> )} - {isEsqlFeatureEnabled && (!isUpdateView || esqlSelectableConfig.isSelected) && ( + {isEsqlRuleTypeEnabled && (!isUpdateView || esqlSelectableConfig.isSelected) && ( Date: Tue, 17 Oct 2023 10:43:36 +0200 Subject: [PATCH 39/87] profiling: include new config key in package schema (#168332) ## Summary Include the `telemetry` config key as part of the Fleet policy configuring the Universal Profiling backend services. ### 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 ### 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) Signed-off-by: inge4pres --- x-pack/plugins/profiling/server/index.ts | 8 ++++-- .../server/lib/setup/fleet_policies.test.ts | 25 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/profiling/server/index.ts b/x-pack/plugins/profiling/server/index.ts index ea2b008c6a5905..25861fbcfc750b 100644 --- a/x-pack/plugins/profiling/server/index.ts +++ b/x-pack/plugins/profiling/server/index.ts @@ -12,11 +12,15 @@ import { ProfilingPlugin } from './plugin'; /** * These properties are used to create both the Collector and the Symbolizer integrations * when Universal Profiling is initialized. - * As of now Universal Profiling is only availble on Elastic Cloud, so - * Elastic Cloud will be responsable of filling these properties up and pass it to Kibana. + * As of now Universal Profiling is only available on Elastic Cloud, so + * Elastic Cloud will fill these properties up and pass it to Kibana. + * Note that the list of config options does not encompass all the avaiable entries + * offered by the integrations pacakges, but are limited to the ones that + * Cloud will make use of. */ const packageInputSchema = schema.object({ host: schema.maybe(schema.string()), + telemetry: schema.maybe(schema.boolean()), tls_enabled: schema.maybe(schema.boolean()), tls_supported_protocols: schema.maybe(schema.arrayOf(schema.string())), tls_certificate_path: schema.maybe(schema.string()), diff --git a/x-pack/plugins/profiling/server/lib/setup/fleet_policies.test.ts b/x-pack/plugins/profiling/server/lib/setup/fleet_policies.test.ts index 66e30bbaa3d914..95b20eab2bec1c 100644 --- a/x-pack/plugins/profiling/server/lib/setup/fleet_policies.test.ts +++ b/x-pack/plugins/profiling/server/lib/setup/fleet_policies.test.ts @@ -72,4 +72,29 @@ describe('getVarsFor', () => { tls_key_path: { type: 'text', value: '456' }, }); }); + + it('returns vars with the telemetry key', () => { + const config: PackageInputType = { + host: 'example.com', + telemetry: true, + tls_enabled: true, + tls_supported_protocols: ['foo', 'bar'], + tls_certificate_path: '123', + tls_key_path: '456', + }; + + const { secret_token: secretToken, ...result } = getVarsFor({ + config, + includeSecretToken: false, + }); + expect(secretToken).toBeUndefined(); + expect(result).toEqual({ + host: { type: 'text', value: 'example.com' }, + telemetry: { type: 'bool', value: true }, + tls_enabled: { type: 'bool', value: true }, + tls_supported_protocols: { type: 'text', value: ['foo', 'bar'] }, + tls_certificate_path: { type: 'text', value: '123' }, + tls_key_path: { type: 'text', value: '456' }, + }); + }); }); From cbb7c4983b32f9c8bedb727857771bba8e52aac3 Mon Sep 17 00:00:00 2001 From: Marco Antonio Ghiani Date: Tue, 17 Oct 2023 11:05:12 +0200 Subject: [PATCH 40/87] [Log Explorer] Set log.level as default breakdown field (#168947) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📓 Summary Closes #166595 This work set the default breakdown field for the Log Explorer to be `log.level`. https://github.com/elastic/kibana/assets/34506779/63a75990-dafc-40d8-89cc-90c2afbdebf0 Co-authored-by: Marco Antonio Ghiani --- x-pack/plugins/log_explorer/common/constants.ts | 1 + .../log_explorer_profile/src/url_state_storage_service.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/log_explorer/common/constants.ts b/x-pack/plugins/log_explorer/common/constants.ts index e0ffcafed69e15..4a93192b13acb3 100644 --- a/x-pack/plugins/log_explorer/common/constants.ts +++ b/x-pack/plugins/log_explorer/common/constants.ts @@ -10,6 +10,7 @@ export const LOG_EXPLORER_PROFILE_ID = 'log-explorer'; // Fields constants export const TIMESTAMP_FIELD = '@timestamp'; export const HOST_NAME_FIELD = 'host.name'; +export const LOG_LEVEL_FIELD = 'log.level'; export const MESSAGE_FIELD = 'message'; export const SERVICE_NAME_FIELD = 'service.name'; diff --git a/x-pack/plugins/log_explorer/public/state_machines/log_explorer_profile/src/url_state_storage_service.ts b/x-pack/plugins/log_explorer/public/state_machines/log_explorer_profile/src/url_state_storage_service.ts index 5fd46dec9bf0bb..b84cce4dbf2cf7 100644 --- a/x-pack/plugins/log_explorer/public/state_machines/log_explorer_profile/src/url_state_storage_service.ts +++ b/x-pack/plugins/log_explorer/public/state_machines/log_explorer_profile/src/url_state_storage_service.ts @@ -19,6 +19,7 @@ import { import { DATA_GRID_COLUMNS_PREFERENCES, DATA_GRID_DEFAULT_COLUMNS, + LOG_LEVEL_FIELD, } from '../../../../common/constants'; import { ControlPanelRT, @@ -182,7 +183,7 @@ export const updateStateContainer = LogExplorerProfileEvent > => async () => { - const { columns, grid, rowHeight } = stateContainer.appState.getState(); + const { breakdownField, columns, grid, rowHeight } = stateContainer.appState.getState(); const stateUpdates: DiscoverAppState = {}; // Update data grid columns list @@ -201,6 +202,9 @@ export const updateStateContainer = // Configure rowHeight preference stateUpdates.rowHeight = rowHeight ?? ROWS_HEIGHT_OPTIONS.single; + // Configure breakdown field preference + stateUpdates.breakdownField = breakdownField ?? LOG_LEVEL_FIELD; + // Finally batch update state app state stateContainer.appState.update(stateUpdates, true); }; From a0b5898940377d21852d5c4d8dc9c4e337ffa76d Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Tue, 17 Oct 2023 11:37:27 +0200 Subject: [PATCH 41/87] Fix incorrect no data alert for Metric threshold and Custom threshold rules when groupBy field is added and removed (#168963) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #168829 ## Summary This PR fixes the issue when a Metric threshold or Custom threshold rule is created with the groupBy field and then gets updated, and the groupBy field is removed. In this scenario, if no alert is triggered, a no-data alert is generated wrongly. This issue is due to saving `groupBy` field as an empty string in the rule's saved object. Screenshot 2023-10-16 at 15 28 41 ### 🧪 How to test - Create a Metric threshold or Custom threshold rule with `groupBy` field that does not trigger any alert - Update the rule and remove the groupBy field - You shouldn't see a no-data alert in this case anymore --- .../lib/alerting/metric_threshold/lib/create_bucket_selector.ts | 2 +- .../lib/rules/custom_threshold/lib/create_bucket_selector.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/create_bucket_selector.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/create_bucket_selector.ts index a458104a7400a4..25e725d7d0a628 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/create_bucket_selector.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/create_bucket_selector.ts @@ -26,7 +26,7 @@ export const createBucketSelector = ( groupBy?: string | string[], lastPeriodEnd?: number ) => { - const hasGroupBy = groupBy != null; + const hasGroupBy = !!groupBy; const hasWarn = condition.warningThreshold != null && condition.warningComparator != null; const isPercentile = [Aggregators.P95, Aggregators.P99].includes(condition.aggType); const isCount = condition.aggType === Aggregators.COUNT; diff --git a/x-pack/plugins/observability/server/lib/rules/custom_threshold/lib/create_bucket_selector.ts b/x-pack/plugins/observability/server/lib/rules/custom_threshold/lib/create_bucket_selector.ts index 83c84af79eda6c..3066276316921d 100644 --- a/x-pack/plugins/observability/server/lib/rules/custom_threshold/lib/create_bucket_selector.ts +++ b/x-pack/plugins/observability/server/lib/rules/custom_threshold/lib/create_bucket_selector.ts @@ -19,7 +19,7 @@ export const createBucketSelector = ( groupBy?: string | string[], lastPeriodEnd?: number ) => { - const hasGroupBy = groupBy != null; + const hasGroupBy = !!groupBy; const isPercentile = [Aggregators.P95, Aggregators.P99].includes(condition.aggType); const isCount = condition.aggType === Aggregators.COUNT; const isRate = condition.aggType === Aggregators.RATE; From 291f5eabc18cf2dd230805d1cb2c8dcba655ad93 Mon Sep 17 00:00:00 2001 From: jennypavlova Date: Tue, 17 Oct 2023 11:55:41 +0200 Subject: [PATCH 42/87] [Infra UI] Add infra serverless functional tests (#168621) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #166749 ## Summary This PR adds serverless functional tests for the infra plugin. The main goal is to make sure that the app loads all the pages and successfully navigates between them. As we already have functional tests covering the whole functionality here we want to cover the differences with serverless and some basic checks ensuring that base functionality works correctly. - Update the test to cover disabling the create rule button added [here](https://github.com/elastic/kibana/pull/167978): ([x-pack/test_serverless/functional/test_suites/observability/infra/hosts_page.ts](https://github.com/elastic/kibana/pull/168621/commits/87fb991f2f07140c0c4379161557935b5187b3bf#diff-76bd05d3fed2c44187682e27b4030ddb9cba1a36235321e0db1b371ef6739cc9)) ⚠️ The tests for the second AC point related to user roles will go in a[ separate issue ](https://github.com/elastic/kibana/issues/168931) Test server run: `node scripts/functional_tests_server.js --config=x-pack/test_serverless/functional/test_suites/observability/config.ts` Tests run: `node scripts/functional_test_runner --config=x-pack/test_serverless/functional/test_suites/observability/config.ts --grep "Observability Infra"` --- .../tabs/processes/processes.tsx | 2 +- .../observability/infra/constants.ts | 21 ++ .../observability/infra/hosts_page.ts | 221 ++++++++++++++++++ .../test_suites/observability/infra/index.ts | 3 + .../test_suites/observability/infra/infra.ts | 131 +++++++++++ .../observability/infra/node_details.ts | 89 +++++++ 6 files changed, 466 insertions(+), 1 deletion(-) create mode 100644 x-pack/test_serverless/functional/test_suites/observability/infra/hosts_page.ts create mode 100644 x-pack/test_serverless/functional/test_suites/observability/infra/infra.ts create mode 100644 x-pack/test_serverless/functional/test_suites/observability/infra/node_details.ts diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/processes/processes.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/processes/processes.tsx index 973ff681ab570c..dfaf227dc10df0 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/processes/processes.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/processes/processes.tsx @@ -105,7 +105,7 @@ export const Processes = () => { - + { + const browser = getService('browser'); + const esArchiver = getService('esArchiver'); + const retry = getService('retry'); + const testSubjects = getService('testSubjects'); + const pageObjects = getPageObjects([ + 'assetDetails', + 'common', + 'infraHome', + 'timePicker', + 'infraHostsView', + 'settings', + 'header', + 'svlCommonPage', + ]); + + const waitForPageToLoad = async () => + await retry.waitFor( + 'wait for table and KPI charts to load', + async () => + (await pageObjects.infraHostsView.isHostTableLoading()) && + (await pageObjects.infraHostsView.isKPIChartsLoaded()) + ); + + describe('Hosts Page', function () { + before(async () => { + await Promise.all([ + esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'), + ]); + await pageObjects.svlCommonPage.login(); + await browser.setWindowSize(1600, 1200); + }); + + after(async () => { + await Promise.all([ + esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'), + ]); + await pageObjects.svlCommonPage.forceLogout(); + }); + + describe('#Single Host Flyout', () => { + before(async () => { + await pageObjects.common.navigateToApp(HOSTS_VIEW_PATH); + await pageObjects.header.waitUntilLoadingHasFinished(); + }); + + describe('Tabs', () => { + before(async () => { + await pageObjects.timePicker.setAbsoluteRange( + START_DATE.format(DATE_PICKER_FORMAT), + END_DATE.format(DATE_PICKER_FORMAT) + ); + + await waitForPageToLoad(); + + await pageObjects.infraHostsView.clickTableOpenFlyoutButton(); + }); + + after(async () => { + await retry.try(async () => { + await pageObjects.infraHostsView.clickCloseFlyoutButton(); + }); + }); + + describe('Overview Tab', () => { + before(async () => { + await pageObjects.assetDetails.clickOverviewTab(); + }); + + it('should render 9 charts in the Metrics section', async () => { + const hosts = await pageObjects.assetDetails.getAssetDetailsMetricsCharts(); + expect(hosts.length).to.equal(9); + }); + + it('should show alerts', async () => { + await pageObjects.header.waitUntilLoadingHasFinished(); + await pageObjects.assetDetails.overviewAlertsTitleExists(); + const CreateRuleButtonExist = await testSubjects.exists( + 'infraAssetDetailsCreateAlertsRuleButton' + ); + expect(CreateRuleButtonExist).to.be(false); + }); + }); + + describe('Metadata Tab', () => { + before(async () => { + await pageObjects.assetDetails.clickMetadataTab(); + }); + + it('should show metadata table', async () => { + await pageObjects.assetDetails.metadataTableExists(); + }); + }); + + describe('Processes Tab', () => { + before(async () => { + await pageObjects.assetDetails.clickProcessesTab(); + }); + + it('should show processes title', async () => { + await await testSubjects.existOrFail('infraAssetDetailsTopProcessesTitle'); + }); + + describe('Logs Tab', () => { + before(async () => { + await pageObjects.assetDetails.clickLogsTab(); + }); + + it('should render logs tab', async () => { + await pageObjects.assetDetails.logsExists(); + }); + }); + }); + }); + + describe('#Page Content', () => { + before(async () => { + await pageObjects.common.navigateToApp(HOSTS_VIEW_PATH); + await pageObjects.header.waitUntilLoadingHasFinished(); + await pageObjects.timePicker.setAbsoluteRange( + START_DATE.format(DATE_PICKER_FORMAT), + END_DATE.format(DATE_PICKER_FORMAT) + ); + + await waitForPageToLoad(); + }); + + it('should render the correct page title', async () => { + const documentTitle = await browser.getTitle(); + expect(documentTitle).to.contain('Hosts - Infrastructure - Observability - Elastic'); + }); + + it('should render the title beta badge', async () => { + await pageObjects.infraHostsView.getBetaBadgeExists(); + }); + + describe('Hosts table', async () => { + let hostRows: WebElementWrapper[] = []; + + before(async () => { + hostRows = await pageObjects.infraHostsView.getHostsTableData(); + }); + + it('should render a table with 6 hosts', async () => { + expect(hostRows.length).to.equal(6); + }); + }); + + describe('KPIs', () => { + it('should render KPIs', async () => { + await testSubjects.existOrFail('hostsViewKPIGrid'); + }); + }); + + describe('Metrics Tab', () => { + before(async () => { + await browser.scrollTop(); + await pageObjects.infraHostsView.visitMetricsTab(); + }); + + after(async () => { + await browser.scrollTop(); + }); + + it('should load 12 lens metric charts', async () => { + const metricCharts = await pageObjects.infraHostsView.getAllMetricsCharts(); + expect(metricCharts.length).to.equal(12); + }); + }); + + describe('Logs Tab', () => { + before(async () => { + await browser.scrollTop(); + await pageObjects.infraHostsView.visitLogsTab(); + }); + + after(async () => { + await browser.scrollTop(); + }); + + it('should load the Logs tab section when clicking on it', async () => { + await testSubjects.existOrFail('hostsView-logs'); + }); + }); + + describe('Alerts Tab', () => { + before(async () => { + await browser.scrollTop(); + await pageObjects.infraHostsView.visitAlertTab(); + }); + + after(async () => { + await browser.scrollTop(); + }); + + it('should correctly load the Alerts tab section when clicking on it', async () => { + testSubjects.existOrFail('hostsView-alerts'); + }); + }); + }); + }); + }); +}; diff --git a/x-pack/test_serverless/functional/test_suites/observability/infra/index.ts b/x-pack/test_serverless/functional/test_suites/observability/infra/index.ts index 80eb2f7a32a53f..bca78c40527e9d 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/infra/index.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/infra/index.ts @@ -12,5 +12,8 @@ export default function ({ loadTestFile }: FtrProviderContext) { // TimeoutError: Waiting for element to be located By(css selector, [data-test-subj="infrastructure-alerts-and-rules"]) this.tags(['failsOnMKI']); loadTestFile(require.resolve('./header_menu')); + loadTestFile(require.resolve('./node_details')); + loadTestFile(require.resolve('./hosts_page')); + loadTestFile(require.resolve('./infra')); }); } diff --git a/x-pack/test_serverless/functional/test_suites/observability/infra/infra.ts b/x-pack/test_serverless/functional/test_suites/observability/infra/infra.ts new file mode 100644 index 00000000000000..94e9f35393e7fe --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/observability/infra/infra.ts @@ -0,0 +1,131 @@ +/* + * 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 type { FtrProviderContext } from '../../../ftr_provider_context'; +import { DATES, INVENTORY_PATH, METRICS_EXPLORER_PATH } from './constants'; + +const DATE_WITH_DATA = DATES.metricsAndLogs.hosts.withData; +const DATE_WITHOUT_DATA = DATES.metricsAndLogs.hosts.withoutData; +const DATE_WITH_POD_WITH_DATA = DATES.metricsAndLogs.pods.withData; + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const esArchiver = getService('esArchiver'); + const browser = getService('browser'); + const retry = getService('retry'); + const testSubjects = getService('testSubjects'); + const pageObjects = getPageObjects(['common', 'header', 'infraHome', 'svlCommonPage']); + const kibanaServer = getService('kibanaServer'); + + const returnTo = async (path: string, timeout = 2000) => + retry.waitForWithTimeout('returned to inventory', timeout, async () => { + await browser.goBack(); + await pageObjects.header.waitUntilLoadingHasFinished(); + const currentUrl = await browser.getCurrentUrl(); + return !!currentUrl.match(path); + }); + + describe('Infra pages', function () { + before(async () => { + await pageObjects.svlCommonPage.login(); + }); + + after(async () => { + await pageObjects.svlCommonPage.forceLogout(); + }); + + describe('Inventory page', function () { + this.tags('includeFirefox'); + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + }); + + describe('with metrics present', () => { + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + await esArchiver.load('x-pack/test/functional/es_archives/infra/8.0.0/pods_only'); + await pageObjects.common.navigateToApp(INVENTORY_PATH); + await pageObjects.infraHome.waitForLoading(); + }); + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + await esArchiver.unload('x-pack/test/functional/es_archives/infra/8.0.0/pods_only'); + }); + + it('renders the correct page title', async () => { + await pageObjects.header.waitUntilLoadingHasFinished(); + + const documentTitle = await browser.getTitle(); + expect(documentTitle).to.contain('Inventory - Infrastructure - Observability - Elastic'); + }); + + it('renders an empty data prompt for dates with no data', async () => { + await pageObjects.infraHome.goToTime(DATE_WITHOUT_DATA); + await pageObjects.infraHome.getNoMetricsDataPrompt(); + }); + + it('renders the waffle map and tooltips for dates with data', async () => { + await pageObjects.infraHome.goToTime(DATE_WITH_DATA); + await pageObjects.infraHome.getWaffleMap(); + }); + + describe('Redirect to Node Details page', () => { + before(async () => { + await pageObjects.common.navigateToApp(INVENTORY_PATH); + await pageObjects.infraHome.waitForLoading(); + }); + + it('Should redirect to Host Details page', async () => { + await pageObjects.infraHome.goToTime(DATE_WITH_DATA); + await pageObjects.infraHome.goToHost(); + await pageObjects.infraHome.clickOnFirstNode(); + await pageObjects.infraHome.waitForLoading(); + await pageObjects.infraHome.clickOnNodeDetailsFlyoutOpenAsPage(); + + await retry.try(async () => { + const documentTitle = await browser.getTitle(); + expect(documentTitle).to.contain( + 'demo-stack-redis-01 - Infrastructure - Observability - Elastic' + ); + }); + + await returnTo(INVENTORY_PATH); + }); + + it('Should redirect to Node Details page', async () => { + await pageObjects.infraHome.goToTime(DATE_WITH_POD_WITH_DATA); + await pageObjects.infraHome.goToPods(); + await pageObjects.infraHome.clickOnFirstNode(); + await pageObjects.infraHome.clickOnGoToNodeDetails(); + + await retry.try(async () => { + const documentTitle = await browser.getTitle(); + expect(documentTitle).to.contain('pod-0 - Infrastructure - Observability - Elastic'); + }); + + await returnTo(INVENTORY_PATH); + }); + }); + }); + }); + describe('Metrics explorer page', function () { + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + await pageObjects.common.navigateToApp(METRICS_EXPLORER_PATH); + await pageObjects.infraHome.waitForLoading(); + await pageObjects.header.waitUntilLoadingHasFinished(); + }); + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + }); + + it('should be disabled', async () => { + await testSubjects.existOrFail('infraNotFoundPage'); + }); + }); + }); +}; diff --git a/x-pack/test_serverless/functional/test_suites/observability/infra/node_details.ts b/x-pack/test_serverless/functional/test_suites/observability/infra/node_details.ts new file mode 100644 index 00000000000000..3806ee94c757da --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/observability/infra/node_details.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 moment from 'moment'; +import expect from '@kbn/expect'; +import type { FtrProviderContext } from '../../../ftr_provider_context'; +import { DATES, NODE_DETAILS_PATH, DATE_PICKER_FORMAT } from './constants'; + +const START_HOST_KUBERNETES_SECTION_DATE = moment.utc( + DATES.metricsAndLogs.hosts.kubernetesSectionStartDate +); +const END_HOST_KUBERNETES_SECTION_DATE = moment.utc( + DATES.metricsAndLogs.hosts.kubernetesSectionEndDate +); + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const esArchiver = getService('esArchiver'); + const testSubjects = getService('testSubjects'); + const pageObjects = getPageObjects([ + 'assetDetails', + 'common', + 'infraHome', + 'header', + 'timePicker', + 'svlCommonPage', + ]); + + describe('Node Details', () => { + describe('#With Asset Details', () => { + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + + await pageObjects.svlCommonPage.login(); + await pageObjects.common.navigateToApp( + `metrics/${NODE_DETAILS_PATH}/demo-stack-kubernetes-01` + ); + await pageObjects.header.waitUntilLoadingHasFinished(); + }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + await pageObjects.svlCommonPage.forceLogout(); + }); + + describe('Osquery Tab', () => { + it('should not render in serverless', async () => { + const OsqueryExist = await testSubjects.exists('infraAssetDetailsOsqueryTab'); + expect(OsqueryExist).to.be(false); + }); + }); + + describe('#With Kubernetes section', () => { + describe('Overview Tab', () => { + before(async () => { + await pageObjects.assetDetails.clickOverviewTab(); + + await pageObjects.timePicker.setAbsoluteRange( + START_HOST_KUBERNETES_SECTION_DATE.format(DATE_PICKER_FORMAT), + END_HOST_KUBERNETES_SECTION_DATE.format(DATE_PICKER_FORMAT) + ); + }); + + it('should show alerts', async () => { + await pageObjects.header.waitUntilLoadingHasFinished(); + await pageObjects.assetDetails.overviewAlertsTitleExists(); + const CreateRuleButtonExist = await testSubjects.exists( + 'infraAssetDetailsCreateAlertsRuleButton' + ); + expect(CreateRuleButtonExist).to.be(false); + }); + + it('should render 12 charts in the Metrics section', async () => { + const hosts = await pageObjects.assetDetails.getAssetDetailsMetricsCharts(); + expect(hosts.length).to.equal(12); + }); + + it('should render 4 charts in the Kubernetes Metrics section', async () => { + const hosts = await pageObjects.assetDetails.getAssetDetailsKubernetesMetricsCharts(); + expect(hosts.length).to.equal(4); + }); + }); + }); + }); + }); +}; From 9e951f59ac3e63238d8e64048c38173f69bb1feb Mon Sep 17 00:00:00 2001 From: Marta Bondyra <4283304+mbondyra@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:12:38 +0200 Subject: [PATCH 43/87] [Lens] passing locale to charts (#168571) ## Summary Screenshot 2023-10-17 at 11 13 20 Passes `locale={i18n.getLocale()}` to Component for elastic charts. For now it only matters for translating months, days etc in time histogram chart, but I'd rather pass it everywhere in case if we introduce some copy in the future. Fixes https://github.com/elastic/kibana/issues/166240 --- .../src/components/field_stats/field_stats.tsx | 8 +++++++- .../__snapshots__/gauge_component.test.tsx.snap | 1 + .../public/components/gauge_component.tsx | 2 ++ .../public/components/heatmap_component.tsx | 1 + .../public/components/metric_vis.tsx | 1 + .../partition_vis_component.test.tsx.snap | 6 ++++++ .../components/partition_vis_component.tsx | 1 + .../public/components/tagcloud_component.tsx | 2 ++ .../__snapshots__/xy_chart.test.tsx.snap | 10 ++++++++++ .../expression_xy/public/components/xy_chart.tsx | 2 ++ .../public/components/timelion_vis_component.tsx | 2 ++ .../visualizations/views/timeseries/index.js | 2 ++ .../document_count_chart.tsx | 1 + .../ml/data_grid/components/column_chart.tsx | 2 ++ .../data_quality_panel/storage_treemap/index.tsx | 2 ++ .../ecs_summary_donut_chart/index.tsx | 14 ++++++++++---- .../components/mini_histogram/mini_histogram.tsx | 7 ++++++- .../ui_components/chart_preview/index.tsx | 2 ++ .../error_group_details/distribution/index.tsx | 1 + .../most_used_charts/sunburst_chart.tsx | 2 +- .../storage_details_per_service.tsx | 1 + .../app/storage_explorer/storage_chart.tsx | 2 ++ .../shared/charts/breakdown_chart/index.tsx | 1 + .../charts/duration_distribution_chart/index.tsx | 1 + .../index.tsx | 1 + .../shared/charts/spark_plot/index.tsx | 2 ++ .../shared/charts/timeseries_chart.tsx | 1 + .../shared/critical_path_flamegraph/index.tsx | 2 ++ .../compliance_charts/compliance_score_chart.tsx | 1 + .../vulnerability_trend_graph.tsx | 2 +- .../document_count_chart.tsx | 1 + .../field_data_expanded_row/boolean_content.tsx | 3 ++- .../components/field_data_row/column_chart.tsx | 2 ++ .../metric_distribution_chart.tsx | 2 +- .../charts/data_drift_distribution_chart.tsx | 3 ++- .../charts/overlap_distribution_chart.tsx | 2 +- .../charts/single_distribution_chart.tsx | 3 ++- .../analytics_collection_chart.tsx | 1 + .../analytics_collection_card.tsx | 1 + .../analytics/components/analytics_chart.tsx | 3 +++ .../alerting/common/components/threshold.tsx | 2 +- .../inventory/components/expression_chart.tsx | 3 ++- .../criterion_preview_chart.tsx | 3 ++- .../components/expression_chart.tsx | 2 ++ .../tabs/processes/process_row_charts.tsx | 6 +++++- .../top_categories/single_metric_sparkline.tsx | 3 ++- .../components/timeline/timeline.tsx | 1 + .../components/chart_section_vis.tsx | 1 + .../metrics_explorer/components/chart.tsx | 7 ++++++- .../feature_importance/decision_path_chart.tsx | 1 + .../feature_importance_summary.tsx | 1 + .../explorer_charts/explorer_charts_container.js | 2 +- .../application/explorer/swimlane_container.tsx | 1 + .../datafeed_chart_flyout.tsx | 1 + .../charts/anomaly_chart/anomaly_chart.tsx | 2 ++ .../charts/event_rate_chart/event_rate_chart.tsx | 2 ++ .../memory_usage/memory_tree_map/tree_map.tsx | 2 +- .../nodes_overview/memory_preview_chart.tsx | 1 + .../components/custom_threshold.tsx | 2 +- .../components/expression_chart.tsx | 2 ++ .../embeddable/slo/overview/slo_overview.tsx | 1 + .../components/sections/apm/apm_section.tsx | 1 + .../components/sections/logs/logs_section.tsx | 1 + .../sections/metrics/metric_with_sparkline.tsx | 3 ++- .../sections/uptime/uptime_section.tsx | 1 + .../pages/slo_details/components/wide_chart.tsx | 2 ++ .../components/common/data_preview_chart.tsx | 1 + .../pages/slos/components/slo_sparkline.tsx | 2 ++ .../public/components/flamegraph/index.tsx | 2 ++ .../components/stacked_bar_chart/index.tsx | 2 ++ .../profiling/public/components/subchart.tsx | 7 ++++++- .../grouped_index_details_chart.tsx | 1 + .../host_breakdown/host_breakdown_chart.tsx | 2 ++ .../common/components/alerts_treemap/index.tsx | 2 ++ .../common/components/charts/areachart.tsx | 2 ++ .../public/common/components/charts/barchart.tsx | 7 ++++++- .../common/components/charts/donutchart.tsx | 2 ++ .../alerts_histogram_panel/alerts_histogram.tsx | 2 ++ .../risk_score/risk_score_over_time/index.tsx | 16 +++++++++++----- .../rule_types/threshold/visualization.tsx | 2 ++ .../monitor_status/monitor_status_panel.tsx | 4 ++-- .../overview/overview/metric_item.tsx | 1 + .../network_timings_donut.tsx | 6 +++++- .../waterfall/waterfall_bar_chart.tsx | 2 ++ .../waterfall/waterfall_chart_fixed_axis.tsx | 2 ++ .../indicators/components/barchart/barchart.tsx | 2 ++ .../components/alert_summary_widget_compact.tsx | 3 ++- .../alert_summary_widget_full_size.tsx | 2 ++ .../components/execution_duration_chart.tsx | 1 + .../__snapshots__/donut_chart.test.tsx.snap | 1 + .../components/common/charts/donut_chart.tsx | 1 + .../components/common/charts/duration_chart.tsx | 1 + .../common/charts/monitor_bar_series.tsx | 1 + .../components/common/charts/ping_histogram.tsx | 1 + .../waterfall/components/waterfall_bar_chart.tsx | 2 ++ .../components/waterfall_chart_fixed_axis.tsx | 3 ++- .../threshold_watch_edit/watch_visualization.tsx | 2 ++ 97 files changed, 208 insertions(+), 35 deletions(-) diff --git a/packages/kbn-unified-field-list/src/components/field_stats/field_stats.tsx b/packages/kbn-unified-field-list/src/components/field_stats/field_stats.tsx index 8e0eaedc2acbcd..4f5b71384b326d 100755 --- a/packages/kbn-unified-field-list/src/components/field_stats/field_stats.tsx +++ b/packages/kbn-unified-field-list/src/components/field_stats/field_stats.tsx @@ -484,6 +484,7 @@ const FieldStatsComponent: React.FC = ({ = ({ size={{ height: 200, width: '100%' }} > - + = memo( ariaLabel={args.ariaLabel} ariaUseDefaultSummary={!args.ariaLabel} onRenderChange={onRenderChange} + locale={i18n.getLocale()} {...getOverridesFor(overrides, 'settings')} /> = memo( onBrushEnd={interactive ? (onBrushEnd as BrushEndListener) : undefined} ariaLabel={args.ariaLabel} ariaUseDefaultSummary={!args.ariaLabel} + locale={i18n.getLocale()} {...settingsOverrides} /> { onRenderChange={onRenderChange} ariaLabel={props.visParams.ariaLabel} ariaUseDefaultSummary={!props.visParams.ariaLabel} + locale={i18n.getLocale()} {...settingsOverrides} /> {annotations.map(({ id, data, icon, color }) => { diff --git a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx index dd0d30862ea783..7fa45baa1fdc69 100644 --- a/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx +++ b/x-pack/packages/ml/aiops_components/src/document_count_chart/document_count_chart.tsx @@ -489,6 +489,7 @@ export const DocumentCountChart: FC = (props) => { debugState={window._echDebugStateFlag ?? false} showLegend={false} showLegendExtra={false} + locale={i18n.getLocale()} /> = ({ = ({ showLegend={false} theme={[treemapTheme, theme]} onElementClick={onElementClick} + locale={i18n.getLocale()} /> = ({ return ( <> -

{i18n.CHART_TITLE}

+

{translations.CHART_TITLE}

@@ -155,10 +156,14 @@ const EcsSummaryDonutChartComponent: React.FC = ({ justifyContent="center" > - + {partitionedFieldMetadata.all.length} - {i18n.FIELDS} + {translations.FIELDS} @@ -169,6 +174,7 @@ const EcsSummaryDonutChartComponent: React.FC = ({ baseTheme={baseTheme} onElementClick={onElementClick} theme={[donutTheme, theme]} + locale={i18n.getLocale()} /> = ({
- + {isDataAvailable ? ( - + {selectionAnnotation !== undefined && ( {type && type === 'bar' ? ( diff --git a/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx b/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx index 8de178569248a8..1fd876d61b3d3b 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx @@ -204,6 +204,7 @@ export function TimeseriesChart({ onToggleLegend(legend); } }} + locale={i18n.getLocale()} /> {}} + locale={i18n.getLocale()} /> { baseTheme={charts.theme.useChartsBaseTheme()} showLegend={false} legendPosition="right" + locale={i18n.getLocale()} /> { >
- + = ({ onElementClick={onElementClick} theme={chartTheme} baseTheme={chartBaseTheme} + locale={i18n.getLocale()} /> = ({ config, onAddFilter }) = tickFormat={(d: any) => getFormattedValue(d, count)} /> - + = ({ chartPaddings: zeroSize, crosshair: { band: { visible: false } }, }} + locale={i18n.getLocale()} /> = ({ > - + - + - + - + setHoverChart(null)} + locale={i18n.getLocale()} /> {charts.map(({ data: chartData, id, name, chartColor }) => ( diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collection_card/analytics_collection_card.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collection_card/analytics_collection_card.tsx index c302b8c6185792..f67cccd4ddcddc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collection_card/analytics_collection_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collection_card/analytics_collection_card.tsx @@ -190,6 +190,7 @@ export const AnalyticsCollectionCard: React.FC< chartMargins: { bottom: 0, left: 0, right: 0, top: 0 }, }} showLegend={false} + locale={i18n.getLocale()} /> = ({ height = 300, lines }) => { {lines.map(({ id, data, isDashed }) => ( - + = ({ tickFormat={dateFormatter} /> - + diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/criterion_preview_chart.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/criterion_preview_chart.tsx index 06f00c26abf26d..12c75ea11507a1 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/criterion_preview_chart.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/criterion_preview_chart.tsx @@ -7,6 +7,7 @@ import React, { ReactElement, useMemo } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; +import { i18n } from '@kbn/i18n'; import { ScaleType, AnnotationDomainType, @@ -330,7 +331,7 @@ const CriterionPreviewChart: React.FC = ({ tickFormat={yAxisFormatter} domain={chartDomain} /> - + diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx index 5ea5ebeecfaf19..8d4381a86572bb 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx @@ -22,6 +22,7 @@ import { useActiveCursor } from '@kbn/charts-plugin/public'; import { DataViewBase } from '@kbn/es-query'; import { first, last } from 'lodash'; +import { i18n } from '@kbn/i18n'; import { useTimelineChartTheme } from '../../../utils/use_timeline_chart_theme'; import { MetricsSourceConfiguration } from '../../../../common/metrics_sources'; import { Color } from '../../../../common/color_palette'; @@ -200,6 +201,7 @@ export const ExpressionChart: React.FC = ({ tooltip: { visible: true }, }} baseTheme={chartTheme.baseTheme} + locale={i18n.getLocale()} /> diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/processes/process_row_charts.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/processes/process_row_charts.tsx index e59aacf03c9d5d..8cd6d923690766 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/processes/process_row_charts.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/processes/process_row_charts.tsx @@ -127,7 +127,11 @@ const ProcessChart = ({ timeseries, color, label }: ProcessChartProps) => { gridLine={{ visible: true }} /> moment(value).format('Y-MM-DD HH:mm:ss.SSS')} /> - + ); diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/single_metric_sparkline.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/single_metric_sparkline.tsx index d95b19741258fe..566b601991c7b9 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/single_metric_sparkline.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/single_metric_sparkline.tsx @@ -12,6 +12,7 @@ import { EUI_SPARKLINE_THEME_PARTIAL, EUI_CHARTS_THEME_DARK, } from '@elastic/eui/dist/eui_charts_theme'; +import { i18n } from '@kbn/i18n'; import { useIsDarkMode } from '../../../../../hooks/use_is_dark_mode'; import { useKibanaTimeZoneSetting } from '../../../../../hooks/use_kibana_time_zone_setting'; import { TimeRange } from '../../../../../../common/time'; @@ -55,7 +56,7 @@ export const SingleMetricSparkline: React.FunctionComponent<{ return ( - + = ({ interval, yAxisFormatter, isVisible onElementClick={onClickPoint} baseTheme={chartTheme.baseTheme} theme={chartTheme.theme} + locale={i18n.getLocale()} /> diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/chart_section_vis.tsx b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/chart_section_vis.tsx index 91c8149bb9d982..3f56c643d662e4 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/chart_section_vis.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/chart_section_vis.tsx @@ -139,6 +139,7 @@ export const ChartSectionVis = ({ showLegend showLegendExtra legendPosition="right" + locale={i18n.getLocale()} />
diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/chart.tsx b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/chart.tsx index afd2b9a4cb2630..e0bc8609dce16d 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/chart.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/chart.tsx @@ -20,6 +20,7 @@ import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { first, last } from 'lodash'; import moment from 'moment'; import React, { useCallback, useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; import { useTimelineChartTheme } from '../../../../utils/use_timeline_chart_theme'; import { useKibanaContextForPlugin } from '../../../../hooks/use_kibana'; import { MetricsExplorerSeries } from '../../../../../common/http_api/metrics_explorer'; @@ -164,7 +165,11 @@ export const MetricsExplorerChart = ({ domain={domain} /> - +
) : options.metrics.length > 0 ? ( diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/decision_path_chart.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/decision_path_chart.tsx index f85cd11113d85e..1eb4fc62b472d2 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/decision_path_chart.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/decision_path_chart.tsx @@ -130,6 +130,7 @@ export const DecisionPathChart = ({ // TODO use the EUI charts theme see src/plugins/charts/public/services/theme/README.md theme={theme} rotation={90} + locale={i18n.getLocale()} /> {regressionBaselineData && ( - } width={0} height={0} /> + } width={0} height={0} locale={i18n.getLocale()} /> {/* Just need an empty chart to access cursor service */} diff --git a/x-pack/plugins/ml/public/application/explorer/swimlane_container.tsx b/x-pack/plugins/ml/public/application/explorer/swimlane_container.tsx index 05e6fdafe28d2f..4b69ce479c58ef 100644 --- a/x-pack/plugins/ml/public/application/explorer/swimlane_container.tsx +++ b/x-pack/plugins/ml/public/application/explorer/swimlane_container.tsx @@ -452,6 +452,7 @@ export const SwimlaneContainer: FC = ({ xDomain={xDomain} debugState={window._echDebugStateFlag ?? false} onBrushEnd={onBrushEnd as BrushEndListener} + locale={i18n.getLocale()} /> = ({ }, }, }} + locale={i18n.getLocale()} /> = ({ diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/charts/event_rate_chart/event_rate_chart.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/charts/event_rate_chart/event_rate_chart.tsx index 06d90e495ecccc..0afee34e406d7d 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/charts/event_rate_chart/event_rate_chart.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/charts/event_rate_chart/event_rate_chart.tsx @@ -17,6 +17,7 @@ import { Tooltip, } from '@elastic/charts'; import { css } from '@emotion/react'; +import { i18n } from '@kbn/i18n'; import { Axes } from '../common/axes'; import { LineChartPoint } from '../../../../common/chart_loader'; import { Anomaly } from '../../../../common/results_loader'; @@ -78,6 +79,7 @@ export const EventRateChart: FC = ({ onBrushEnd={onBrushEnd} // TODO use the EUI charts theme see src/plugins/charts/public/services/theme/README.md theme={theme} + locale={i18n.getLocale()} /> {overlayRanges && diff --git a/x-pack/plugins/ml/public/application/memory_usage/memory_tree_map/tree_map.tsx b/x-pack/plugins/ml/public/application/memory_usage/memory_tree_map/tree_map.tsx index b236e2cb33a836..0cf65ec6d09493 100644 --- a/x-pack/plugins/ml/public/application/memory_usage/memory_tree_map/tree_map.tsx +++ b/x-pack/plugins/ml/public/application/memory_usage/memory_tree_map/tree_map.tsx @@ -173,7 +173,7 @@ export const JobMemoryTreeMap: FC = ({ node, type, height }) => { {data.length ? ( - + id="memoryUsageTreeMap" data={data} diff --git a/x-pack/plugins/ml/public/application/memory_usage/nodes_overview/memory_preview_chart.tsx b/x-pack/plugins/ml/public/application/memory_usage/nodes_overview/memory_preview_chart.tsx index 91123112b3e31f..dc75907e771b2b 100644 --- a/x-pack/plugins/ml/public/application/memory_usage/nodes_overview/memory_preview_chart.tsx +++ b/x-pack/plugins/ml/public/application/memory_usage/nodes_overview/memory_preview_chart.tsx @@ -119,6 +119,7 @@ export const MemoryPreviewChart: FC = ({ memoryOverview - + diff --git a/x-pack/plugins/observability/public/embeddable/slo/overview/slo_overview.tsx b/x-pack/plugins/observability/public/embeddable/slo/overview/slo_overview.tsx index 5e8947a6c5ba9e..e190196acd794c 100644 --- a/x-pack/plugins/observability/public/embeddable/slo/overview/slo_overview.tsx +++ b/x-pack/plugins/observability/public/embeddable/slo/overview/slo_overview.tsx @@ -133,6 +133,7 @@ export function SloOverview({ sloId, sloInstanceId, lastReloadRequestTime }: Emb ) ); }} + locale={i18n.getLocale()} /> diff --git a/x-pack/plugins/observability/public/pages/overview/components/sections/apm/apm_section.tsx b/x-pack/plugins/observability/public/pages/overview/components/sections/apm/apm_section.tsx index 562d01265ac500..cfbe160590401b 100644 --- a/x-pack/plugins/observability/public/pages/overview/components/sections/apm/apm_section.tsx +++ b/x-pack/plugins/observability/public/pages/overview/components/sections/apm/apm_section.tsx @@ -150,6 +150,7 @@ export function APMSection({ bucketSize }: Props) { theme={chartTheme} showLegend={false} xDomain={{ min, max }} + locale={i18n.getLocale()} /> {series?.transactions.coordinates && ( <> diff --git a/x-pack/plugins/observability/public/pages/overview/components/sections/logs/logs_section.tsx b/x-pack/plugins/observability/public/pages/overview/components/sections/logs/logs_section.tsx index 55363e7272a1b3..4097fbcb5bb877 100644 --- a/x-pack/plugins/observability/public/pages/overview/components/sections/logs/logs_section.tsx +++ b/x-pack/plugins/observability/public/pages/overview/components/sections/logs/logs_section.tsx @@ -143,6 +143,7 @@ export function LogsSection({ bucketSize }: Props) { legendPosition={Position.Right} xDomain={{ min, max }} showLegendExtra + locale={i18n.getLocale()} /> {series && Object.keys(series).map((key) => { diff --git a/x-pack/plugins/observability/public/pages/overview/components/sections/metrics/metric_with_sparkline.tsx b/x-pack/plugins/observability/public/pages/overview/components/sections/metrics/metric_with_sparkline.tsx index ede1c025440b7e..56e518e835c43b 100644 --- a/x-pack/plugins/observability/public/pages/overview/components/sections/metrics/metric_with_sparkline.tsx +++ b/x-pack/plugins/observability/public/pages/overview/components/sections/metrics/metric_with_sparkline.tsx @@ -15,6 +15,7 @@ import { } from '@elastic/eui/dist/eui_charts_theme'; import { ThemeContext } from 'styled-components'; +import { i18n } from '@kbn/i18n'; import { NumberOrNull } from '../../../../..'; interface Props { @@ -47,7 +48,7 @@ export function MetricWithSparkline({ id, formatter, value, timeseries, color }: - + } + locale={i18n.getLocale()} /> {} }]} diff --git a/x-pack/plugins/profiling/public/components/stacked_bar_chart/index.tsx b/x-pack/plugins/profiling/public/components/stacked_bar_chart/index.tsx index a8031583535f0d..55892be80b31f8 100644 --- a/x-pack/plugins/profiling/public/components/stacked_bar_chart/index.tsx +++ b/x-pack/plugins/profiling/public/components/stacked_bar_chart/index.tsx @@ -21,6 +21,7 @@ import { import { EuiPanel } from '@elastic/eui'; import { keyBy } from 'lodash'; import React, { useMemo, useState } from 'react'; +import { i18n } from '@kbn/i18n'; import { TopNSample, TopNSubchart } from '../../../common/topn'; import { useKibanaTimeZoneSetting } from '../../hooks/use_kibana_timezone_setting'; import { useProfilingChartsTheme } from '../../hooks/use_profiling_charts_theme'; @@ -120,6 +121,7 @@ export function StackedBarChart({ onElementOut={() => { setHighlightedSample(undefined); }} + locale={i18n.getLocale()} /> {charts.map((chart) => ( diff --git a/x-pack/plugins/profiling/public/components/subchart.tsx b/x-pack/plugins/profiling/public/components/subchart.tsx index 9100af82d1f4bb..dbb3db5caa3438 100644 --- a/x-pack/plugins/profiling/public/components/subchart.tsx +++ b/x-pack/plugins/profiling/public/components/subchart.tsx @@ -220,7 +220,12 @@ export function SubChart({ - + = ({ showLegend={false} theme={[treemapTheme, theme]} onElementClick={onElementClick} + locale={i18n.getLocale()} /> - + {data.map((series) => { const barSeriesKey = series.key; return checkIfAllTheDataInTheSeriesAreValid(series) ? ( diff --git a/x-pack/plugins/security_solution/public/common/components/charts/donutchart.tsx b/x-pack/plugins/security_solution/public/common/components/charts/donutchart.tsx index c41a5a0e93b102..b5befa16d3e2ba 100644 --- a/x-pack/plugins/security_solution/public/common/components/charts/donutchart.tsx +++ b/x-pack/plugins/security_solution/public/common/components/charts/donutchart.tsx @@ -21,6 +21,7 @@ import { isEmpty } from 'lodash'; import type { FlattenSimpleInterpolation } from 'styled-components'; import styled from 'styled-components'; +import { i18n } from '@kbn/i18n'; import { useThemes } from './common'; import { DraggableLegend } from './draggable_legend'; import type { LegendItem } from './draggable_legend_item'; @@ -199,6 +200,7 @@ export const DonutChart = ({ theme={[donutTheme, theme]} baseTheme={baseTheme} onElementClick={onElementClicked} + locale={i18n.getLocale()} /> ( showLegendExtra={showLegend} theme={theme} baseTheme={baseTheme} + locale={i18n.getLocale()} /> diff --git a/x-pack/plugins/security_solution/public/explore/components/risk_score/risk_score_over_time/index.tsx b/x-pack/plugins/security_solution/public/explore/components/risk_score/risk_score_over_time/index.tsx index 7a5170d20235a3..96381b3681c8b6 100644 --- a/x-pack/plugins/security_solution/public/explore/components/risk_score/risk_score_over_time/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/components/risk_score/risk_score_over_time/index.tsx @@ -21,12 +21,13 @@ import { import { EuiFlexGroup, EuiFlexItem, EuiLoadingChart, EuiText, EuiPanel } from '@elastic/eui'; import styled from 'styled-components'; import { euiThemeVars } from '@kbn/ui-theme'; +import { i18n } from '@kbn/i18n'; import { chartDefaultSettings, useThemes } from '../../../../common/components/charts/common'; import { useTimeZone } from '../../../../common/lib/kibana'; import { histogramDateTimeFormatter } from '../../../../common/components/utils'; import { HeaderSection } from '../../../../common/components/header_section'; import { InspectButton, InspectButtonContainer } from '../../../../common/components/inspect'; -import * as i18n from './translations'; +import * as translations from './translations'; import { PreferenceFormattedDate } from '../../../../common/components/formatted_date'; import type { HostRiskScore, @@ -145,7 +146,12 @@ const RiskScoreOverTimeComponent: React.FC = ({ ) : ( - + = ({ /> = ({ { dataValue: RISKY_THRESHOLD, details: `${RISKY_THRESHOLD}`, - header: i18n.RISK_THRESHOLD, + header: translations.RISK_THRESHOLD, }, ]} markerPosition="left" @@ -205,7 +211,7 @@ const RiskScoreOverTimeComponent: React.FC = ({ }} marker={ - {i18n.RISKY} + {translations.RISKY} } /> diff --git a/x-pack/plugins/stack_alerts/public/rule_types/threshold/visualization.tsx b/x-pack/plugins/stack_alerts/public/rule_types/threshold/visualization.tsx index d5c2d333222320..c16d3dd0bdb55c 100644 --- a/x-pack/plugins/stack_alerts/public/rule_types/threshold/visualization.tsx +++ b/x-pack/plugins/stack_alerts/public/rule_types/threshold/visualization.tsx @@ -34,6 +34,7 @@ import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { AggregationType, Comparator } from '@kbn/triggers-actions-ui-plugin/public'; import { parseDuration } from '@kbn/alerting-plugin/common/parse_duration'; +import { i18n } from '@kbn/i18n'; import { getThresholdRuleVisualizationData, GetThresholdRuleVisualizationDataParams, @@ -270,6 +271,7 @@ export const ThresholdVisualization: React.FunctionComponent = ({ showLegend={!!termField} showLegendExtra legendPosition={Position.Bottom} + locale={i18n.getLocale()} /> { onBrushed?.(getBrushData(brushArea)); }} + locale={i18n.getLocale()} /> { - + = ({ legendPosition={Position.Right} legendSize={DEFAULT_LEGEND_SIZE} legendAction={({ label }) => } + locale={i18n.getLocale()} /> - + = ({ line: { stroke: lightEuiTheme.euiColorAccent }, }, }} + locale={i18n.getLocale()} /> { = ({ showLegend={false} onBrushEnd={onBrushEnd} onElementClick={onBarClicked} + locale={i18n.getLocale()} {...chartTheme} /> - + { showLegend={!!watch.termField} showLegendExtra legendPosition={Position.Bottom} + locale={i18n.getLocale()} /> Date: Tue, 17 Oct 2023 13:02:30 +0200 Subject: [PATCH 44/87] [ML] Fix the model state column in the Trained Models UI (#169068) ## Summary Fixes an issue when the `Ready to deploy` download state was overriding the `starting` and `stopping` deployment states. --- .../ml/public/application/model_management/models_list.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/application/model_management/models_list.tsx b/x-pack/plugins/ml/public/application/model_management/models_list.tsx index c0249947ae16f9..af9b9ba3015e73 100644 --- a/x-pack/plugins/ml/public/application/model_management/models_list.tsx +++ b/x-pack/plugins/ml/public/application/model_management/models_list.tsx @@ -35,6 +35,7 @@ import { BUILT_IN_MODEL_TAG, BUILT_IN_MODEL_TYPE, DEPLOYMENT_STATE, + DeploymentState, ELASTIC_MODEL_DEFINITIONS, ELASTIC_MODEL_TAG, ELASTIC_MODEL_TYPE, @@ -349,7 +350,7 @@ export const ModelsList: FC = ({ ); if (elasticModels.length > 0) { for (const model of elasticModels) { - if (model.state === MODEL_STATE.STARTED) { + if (Object.values(DEPLOYMENT_STATE).includes(model.state as DeploymentState)) { // no need to check for the download status if the model has been deployed continue; } From 24c008b4c5026dd543f1b4aded94f3787bce5fb0 Mon Sep 17 00:00:00 2001 From: Juan Pablo Djeredjian Date: Tue, 17 Oct 2023 13:05:49 +0200 Subject: [PATCH 45/87] [Security Solution] Install/Update Prebuilt Rules Test Implementation refactor (#165488) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/elastic/kibana/issues/148192 (Tick the two open checkboxes in that issue when merging this PR) ## Summary This PR rewrites/refactors Cypress tests for the Installation and Upgrade of Prebuilt Rules implemented in https://github.com/elastic/kibana/pull/161687. Most of the changes here address feedback received in that PR - answered those comments there. - RBAC/Authorization: adds tests scenarios for users with full privileges (happy path) - Gets rid of huge util helpers such as `assertRuleAvailableForInstallAndInstallOne` and rewrites test cases in a more descriptive way, with step by step actions. - Gets rid of complex logic in tests and their helpers - removing if/else logic within them and removing optional flags passed to helpers. - Fixes `bulkCreateRuleAssets` util and uses it in other helpers to install multiple `security-rule` assets with a single bulk request to ES. Additionally: checked `installation_and_upgrade.md` test plan to make sure it matches with the test in place. Added [link](https://github.com/elastic/kibana/issues/166215) to a ticket for a to-do task for the sections: - Rule installation workflow: filtering, sorting, pagination - Rule upgrade workflow: filtering, sorting, pagination ## Flaky test runner ~~https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/3420~~ ~~🟢~~ https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/3513 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../installation_and_upgrade.md | 4 +- .../use_add_prebuilt_rules_table_columns.tsx | 10 +- ...e_upgrade_prebuilt_rules_table_columns.tsx | 10 +- ...t_rules_install_update_authorization.cy.ts | 132 +++++++--- ..._rules_install_update_error_handling.cy.ts | 138 ++++++---- ...built_rules_install_update_workflows.cy.ts | 126 +++++---- .../prebuilt_rules_management.cy.ts | 2 +- .../prebuilt_rules_notifications.cy.ts | 18 +- .../bulk_actions/bulk_edit_rules.cy.ts | 6 +- .../bulk_edit_rules_actions.cy.ts | 2 +- .../import_export/export_rule.cy.ts | 6 +- .../rules_table/rules_table_selection.cy.ts | 2 +- .../cypress/screens/alerts_detection_rules.ts | 12 +- .../cypress/tasks/api_calls/prebuilt_rules.ts | 99 +++---- .../cypress/tasks/common.ts | 1 + .../cypress/tasks/prebuilt_rules.ts | 242 ++++++------------ .../security_solution_cypress/package.json | 60 ++--- 17 files changed, 468 insertions(+), 402 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md b/x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md index 09198dd2d9ef8f..b8ae0c85c82e62 100644 --- a/x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md +++ b/x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md @@ -431,7 +431,7 @@ And user should see a CTA that leads to the Rule Management page ### Rule installation workflow: filtering, sorting, pagination -TODO: add scenarios +TODO: add scenarios https://github.com/elastic/kibana/issues/166215 ### Rule installation workflow: misc cases @@ -515,7 +515,7 @@ And user should NOT see the Rule Updates table ### Rule upgrade workflow: filtering, sorting, pagination -TODO: add scenarios +TODO: add scenarios https://github.com/elastic/kibana/issues/166215 ### Rule upgrade workflow: misc cases diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/add_prebuilt_rules_table/use_add_prebuilt_rules_table_columns.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/add_prebuilt_rules_table/use_add_prebuilt_rules_table_columns.tsx index 275dc1276cb5ae..4376014ab110e5 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/add_prebuilt_rules_table/use_add_prebuilt_rules_table_columns.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/add_prebuilt_rules_table/use_add_prebuilt_rules_table_columns.tsx @@ -42,6 +42,7 @@ const RuleName = ({ name, ruleId }: RuleNameProps) => { onClick={() => { openRulePreview(ruleId); }} + data-test-subj="ruleName" > {name} @@ -121,7 +122,14 @@ const createInstallButtonColumn = ( onClick={() => installOneRule(ruleId)} data-test-subj={`installSinglePrebuiltRuleButton-${ruleId}`} > - {isRuleInstalling ? : i18n.INSTALL_RULE_BUTTON} + {isRuleInstalling ? ( + + ) : ( + i18n.INSTALL_RULE_BUTTON + )} ); }, diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_prebuilt_rules_table_columns.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_prebuilt_rules_table_columns.tsx index 054d77cb5e4412..3f72208dc51bf3 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_prebuilt_rules_table_columns.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/upgrade_prebuilt_rules_table/use_upgrade_prebuilt_rules_table_columns.tsx @@ -40,6 +40,7 @@ const RuleName = ({ name, ruleId }: RuleNameProps) => { onClick={() => { openRulePreview(ruleId); }} + data-test-subj="ruleName" > {name} @@ -120,7 +121,14 @@ const createUpgradeButtonColumn = ( onClick={() => upgradeOneRule(ruleId)} data-test-subj={`upgradeSinglePrebuiltRuleButton-${ruleId}`} > - {isRuleUpgrading ? : i18n.UPDATE_RULE_BUTTON} + {isRuleUpgrading ? ( + + ) : ( + i18n.UPDATE_RULE_BUTTON + )} ); }, diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_authorization.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_authorization.cy.ts index 63e1aa776cd07a..f95a4274a5181c 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_authorization.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_authorization.cy.ts @@ -13,23 +13,30 @@ import { import { ROLES } from '@kbn/security-solution-plugin/common/test'; import { createRuleAssetSavedObject } from '../../../helpers/rules'; -import { createAndInstallMockedPrebuiltRules } from '../../../tasks/api_calls/prebuilt_rules'; -import { resetRulesTableState, deleteAlertsAndRules } from '../../../tasks/common'; -import { login } from '../../../tasks/login'; +import { + createAndInstallMockedPrebuiltRules, + installPrebuiltRuleAssets, + preventPrebuiltRulesPackageInstallation, +} from '../../../tasks/api_calls/prebuilt_rules'; import { visit } from '../../../tasks/navigation'; import { RULES_MANAGEMENT_URL } from '../../../urls/rules_management'; import { ADD_ELASTIC_RULES_BTN, getInstallSingleRuleButtonByRuleId, getUpgradeSingleRuleButtonByRuleId, + GO_BACK_TO_RULES_TABLE_BUTTON, INSTALL_ALL_RULES_BUTTON, + RULES_MANAGEMENT_TAB, + RULES_MANAGEMENT_TABLE, RULES_UPDATES_TAB, RULE_CHECKBOX, UPGRADE_ALL_RULES_BUTTON, } from '../../../screens/alerts_detection_rules'; +import { cleanKibana } from '../../../tasks/common'; +import { login } from '../../../tasks/login'; +// Rule to test update const RULE_1_ID = 'rule_1'; -const RULE_2_ID = 'rule_2'; const OUTDATED_RULE_1 = createRuleAssetSavedObject({ name: 'Outdated rule 1', rule_id: RULE_1_ID, @@ -40,22 +47,25 @@ const UPDATED_RULE_1 = createRuleAssetSavedObject({ rule_id: RULE_1_ID, version: 2, }); -const OUTDATED_RULE_2 = createRuleAssetSavedObject({ - name: 'Outdated rule 2', + +// Rule to test installation +const RULE_2_ID = 'rule_2'; +const RULE_2 = createRuleAssetSavedObject({ + name: 'Rule 2', rule_id: RULE_2_ID, version: 1, }); -const UPDATED_RULE_2 = createRuleAssetSavedObject({ - name: 'Updated rule 2', - rule_id: RULE_2_ID, - version: 2, -}); const loadPageAsReadOnlyUser = (url: string) => { login(ROLES.reader); visit(url, { role: ROLES.reader }); }; +const loginPageAsWriteAuthorizedUser = (url: string) => { + login(ROLES.hunter); + visit(url); +}; + // TODO: https://github.com/elastic/kibana/issues/164451 We should find a way to make this spec work in Serverless // TODO: https://github.com/elastic/kibana/issues/161540 describe( @@ -63,29 +73,18 @@ describe( { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => { beforeEach(() => { - login(); - resetRulesTableState(); - deleteAlertsAndRules(); - cy.task('esArchiverResetKibana'); - createAndInstallMockedPrebuiltRules({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] }); + preventPrebuiltRulesPackageInstallation(); + cleanKibana(); }); describe('User with read privileges on Security Solution', () => { - const RULE_1 = createRuleAssetSavedObject({ - name: 'Test rule 1', - rule_id: 'rule_1', - }); - const RULE_2 = createRuleAssetSavedObject({ - name: 'Test rule 2', - rule_id: 'rule_2', - }); - beforeEach(() => { + it('should not be able to install prebuilt rules', () => { + // Install one prebuilt rule asset to assert that user can't install it + installPrebuiltRuleAssets([RULE_2]); + // Now login with read-only user in preparation for test - createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2], installToKibana: false }); loadPageAsReadOnlyUser(RULES_MANAGEMENT_URL); - }); - it('should not be able to install prebuilt rules', () => { // Check that Add Elastic Rules button is disabled cy.get(ADD_ELASTIC_RULES_BTN).should('be.disabled'); @@ -94,25 +93,21 @@ describe( // installation buttons are disabled cy.visit(`${APP_PATH}${RULES_ADD_PATH}`); cy.get(INSTALL_ALL_RULES_BUTTON).should('be.disabled'); - cy.get(getInstallSingleRuleButtonByRuleId(RULE_1['security-rule'].rule_id)).should( + cy.get(getInstallSingleRuleButtonByRuleId(UPDATED_RULE_1['security-rule'].rule_id)).should( 'not.exist' ); cy.get(RULE_CHECKBOX).should('not.exist'); }); - }); - describe('User with read privileges on Security Solution', () => { - beforeEach(() => { - /* Create a second version of the rule, making it available for update */ - createAndInstallMockedPrebuiltRules({ - rules: [UPDATED_RULE_1, UPDATED_RULE_2], - installToKibana: false, - }); + it('should not be able to upgrade prebuilt rules', () => { + // Install one prebuilt rule asset to assert that user can't upgrade it + createAndInstallMockedPrebuiltRules([OUTDATED_RULE_1]); + // Create a new version of the rule to make it available for upgrade + installPrebuiltRuleAssets([UPDATED_RULE_1]); + // Now login with read-only user in preparation for test loadPageAsReadOnlyUser(RULES_MANAGEMENT_URL); - }); - it('should not be able to upgrade prebuilt rules', () => { // Check that Rule Update tab is not shown cy.get(RULES_UPDATES_TAB).should('not.exist'); @@ -121,11 +116,70 @@ describe( // upgrade buttons are disabled cy.visit(`${APP_PATH}${RULES_UPDATES}`); cy.get(UPGRADE_ALL_RULES_BUTTON).should('be.disabled'); + + // Upgrade button and selection checkbox should not be visible cy.get(getUpgradeSingleRuleButtonByRuleId(OUTDATED_RULE_1['security-rule'].rule_id)).should( 'not.exist' ); cy.get(RULE_CHECKBOX).should('not.exist'); }); }); + + describe('User with write privileges on Security Solution', () => { + it('should be able to install prebuilt rules', () => { + // Install one prebuilt rule asset to assert that user can install it + installPrebuiltRuleAssets([RULE_2]); + loginPageAsWriteAuthorizedUser(RULES_MANAGEMENT_URL); + + // Check that Add Elastic Rules button is enabled + cy.get(ADD_ELASTIC_RULES_BTN).should('not.be.disabled'); + + // Navigate to Add Elastic Rules page and assert that rules can be selected + // and all installation buttons are enabled + cy.get(ADD_ELASTIC_RULES_BTN).click(); + cy.get(INSTALL_ALL_RULES_BUTTON).should('not.be.disabled'); + cy.get(getInstallSingleRuleButtonByRuleId(RULE_2['security-rule'].rule_id)).should('exist'); + cy.get(RULE_CHECKBOX).should('exist'); + + // Install all available prebuilt rules + cy.get(INSTALL_ALL_RULES_BUTTON).click(); + + // Rule shouldn't be available for installation anymore + cy.get(getInstallSingleRuleButtonByRuleId(RULE_2['security-rule'].rule_id)).should( + 'not.exist' + ); + + // Navigate back to rules table and assert rule is installed + cy.get(GO_BACK_TO_RULES_TABLE_BUTTON).click(); + cy.get(RULES_MANAGEMENT_TABLE).contains(RULE_2['security-rule'].name); + }); + + it('should be able to upgrade prebuilt rules', () => { + // Install one prebuilt rule asset to assert that user can upgrade it + createAndInstallMockedPrebuiltRules([OUTDATED_RULE_1]); + // Create a new version of the rule to make it available for upgrade + installPrebuiltRuleAssets([UPDATED_RULE_1]); + loginPageAsWriteAuthorizedUser(RULES_MANAGEMENT_URL); + + // Check that Rule Update tab is shown + cy.get(RULES_UPDATES_TAB).should('exist'); + + // Navigate to Rule Update tab and assert that rules can be selected + // and all upgrade buttons are enabled + cy.get(RULES_UPDATES_TAB).click(); + cy.get(UPGRADE_ALL_RULES_BUTTON).should('not.be.disabled'); + cy.get(RULE_CHECKBOX).should('exist'); + cy.get(getUpgradeSingleRuleButtonByRuleId(OUTDATED_RULE_1['security-rule'].rule_id)).should( + 'exist' + ); + + // Upgrade the rule and assert that it's upgraded + cy.get( + getUpgradeSingleRuleButtonByRuleId(OUTDATED_RULE_1['security-rule'].rule_id) + ).click(); + cy.get(RULES_MANAGEMENT_TAB).click(); + cy.get(RULES_MANAGEMENT_TABLE).contains(UPDATED_RULE_1['security-rule'].name); + }); + }); } ); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_error_handling.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_error_handling.cy.ts index a0004572f86085..effb732489849e 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_error_handling.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_error_handling.cy.ts @@ -6,20 +6,32 @@ */ import { createRuleAssetSavedObject } from '../../../helpers/rules'; -import { createAndInstallMockedPrebuiltRules } from '../../../tasks/api_calls/prebuilt_rules'; -import { resetRulesTableState, deleteAlertsAndRules } from '../../../tasks/common'; +import { + getInstallSingleRuleButtonByRuleId, + getUpgradeSingleRuleButtonByRuleId, + INSTALL_ALL_RULES_BUTTON, + INSTALL_SELECTED_RULES_BUTTON, + SELECT_ALL_RULES_ON_PAGE_CHECKBOX, + UPGRADE_ALL_RULES_BUTTON, + UPGRADE_SELECTED_RULES_BUTTON, +} from '../../../screens/alerts_detection_rules'; +import { selectRulesByName } from '../../../tasks/alerts_detection_rules'; +import { + installPrebuiltRuleAssets, + createAndInstallMockedPrebuiltRules, + preventPrebuiltRulesPackageInstallation, +} from '../../../tasks/api_calls/prebuilt_rules'; +import { cleanKibana } from '../../../tasks/common'; import { login } from '../../../tasks/login'; import { addElasticRulesButtonClick, - assertRuleAvailableForInstallAndInstallOne, - assertRuleAvailableForInstallAndInstallSelected, - assertRuleAvailableForInstallAndInstallAllInPage, - assertRuleAvailableForInstallAndInstallAll, - assertRuleUpgradeAvailableAndUpgradeOne, - assertRuleUpgradeAvailableAndUpgradeSelected, - assertRuleUpgradeAvailableAndUpgradeAllInPage, - assertRuleUpgradeAvailableAndUpgradeAll, + assertInstallationRequestIsComplete, + interceptInstallationRequestToFail, + interceptUpgradeRequestToFail, + assertUpgradeFailure, ruleUpdatesTabClick, + assertInstallationFailure, + assertUpgradeRequestIsComplete, } from '../../../tasks/prebuilt_rules'; import { visitRulesManagementTable } from '../../../tasks/rules_management'; @@ -28,10 +40,9 @@ describe( { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { + preventPrebuiltRulesPackageInstallation(); + cleanKibana(); login(); - resetRulesTableState(); - deleteAlertsAndRules(); - cy.task('esArchiverResetKibana'); visitRulesManagementTable(); }); @@ -45,37 +56,52 @@ describe( name: 'Test rule 2', rule_id: 'rule_2', }); + beforeEach(() => { - createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2], installToKibana: false }); + // Make two mock rules available for installation + installPrebuiltRuleAssets([RULE_1, RULE_2]); }); it('installing prebuilt rules one by one', () => { + // Navigate to install Elastic rules page addElasticRulesButtonClick(); - assertRuleAvailableForInstallAndInstallOne({ rules: [RULE_1], didRequestFail: true }); + + // Intercept and force the installation request to fail + interceptInstallationRequestToFail([RULE_1]); + + // Attempt to install rule + cy.get(getInstallSingleRuleButtonByRuleId(RULE_1['security-rule'].rule_id)).click(); + // Wait for request to complete + assertInstallationRequestIsComplete([RULE_1]); + + assertInstallationFailure([RULE_1]); }); it('installing multiple selected prebuilt rules by selecting them individually', () => { addElasticRulesButtonClick(); - assertRuleAvailableForInstallAndInstallSelected({ - rules: [RULE_1, RULE_2], - didRequestFail: true, - }); + + interceptInstallationRequestToFail([RULE_1, RULE_2]); + selectRulesByName([RULE_1['security-rule'].name, RULE_2['security-rule'].name]); + cy.get(INSTALL_SELECTED_RULES_BUTTON).click(); + assertInstallationRequestIsComplete([RULE_1, RULE_2]); + assertInstallationFailure([RULE_1, RULE_2]); }); it('installing multiple selected prebuilt rules by selecting all in page', () => { addElasticRulesButtonClick(); - assertRuleAvailableForInstallAndInstallAllInPage({ - rules: [RULE_1, RULE_2], - didRequestFail: true, - }); + interceptInstallationRequestToFail([RULE_1, RULE_2]); + cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click(); + cy.get(INSTALL_SELECTED_RULES_BUTTON).click(); + assertInstallationRequestIsComplete([RULE_1, RULE_2]); + assertInstallationFailure([RULE_1, RULE_2]); }); it('installing all available rules at once', () => { addElasticRulesButtonClick(); - assertRuleAvailableForInstallAndInstallAll({ - rules: [RULE_1, RULE_2], - didRequestFail: true, - }); + interceptInstallationRequestToFail([RULE_1, RULE_2]); + cy.get(INSTALL_ALL_RULES_BUTTON).click(); + assertInstallationRequestIsComplete([RULE_1, RULE_2]); + assertInstallationFailure([RULE_1, RULE_2]); }); }); @@ -102,44 +128,66 @@ describe( rule_id: RULE_2_ID, version: 2, }); + beforeEach(() => { /* Create a new rule and install it */ - createAndInstallMockedPrebuiltRules({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] }); + createAndInstallMockedPrebuiltRules([OUTDATED_RULE_1, OUTDATED_RULE_2]); /* Create a second version of the rule, making it available for update */ - createAndInstallMockedPrebuiltRules({ - rules: [UPDATED_RULE_1, UPDATED_RULE_2], - installToKibana: false, - }); + installPrebuiltRuleAssets([UPDATED_RULE_1, UPDATED_RULE_2]); cy.reload(); }); it('upgrading prebuilt rules one by one', () => { + interceptUpgradeRequestToFail([OUTDATED_RULE_1]); + + // Navigate to Rule Upgrade table ruleUpdatesTabClick(); - assertRuleUpgradeAvailableAndUpgradeOne({ rules: [OUTDATED_RULE_1], didRequestFail: true }); + + // Attempt to upgrade rule + cy.get( + getUpgradeSingleRuleButtonByRuleId(OUTDATED_RULE_1['security-rule'].rule_id) + ).click(); + // Wait for request to complete + assertUpgradeRequestIsComplete([OUTDATED_RULE_1]); + + assertUpgradeFailure([OUTDATED_RULE_1]); }); it('upgrading multiple selected prebuilt rules by selecting them individually', () => { + interceptUpgradeRequestToFail([OUTDATED_RULE_1, OUTDATED_RULE_2]); + + // Navigate to Rule Upgrade table ruleUpdatesTabClick(); - assertRuleUpgradeAvailableAndUpgradeSelected({ - rules: [OUTDATED_RULE_1, OUTDATED_RULE_2], - didRequestFail: true, - }); + + selectRulesByName([ + OUTDATED_RULE_1['security-rule'].name, + OUTDATED_RULE_2['security-rule'].name, + ]); + cy.get(UPGRADE_SELECTED_RULES_BUTTON).click(); + assertUpgradeRequestIsComplete([OUTDATED_RULE_1, OUTDATED_RULE_2]); + assertUpgradeFailure([OUTDATED_RULE_1, OUTDATED_RULE_2]); }); it('upgrading multiple selected prebuilt rules by selecting all in page', () => { + interceptUpgradeRequestToFail([OUTDATED_RULE_1, OUTDATED_RULE_2]); + + // Navigate to Rule Upgrade table ruleUpdatesTabClick(); - assertRuleUpgradeAvailableAndUpgradeAllInPage({ - rules: [OUTDATED_RULE_1, OUTDATED_RULE_2], - didRequestFail: true, - }); + cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click(); + cy.get(UPGRADE_SELECTED_RULES_BUTTON).click(); + assertUpgradeRequestIsComplete([OUTDATED_RULE_1, OUTDATED_RULE_2]); + assertUpgradeFailure([OUTDATED_RULE_1, OUTDATED_RULE_2]); }); it('upgrading all rules with available upgrades at once', () => { + interceptUpgradeRequestToFail([OUTDATED_RULE_1, OUTDATED_RULE_2]); + + // Navigate to Rule Upgrade table ruleUpdatesTabClick(); - assertRuleUpgradeAvailableAndUpgradeAll({ - rules: [OUTDATED_RULE_1, OUTDATED_RULE_2], - didRequestFail: true, - }); + + cy.get(UPGRADE_ALL_RULES_BUTTON).click(); + assertUpgradeRequestIsComplete([OUTDATED_RULE_1, OUTDATED_RULE_2]); + assertUpgradeFailure([OUTDATED_RULE_1, OUTDATED_RULE_2]); }); }); } diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_workflows.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_workflows.cy.ts index 5c8ff2a4d49638..68830ff0611a8b 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_workflows.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_workflows.cy.ts @@ -10,33 +10,35 @@ import type { Rule } from '@kbn/security-solution-plugin/public/detection_engine import { createRuleAssetSavedObject } from '../../../helpers/rules'; import { + getInstallSingleRuleButtonByRuleId, + getUpgradeSingleRuleButtonByRuleId, GO_BACK_TO_RULES_TABLE_BUTTON, INSTALL_ALL_RULES_BUTTON, INSTALL_SELECTED_RULES_BUTTON, - NO_RULES_AVAILABLE_FOR_INSTALL_MESSSAGE, - NO_RULES_AVAILABLE_FOR_UPGRADE_MESSSAGE, + NO_RULES_AVAILABLE_FOR_INSTALL_MESSAGE, + NO_RULES_AVAILABLE_FOR_UPGRADE_MESSAGE, RULES_UPDATES_TAB, RULE_CHECKBOX, SELECT_ALL_RULES_ON_PAGE_CHECKBOX, TOASTER, + UPGRADE_ALL_RULES_BUTTON, + UPGRADE_SELECTED_RULES_BUTTON, } from '../../../screens/alerts_detection_rules'; +import { selectRulesByName } from '../../../tasks/alerts_detection_rules'; import { getRuleAssets, + installPrebuiltRuleAssets, createAndInstallMockedPrebuiltRules, } from '../../../tasks/api_calls/prebuilt_rules'; import { resetRulesTableState, deleteAlertsAndRules } from '../../../tasks/common'; import { login } from '../../../tasks/login'; import { addElasticRulesButtonClick, - assertRuleAvailableForInstallAndInstallOne, - assertRuleAvailableForInstallAndInstallSelected, - assertRuleAvailableForInstallAndInstallAllInPage, - assertRuleAvailableForInstallAndInstallAll, - assertRuleUpgradeAvailableAndUpgradeOne, - assertRuleUpgradeAvailableAndUpgradeSelected, - assertRuleUpgradeAvailableAndUpgradeAllInPage, - assertRuleUpgradeAvailableAndUpgradeAll, ruleUpdatesTabClick, + assertInstallationSuccess, + assertInstallationRequestIsComplete, + assertUpgradeRequestIsComplete, + assertUpgradeSuccess, } from '../../../tasks/prebuilt_rules'; import { visitRulesManagementTable } from '../../../tasks/rules_management'; @@ -99,11 +101,17 @@ describe( }); it('should install rules from the Fleet package when user clicks on CTA', () => { + interface Response { + body: { + hits: { + hits: Array<{ _source: { ['security-rule']: Rule } }>; + }; + }; + } const getRulesAndAssertNumberInstalled = () => { getRuleAssets().then((response) => { - const ruleIds = response.body.hits.hits.map( - (hit: { _source: { ['security-rule']: Rule } }) => - hit._source['security-rule'].rule_id + const ruleIds = (response as Response).body.hits.hits.map( + (hit) => hit._source['security-rule'].rule_id ); const numberOfRulesToInstall = new Set(ruleIds).size; @@ -147,52 +155,49 @@ describe( rule_id: 'rule_2', }); beforeEach(() => { - createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2], installToKibana: false }); + installPrebuiltRuleAssets([RULE_1, RULE_2]); cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/installation/_perform').as( 'installPrebuiltRules' ); + addElasticRulesButtonClick(); }); it('should install prebuilt rules one by one', () => { - addElasticRulesButtonClick(); - assertRuleAvailableForInstallAndInstallOne({ rules: [RULE_1] }); + // Attempt to install rules + cy.get(getInstallSingleRuleButtonByRuleId(RULE_1['security-rule'].rule_id)).click(); + // Wait for request to complete + assertInstallationRequestIsComplete([RULE_1]); + // Assert installation succeeded + assertInstallationSuccess([RULE_1]); }); it('should install multiple selected prebuilt rules by selecting them individually', () => { - addElasticRulesButtonClick(); - assertRuleAvailableForInstallAndInstallSelected({ rules: [RULE_1, RULE_2] }); + selectRulesByName([RULE_1['security-rule'].name, RULE_2['security-rule'].name]); + cy.get(INSTALL_SELECTED_RULES_BUTTON).click(); + assertInstallationRequestIsComplete([RULE_1, RULE_2]); + assertInstallationSuccess([RULE_1, RULE_2]); }); it('should install multiple selected prebuilt rules by selecting all in page', () => { - addElasticRulesButtonClick(); - assertRuleAvailableForInstallAndInstallAllInPage({ rules: [RULE_1, RULE_2] }); + cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click(); + cy.get(INSTALL_SELECTED_RULES_BUTTON).click(); + assertInstallationRequestIsComplete([RULE_1, RULE_2]); + assertInstallationSuccess([RULE_1, RULE_2]); }); it('should install all available rules at once', () => { - addElasticRulesButtonClick(); - assertRuleAvailableForInstallAndInstallAll({ rules: [RULE_1, RULE_2] }); + cy.get(INSTALL_ALL_RULES_BUTTON).click(); + assertInstallationRequestIsComplete([RULE_1, RULE_2]); + assertInstallationSuccess([RULE_1, RULE_2]); }); it('should display an empty screen when all available prebuilt rules have been installed', () => { - addElasticRulesButtonClick(); cy.get(INSTALL_ALL_RULES_BUTTON).click(); cy.get(TOASTER).should('be.visible').should('have.text', `2 rules installed successfully.`); cy.get(RULE_CHECKBOX).should('not.exist'); - cy.get(NO_RULES_AVAILABLE_FOR_INSTALL_MESSSAGE).should('exist'); + cy.get(NO_RULES_AVAILABLE_FOR_INSTALL_MESSAGE).should('exist'); cy.get(GO_BACK_TO_RULES_TABLE_BUTTON).should('exist'); }); - - it('should fail gracefully with toast error message when request to install rules fails', () => { - /* Stub request to force rules installation to fail */ - cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/installation/_perform', { - statusCode: 500, - }).as('installPrebuiltRules'); - addElasticRulesButtonClick(); - cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click(); - cy.get(INSTALL_SELECTED_RULES_BUTTON).click(); - cy.wait('@installPrebuiltRules'); - cy.get(TOASTER).should('be.visible').should('have.text', 'Rule installation failed'); - }); }); describe('Upgrade of prebuilt rules', () => { @@ -223,43 +228,52 @@ describe( 'updatePrebuiltRules' ); /* Create a new rule and install it */ - createAndInstallMockedPrebuiltRules({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] }); + createAndInstallMockedPrebuiltRules([OUTDATED_RULE_1, OUTDATED_RULE_2]); /* Create a second version of the rule, making it available for update */ - createAndInstallMockedPrebuiltRules({ - rules: [UPDATED_RULE_1, UPDATED_RULE_2], - installToKibana: false, - }); - cy.reload(); + installPrebuiltRuleAssets([UPDATED_RULE_1, UPDATED_RULE_2]); + + visitRulesManagementTable(); + ruleUpdatesTabClick(); }); it('should upgrade prebuilt rules one by one', () => { - ruleUpdatesTabClick(); - assertRuleUpgradeAvailableAndUpgradeOne({ rules: [OUTDATED_RULE_1] }); + // Attempt to upgrade rule + cy.get( + getUpgradeSingleRuleButtonByRuleId(OUTDATED_RULE_1['security-rule'].rule_id) + ).click(); + // Wait for request to complete + assertUpgradeRequestIsComplete([OUTDATED_RULE_1]); + + assertUpgradeSuccess([OUTDATED_RULE_1]); }); it('should upgrade multiple selected prebuilt rules by selecting them individually', () => { - ruleUpdatesTabClick(); - assertRuleUpgradeAvailableAndUpgradeSelected({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] }); + selectRulesByName([ + OUTDATED_RULE_1['security-rule'].name, + OUTDATED_RULE_2['security-rule'].name, + ]); + cy.get(UPGRADE_SELECTED_RULES_BUTTON).click(); + assertUpgradeRequestIsComplete([OUTDATED_RULE_1, OUTDATED_RULE_2]); + assertUpgradeSuccess([OUTDATED_RULE_1, OUTDATED_RULE_2]); }); it('should upgrade multiple selected prebuilt rules by selecting all in page', () => { - ruleUpdatesTabClick(); - assertRuleUpgradeAvailableAndUpgradeAllInPage({ - rules: [OUTDATED_RULE_1, OUTDATED_RULE_2], - }); + cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click(); + cy.get(UPGRADE_SELECTED_RULES_BUTTON).click(); + assertUpgradeRequestIsComplete([OUTDATED_RULE_1, OUTDATED_RULE_2]); + assertUpgradeSuccess([OUTDATED_RULE_1, OUTDATED_RULE_2]); }); it('should upgrade all rules with available upgrades at once', () => { - ruleUpdatesTabClick(); - assertRuleUpgradeAvailableAndUpgradeAll({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] }); - cy.get(RULES_UPDATES_TAB).should('not.exist'); + cy.get(UPGRADE_ALL_RULES_BUTTON).click(); + assertUpgradeRequestIsComplete([OUTDATED_RULE_1, OUTDATED_RULE_2]); + assertUpgradeSuccess([OUTDATED_RULE_1, OUTDATED_RULE_2]); }); it('should display an empty screen when all rules with available updates have been upgraded', () => { - ruleUpdatesTabClick(); - assertRuleUpgradeAvailableAndUpgradeAll({ rules: [OUTDATED_RULE_1, OUTDATED_RULE_2] }); + cy.get(UPGRADE_ALL_RULES_BUTTON).click(); cy.get(RULES_UPDATES_TAB).should('not.exist'); - cy.get(NO_RULES_AVAILABLE_FOR_UPGRADE_MESSSAGE).should('exist'); + cy.get(NO_RULES_AVAILABLE_FOR_UPGRADE_MESSAGE).should('exist'); }); }); } 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 a7ef216bf9571d..7fef8e4abbea29 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 @@ -62,7 +62,7 @@ describe('Prebuilt rules', { tags: ['@ess', '@serverless'] }, () => { deletePrebuiltRulesAssets(); preventPrebuiltRulesPackageInstallation(); visit(RULES_MANAGEMENT_URL); - createAndInstallMockedPrebuiltRules({ rules }); + createAndInstallMockedPrebuiltRules(rules); cy.reload(); waitForPrebuiltDetectionRulesToBeLoaded(); disableAutoRefresh(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_notifications.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_notifications.cy.ts index e98d6a9487c242..eef35c79d36247 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_notifications.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_notifications.cy.ts @@ -14,6 +14,7 @@ import { import { deleteFirstRule } from '../../../tasks/alerts_detection_rules'; import { installAllPrebuiltRulesRequest, + installPrebuiltRuleAssets, createAndInstallMockedPrebuiltRules, } from '../../../tasks/api_calls/prebuilt_rules'; import { @@ -54,8 +55,8 @@ describe( }); it('should NOT display install or update notifications when latest rules are installed', () => { - createAndInstallMockedPrebuiltRules({ rules: [RULE_1], installToKibana: true }); visitRulesManagementTable(); + createAndInstallMockedPrebuiltRules([RULE_1]); /* Assert that there are no installation or update notifications */ /* Add Elastic Rules button should not contain a number badge */ @@ -67,7 +68,7 @@ describe( describe('Notifications', () => { beforeEach(() => { - createAndInstallMockedPrebuiltRules({ rules: [RULE_1], installToKibana: false }); + installPrebuiltRuleAssets([RULE_1]); }); describe('Rules installation notification when no rules have been installed', () => { @@ -96,11 +97,8 @@ describe( rule_id: 'rule_3', }); - createAndInstallMockedPrebuiltRules({ - rules: [RULE_2, RULE_3], - installToKibana: false, - }); visitRulesManagementTable(); + installPrebuiltRuleAssets([RULE_2, RULE_3]); }); }); @@ -136,9 +134,8 @@ describe( rule_id: 'rule_1', version: 2, }); - createAndInstallMockedPrebuiltRules({ rules: [UPDATED_RULE], installToKibana: false }); + installPrebuiltRuleAssets([UPDATED_RULE]); visitRulesManagementTable(); - cy.reload(); }); }); @@ -167,10 +164,7 @@ describe( rule_id: 'rule_1', version: 2, }); - createAndInstallMockedPrebuiltRules({ - rules: [RULE_2, UPDATED_RULE], - installToKibana: false, - }); + installPrebuiltRuleAssets([RULE_2, UPDATED_RULE]); visitRulesManagementTable(); }); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules.cy.ts index c877221cb02bc2..8d551b655fca41 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules.cy.ts @@ -194,7 +194,7 @@ describe( }); it('Only prebuilt rules selected', () => { - createAndInstallMockedPrebuiltRules({ rules: PREBUILT_RULES }); + createAndInstallMockedPrebuiltRules(PREBUILT_RULES); // select Elastic(prebuilt) rules, check if we can't proceed further, as Elastic rules are not editable filterByElasticRules(); @@ -213,7 +213,7 @@ describe( it('Prebuilt and custom rules selected: user proceeds with custom rules editing', () => { getRulesManagementTableRows().then((existedRulesRows) => { - createAndInstallMockedPrebuiltRules({ rules: PREBUILT_RULES }); + createAndInstallMockedPrebuiltRules(PREBUILT_RULES); // modal window should show how many rules can be edit, how many not selectAllRules(); @@ -238,7 +238,7 @@ describe( }); it('Prebuilt and custom rules selected: user cancels action', () => { - createAndInstallMockedPrebuiltRules({ rules: PREBUILT_RULES }); + createAndInstallMockedPrebuiltRules(PREBUILT_RULES); getRulesManagementTableRows().then((rows) => { // modal window should show how many rules can be edit, how many not diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_actions.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_actions.cy.ts index fb54b040051394..1d59135012a9d0 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_actions.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_actions.cy.ts @@ -145,7 +145,7 @@ describe( rule_id: 'rule_2', }); - createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2] }); + createAndInstallMockedPrebuiltRules([RULE_1, RULE_2]); }); context('Restricted action privileges', () => { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/import_export/export_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/import_export/export_rule.cy.ts index 2e1f4ec1524cf2..262c6904db4bd7 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/import_export/export_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_actions/import_export/export_rule.cy.ts @@ -103,7 +103,7 @@ describe('Export rules', { tags: ['@ess', '@serverless', '@brokenInServerless'] }); it('shows a modal saying that no rules can be exported if all the selected rules are prebuilt', function () { - createAndInstallMockedPrebuiltRules({ rules: prebuiltRules }); + createAndInstallMockedPrebuiltRules(prebuiltRules); filterByElasticRules(); selectAllRules(); @@ -117,7 +117,7 @@ describe('Export rules', { tags: ['@ess', '@serverless', '@brokenInServerless'] it('exports only custom rules', function () { const expectedNumberCustomRulesToBeExported = 1; - createAndInstallMockedPrebuiltRules({ rules: prebuiltRules }); + createAndInstallMockedPrebuiltRules(prebuiltRules); selectAllRules(); bulkExportRules(); @@ -170,7 +170,7 @@ describe('Export rules', { tags: ['@ess', '@serverless', '@brokenInServerless'] // one rule with exception, one without it const expectedNumberCustomRulesToBeExported = 2; - createAndInstallMockedPrebuiltRules({ rules: prebuiltRules }); + createAndInstallMockedPrebuiltRules(prebuiltRules); reload(); selectAllRules(); bulkExportRules(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_selection.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_selection.cy.ts index 6ae36029a8c0ad..d07186c8252f9a 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_selection.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rules_table/rules_table_selection.cy.ts @@ -42,7 +42,7 @@ describe('Rules table: selection', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { login(); /* Create and install two mock rules */ - createAndInstallMockedPrebuiltRules({ rules: [RULE_1, RULE_2] }); + createAndInstallMockedPrebuiltRules([RULE_1, RULE_2]); visit(RULES_MANAGEMENT_URL); waitForPrebuiltDetectionRulesToBeLoaded(); }); diff --git a/x-pack/test/security_solution_cypress/cypress/screens/alerts_detection_rules.ts b/x-pack/test/security_solution_cypress/cypress/screens/alerts_detection_rules.ts index 1ae1ed9d95dbb8..14c885fc076e2f 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/alerts_detection_rules.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/alerts_detection_rules.ts @@ -61,6 +61,14 @@ export const UPGRADE_ALL_RULES_BUTTON = '[data-test-subj="upgradeAllRulesButton" export const UPGRADE_SELECTED_RULES_BUTTON = '[data-test-subj="upgradeSelectedRulesButton"]'; +export const getInstallSingleRuleLoadingSpinnerByRuleId = (ruleId: string) => { + return `[data-test-subj="installSinglePrebuiltRuleButton-loadingSpinner-${ruleId}"]`; +}; + +export const getUpgradeSingleRuleLoadingSpinnerByRuleId = (ruleId: string) => { + return `[data-test-subj="upgradeSinglePrebuiltRuleButton-loadingSpinner-${ruleId}"]`; +}; + export const GO_BACK_TO_RULES_TABLE_BUTTON = '[data-test-subj="addRulesGoBackToRulesTableBtn"]'; export const RULES_TABLE_REFRESH_INDICATOR = '[data-test-subj="loading-spinner"]'; @@ -179,7 +187,7 @@ export const getUpgradeSingleRuleButtonByRuleId = (ruleId: string) => { return `[data-test-subj="upgradeSinglePrebuiltRuleButton-${ruleId}"]`; }; -export const NO_RULES_AVAILABLE_FOR_INSTALL_MESSSAGE = +export const NO_RULES_AVAILABLE_FOR_INSTALL_MESSAGE = '[data-test-subj="noPrebuiltRulesAvailableForInstall"]'; -export const NO_RULES_AVAILABLE_FOR_UPGRADE_MESSSAGE = +export const NO_RULES_AVAILABLE_FOR_UPGRADE_MESSAGE = '[data-test-subj="noPrebuiltRulesAvailableForUpgrade"]'; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/api_calls/prebuilt_rules.ts b/x-pack/test/security_solution_cypress/cypress/tasks/api_calls/prebuilt_rules.ts index 48b21115b98956..98b9a884e683ab 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/api_calls/prebuilt_rules.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/api_calls/prebuilt_rules.ts @@ -13,9 +13,10 @@ import { ELASTIC_SECURITY_RULE_ID } from '@kbn/security-solution-plugin/common/d import type { PrePackagedRulesStatusResponse } from '@kbn/security-solution-plugin/public/detection_engine/rule_management/logic/types'; import { getPrebuiltRuleWithExceptionsMock } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules/mocks'; import { createRuleAssetSavedObject } from '../../helpers/rules'; +import { rootRequest } from '../common'; export const getPrebuiltRulesStatus = () => { - return cy.request({ + return rootRequest({ method: 'GET', url: 'api/detection_engine/rules/prepackaged/_status', headers: { @@ -39,7 +40,7 @@ export const SAMPLE_PREBUILT_RULE = createRuleAssetSavedObject({ * instead of all rules available in the `security_detection_engine` package */ export const installAllPrebuiltRulesRequest = () => - cy.request({ + rootRequest({ method: 'POST', url: PERFORM_RULE_INSTALLATION_URL, headers: { @@ -52,6 +53,30 @@ export const installAllPrebuiltRulesRequest = () => }, }); +/* Install specific prebuilt rules. Should be available as security-rule saved objects +/* as a prerequisite for this request to succeed. + * Use in combination with `preventPrebuiltRulesPackageInstallation` and + * `createNewRuleAsset` to create mocked prebuilt rules and install only those + * instead of all rules available in the `security_detection_engine` package + */ +export const installSpecificPrebuiltRulesRequest = (rules: Array) => + rootRequest({ + method: 'POST', + url: PERFORM_RULE_INSTALLATION_URL, + headers: { + 'kbn-xsrf': 'cypress-creds', + 'x-elastic-internal-origin': 'security-solution', + 'elastic-api-version': '1', + }, + body: { + mode: 'SPECIFIC_RULES', + rules: rules.map((rule) => ({ + rule_id: rule['security-rule'].rule_id, + version: rule['security-rule'].version, + })), + }, + }); + export const getAvailablePrebuiltRulesCount = () => { cy.log('Get prebuilt rules count'); return getPrebuiltRulesStatus().then(({ body }) => { @@ -123,48 +148,44 @@ export const bulkCreateRuleAssets = ({ index?: string; rules?: Array; }) => { - const url = `${Cypress.env('ELASTICSEARCH_URL')}/${index}/_bulk`; + cy.log( + 'Bulk Install prebuilt rules', + rules?.map((rule) => rule['security-rule'].rule_id).join(', ') + ); + const url = `${Cypress.env('ELASTICSEARCH_URL')}/${index}/_bulk?refresh`; const bulkIndexRequestBody = rules.reduce((body, rule) => { const indexOperation = { index: { _index: index, - _id: rule['security-rule'].rule_id, + _id: `security-rule:${rule['security-rule'].rule_id}`, }, }; const documentData = JSON.stringify(rule); - return body.concat(JSON.stringify(indexOperation), '\n', documentData, '\n'); }, ''); - cy.request({ + rootRequest({ method: 'PUT', - url: `${Cypress.env('ELASTICSEARCH_URL')}/${index}/_mapping?refresh`, + url: `${Cypress.env('ELASTICSEARCH_URL')}/${index}/_mapping`, body: { dynamic: true, }, headers: { 'Content-Type': 'application/json', - 'x-elastic-internal-origin': 'security-solution', }, }); cy.waitUntil( () => { - return cy - .request({ - method: 'POST', - url, - headers: { - 'kbn-xsrf': 'cypress-creds', - 'x-elastic-internal-origin': 'security-solution', - 'Content-Type': 'application/json', - }, - failOnStatusCode: false, - body: bulkIndexRequestBody, - }) - .then((response) => response.status === 200); + return rootRequest({ + method: 'POST', + url, + headers: { 'kbn-xsrf': 'cypress-creds', 'Content-Type': 'application/json' }, + failOnStatusCode: false, + body: bulkIndexRequestBody, + }).then((response) => response.status === 200); }, { interval: 500, timeout: 12000 } ); @@ -172,7 +193,7 @@ export const bulkCreateRuleAssets = ({ export const getRuleAssets = (index: string | undefined = '.kibana_security_solution') => { const url = `${Cypress.env('ELASTICSEARCH_URL')}/${index}/_search?size=10000`; - return cy.request({ + return rootRequest({ method: 'GET', url, headers: { @@ -194,6 +215,7 @@ export const getRuleAssets = (index: string | undefined = '.kibana_security_solu /* Used primarily to prevent the unwanted installation of "real" prebuilt rules /* during e2e tests, and allow for manual installation of mock rules instead. */ export const preventPrebuiltRulesPackageInstallation = () => { + cy.log('Prevent prebuilt rules package installation'); cy.intercept('POST', '/api/fleet/epm/packages/_bulk*', {}); cy.intercept('POST', '/api/fleet/epm/packages/security_detection_engine/*', {}); }; @@ -202,42 +224,31 @@ export const preventPrebuiltRulesPackageInstallation = () => { * Install prebuilt rule assets. After installing these assets become available to be installed * as prebuilt rules. Prebuilt rule assets can be generated via `createRuleAssetSavedObject()` helper function. * - * It's also important to take into account that business logic tries to fetch prebuilt rules Fleet package + * It's also important to take into account that the business logic tries to fetch prebuilt rules Fleet package * and you need to add `preventPrebuiltRulesPackageInstallation()` to `beforeEach` section (before visit commands) - * to avoid actually pulling a real Fleet package and have only provided prebuilt rule assets for testing. + * to avoid actually pulling a real Fleet package and have only the mocked prebuilt rule assets for testing. */ export const installPrebuiltRuleAssets = (ruleAssets: Array): void => { cy.log('Create mocked available to install prebuilt rules', ruleAssets.length); preventPrebuiltRulesPackageInstallation(); - // TODO: use this bulk method once the issue with Cypress is fixed - // bulkCreateRuleAssets({ rules }); - ruleAssets.forEach((rule) => { - createNewRuleAsset({ rule }); - }); + + bulkCreateRuleAssets({ rules: ruleAssets }); }; /** * Prevent the installation of the `security_detection_engine` package from Fleet. * The create a `security-rule` asset for each rule provided in the `rules` array. - * Optionally install the rules to Kibana, with a flag defaulting to true - * Explicitly set the `installToKibana` flag to false in cases when needing to - * make mock rules available for installation or update, but do those operations manually * * * @param {Array} rules - Rule assets to be created and optionally installed * - * * @param {string} installToKibana - Flag to decide whether to install the rules as 'alerts' SO. Defaults to true. */ -export const createAndInstallMockedPrebuiltRules = ({ - rules: ruleAssets, - installToKibana = true, -}: { - rules: Array; - installToKibana?: boolean; -}) => { +export const createAndInstallMockedPrebuiltRules = ( + ruleAssets: Array +) => { + preventPrebuiltRulesPackageInstallation(); + // Install assets into ES as `security-rule` SOs installPrebuiltRuleAssets(ruleAssets); - if (installToKibana) { - cy.log('Install prebuilt rules', ruleAssets.length); - return installAllPrebuiltRulesRequest(); - } + // Install rules into Kibana as `alerts` SOs + return installSpecificPrebuiltRulesRequest(ruleAssets); }; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/common.ts b/x-pack/test/security_solution_cypress/cypress/tasks/common.ts index 3c2467c25f6ad2..67bcf971c3b150 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/common.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/common.ts @@ -93,6 +93,7 @@ export const resetRulesTableState = () => { export const cleanKibana = () => { resetRulesTableState(); + deletePrebuiltRulesAssets(); deleteAlertsAndRules(); deleteAllCasesItems(); deleteTimelines(); diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules.ts b/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules.ts index 7b58dda17015fb..fc78399fff8e44 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/prebuilt_rules.ts @@ -9,18 +9,12 @@ import { RULES_ADD_PATH, RULES_UPDATES } from '@kbn/security-solution-plugin/com import { ADD_ELASTIC_RULES_BTN, ADD_ELASTIC_RULES_TABLE, - getInstallSingleRuleButtonByRuleId, - getUpgradeSingleRuleButtonByRuleId, - INSTALL_ALL_RULES_BUTTON, - INSTALL_SELECTED_RULES_BUTTON, + getInstallSingleRuleLoadingSpinnerByRuleId, + getUpgradeSingleRuleLoadingSpinnerByRuleId, RULES_MANAGEMENT_TABLE, RULES_UPDATES_TAB, RULES_UPDATES_TABLE, - RULE_CHECKBOX, - SELECT_ALL_RULES_ON_PAGE_CHECKBOX, TOASTER, - UPGRADE_ALL_RULES_BUTTON, - UPGRADE_SELECTED_RULES_BUTTON, } from '../screens/alerts_detection_rules'; import { RULE_MANAGEMENT_PAGE_BREADCRUMB } from '../screens/breadcrumbs'; import type { SAMPLE_PREBUILT_RULE } from './api_calls/prebuilt_rules'; @@ -35,190 +29,116 @@ export const ruleUpdatesTabClick = () => { cy.location('pathname').should('include', RULES_UPDATES); }; -interface RuleInstallUpgradeAssertionPayload { - rules: Array; - didRequestFail?: boolean; -} - -export const assertRuleAvailableForInstallAndInstallOne = ({ - rules, - didRequestFail = false, -}: RuleInstallUpgradeAssertionPayload) => { - interceptInstallationRequestToFail(rules, didRequestFail); - const rule = rules[0]; - cy.get(getInstallSingleRuleButtonByRuleId(rule['security-rule'].rule_id)).click(); - cy.wait('@installPrebuiltRules'); - assertInstallationSuccessOrFailure([rule], didRequestFail); -}; - -export const assertRuleAvailableForInstallAndInstallSelected = ({ - rules, - didRequestFail = false, -}: RuleInstallUpgradeAssertionPayload) => { - interceptInstallationRequestToFail(rules, didRequestFail); - let i = 0; +export const assertInstallationRequestIsComplete = (rules: Array) => { for (const rule of rules) { - cy.get(RULE_CHECKBOX).eq(i).click(); - cy.get(ADD_ELASTIC_RULES_TABLE).contains(rule['security-rule'].name); - i++; + cy.get(getInstallSingleRuleLoadingSpinnerByRuleId(rule['security-rule'].rule_id)).should( + 'exist' + ); } - cy.get(INSTALL_SELECTED_RULES_BUTTON).click(); - cy.wait('@installPrebuiltRules'); - assertInstallationSuccessOrFailure(rules, didRequestFail); -}; - -export const assertRuleAvailableForInstallAndInstallAllInPage = ({ - rules, - didRequestFail = false, -}: RuleInstallUpgradeAssertionPayload) => { - interceptInstallationRequestToFail(rules, didRequestFail); for (const rule of rules) { - cy.get(ADD_ELASTIC_RULES_TABLE).contains(rule['security-rule'].name); + cy.get(getInstallSingleRuleLoadingSpinnerByRuleId(rule['security-rule'].rule_id)).should( + 'not.exist' + ); } - cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click(); - cy.get(INSTALL_SELECTED_RULES_BUTTON).click(); - cy.wait('@installPrebuiltRules'); - assertInstallationSuccessOrFailure(rules, didRequestFail); }; -export const assertRuleAvailableForInstallAndInstallAll = ({ - rules, - didRequestFail = false, -}: RuleInstallUpgradeAssertionPayload) => { - interceptInstallationRequestToFail(rules, didRequestFail); +export const assertUpgradeRequestIsComplete = (rules: Array) => { for (const rule of rules) { - cy.get(ADD_ELASTIC_RULES_TABLE).contains(rule['security-rule'].name); + cy.get(getUpgradeSingleRuleLoadingSpinnerByRuleId(rule['security-rule'].rule_id)).should( + 'exist' + ); + } + for (const rule of rules) { + cy.get(getUpgradeSingleRuleLoadingSpinnerByRuleId(rule['security-rule'].rule_id)).should( + 'not.exist' + ); } - cy.get(INSTALL_ALL_RULES_BUTTON).click(); - cy.wait('@installPrebuiltRules'); - assertInstallationSuccessOrFailure(rules, didRequestFail); }; -const assertInstallationSuccessOrFailure = ( - rules: Array, - didRequestFail: boolean -) => { +/** + * Assert that when the rule installation succeeds, the toast is shown with the right message + * -confirming the succesful install- and subsequently check that the rules available for installation + * are not present in the Add Elastic Rules table anymore + */ +export const assertInstallationSuccess = (rules: Array) => { const rulesString = rules.length > 1 ? 'rules' : 'rule'; - const toastMessage = didRequestFail - ? `${rules.length} ${rulesString} failed to install.` - : `${rules.length} ${rulesString} installed successfully.`; + const toastMessage = `${rules.length} ${rulesString} installed successfully.`; cy.get(TOASTER).should('be.visible').should('have.text', toastMessage); - if (didRequestFail) { - for (const rule of rules) { - cy.get(ADD_ELASTIC_RULES_TABLE).contains(rule['security-rule'].name); - } - } else { - cy.get(RULE_MANAGEMENT_PAGE_BREADCRUMB).click(); - for (const rule of rules) { - cy.get(RULES_MANAGEMENT_TABLE).contains(rule['security-rule'].name); - } - } -}; -const interceptInstallationRequestToFail = ( - rules: Array, - didRequestFail: boolean -) => { - if (didRequestFail) { - cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/installation/_perform', { - body: { - summary: { - succeeded: [], - skipped: [], - failed: rules.length, - }, - }, - }).as('installPrebuiltRules'); + // Go back to rules table and assert that the rules are installed + cy.get(RULE_MANAGEMENT_PAGE_BREADCRUMB).click(); + for (const rule of rules) { + cy.get(RULES_MANAGEMENT_TABLE).contains(rule['security-rule'].name); } }; -export const assertRuleUpgradeAvailableAndUpgradeOne = ({ - rules, - didRequestFail = false, -}: RuleInstallUpgradeAssertionPayload) => { - interceptUpgradeRequestToFail(rules, didRequestFail); - const rule = rules[0]; - cy.get(getUpgradeSingleRuleButtonByRuleId(rule['security-rule'].rule_id)).click(); - cy.wait('@updatePrebuiltRules'); - assertUpgradeSuccessOrFailure([rule], didRequestFail); -}; +/** + * Assert that when the rule installation fails, the toast is shown with the right message + * -notifying that the installation failed- and subsequently check that the rules available for installation + * are still present in the Rule Update table + */ +export const assertInstallationFailure = (rules: Array) => { + const rulesString = rules.length > 1 ? 'rules' : 'rule'; + const toastMessage = `${rules.length} ${rulesString} failed to install.`; + cy.get(TOASTER).should('be.visible').should('have.text', toastMessage); -export const assertRuleUpgradeAvailableAndUpgradeSelected = ({ - rules, - didRequestFail = false, -}: RuleInstallUpgradeAssertionPayload) => { - interceptUpgradeRequestToFail(rules, didRequestFail); - let i = 0; + // Check rules are still available for install for (const rule of rules) { - cy.get(RULE_CHECKBOX).eq(i).click(); - cy.get(RULES_UPDATES_TABLE).contains(rule['security-rule'].name); - i++; + cy.get(ADD_ELASTIC_RULES_TABLE).contains(rule['security-rule'].name); } - cy.get(UPGRADE_SELECTED_RULES_BUTTON).click(); - cy.wait('@updatePrebuiltRules'); - assertUpgradeSuccessOrFailure(rules, didRequestFail); }; -export const assertRuleUpgradeAvailableAndUpgradeAllInPage = ({ - rules, - didRequestFail = false, -}: RuleInstallUpgradeAssertionPayload) => { - interceptUpgradeRequestToFail(rules, didRequestFail); - for (const rule of rules) { - cy.get(RULES_UPDATES_TABLE).contains(rule['security-rule'].name); - } - cy.get(SELECT_ALL_RULES_ON_PAGE_CHECKBOX).click(); - cy.get(UPGRADE_SELECTED_RULES_BUTTON).click(); - cy.wait('@updatePrebuiltRules'); - assertUpgradeSuccessOrFailure(rules, didRequestFail); +export const interceptInstallationRequestToFail = (rules: Array) => { + cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/installation/_perform', { + body: { + summary: { + succeeded: [], + skipped: [], + failed: rules.length, + }, + }, + delay: 500, // Add delay to give Cypress time to find the loading spinner + }).as('installPrebuiltRules'); }; -export const assertRuleUpgradeAvailableAndUpgradeAll = ({ - rules, - didRequestFail = false, -}: RuleInstallUpgradeAssertionPayload) => { - interceptUpgradeRequestToFail(rules, didRequestFail); +/** + * Assert that when the rule version upgrade succeeds, the toast is shown with the right message + * -confirming the succesful upgrade- and subsequently check that the rules available for upgrade + * are not present in the Rule Update table anymore + */ +export const assertUpgradeSuccess = (rules: Array) => { + const rulesString = rules.length > 1 ? 'rules' : 'rule'; + const toastMessage = `${rules.length} ${rulesString} updated successfully.`; + cy.get(TOASTER).should('be.visible').should('have.text', toastMessage); for (const rule of rules) { - cy.get(RULES_UPDATES_TABLE).contains(rule['security-rule'].name); + cy.get(rule['security-rule'].name).should('not.exist'); } - cy.get(UPGRADE_ALL_RULES_BUTTON).click(); - cy.wait('@updatePrebuiltRules'); - assertUpgradeSuccessOrFailure(rules, didRequestFail); }; -const assertUpgradeSuccessOrFailure = ( - rules: Array, - didRequestFail: boolean -) => { +/** + * Assert that when the rule version upgrade fails, the toast is shown with the right message + * -notifying that the upgrade failed- and subsequently check that the rules available for upgrade + * are still present in the Rule Update table + */ +export const assertUpgradeFailure = (rules: Array) => { const rulesString = rules.length > 1 ? 'rules' : 'rule'; - const toastMessage = didRequestFail - ? `${rules.length} ${rulesString} failed to update.` - : `${rules.length} ${rulesString} updated successfully.`; + const toastMessage = `${rules.length} ${rulesString} failed to update.`; cy.get(TOASTER).should('be.visible').should('have.text', toastMessage); - if (didRequestFail) { - for (const rule of rules) { - cy.get(RULES_UPDATES_TABLE).contains(rule['security-rule'].name); - } - } else { - for (const rule of rules) { - cy.get(rule['security-rule'].name).should('not.exist'); - } + + for (const rule of rules) { + cy.get(RULES_UPDATES_TABLE).contains(rule['security-rule'].name); } }; -const interceptUpgradeRequestToFail = ( - rules: Array, - didRequestFail: boolean -) => { - if (didRequestFail) { - cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/upgrade/_perform', { - body: { - summary: { - succeeded: [], - skipped: [], - failed: rules.length, - }, +export const interceptUpgradeRequestToFail = (rules: Array) => { + cy.intercept('POST', '/internal/detection_engine/prebuilt_rules/upgrade/_perform', { + body: { + summary: { + succeeded: [], + skipped: [], + failed: rules.length, }, - }).as('updatePrebuiltRules'); - } + }, + delay: 500, // Add delay to give Cypress time to find the loading spinner + }).as('updatePrebuiltRules'); }; diff --git a/x-pack/test/security_solution_cypress/package.json b/x-pack/test/security_solution_cypress/package.json index c434d5d7a4099f..82169a43d04114 100644 --- a/x-pack/test/security_solution_cypress/package.json +++ b/x-pack/test/security_solution_cypress/package.json @@ -1,32 +1,32 @@ { - "author": "Elastic", - "name": "@kbn/security-solution-plugin", - "version": "1.0.0", - "private": true, - "license": "Elastic License 2.0", - "scripts": { - "cypress": "NODE_OPTIONS=--openssl-legacy-provider ../../../node_modules/.bin/cypress", - "cypress:open:ess": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../plugins/security_solution/scripts/start_cypress_parallel open --spec './cypress/e2e/**/*.cy.ts' --config-file ../../test/security_solution_cypress/cypress/cypress.config.ts --ftr-config-file ../../test/security_solution_cypress/cli_config", - "cypress:run:ess": "yarn cypress:ess --spec './cypress/e2e/!(investigations|explore)/**/*.cy.ts'", - "cypress:run:cases:ess": "yarn cypress:ess --spec './cypress/e2e/explore/cases/*.cy.ts'", - "cypress:ess": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../plugins/security_solution/scripts/start_cypress_parallel run --config-file ../../test/security_solution_cypress/cypress/cypress_ci.config.ts --ftr-config-file ../../test/security_solution_cypress/cli_config", - "cypress:run:respops:ess": "yarn cypress:ess --spec './cypress/e2e/(detection_alerts|detection_rules|exceptions)/*.cy.ts'", - "cypress:investigations:run:ess": "yarn cypress:ess --spec './cypress/e2e/investigations/**/*.cy.ts'", - "cypress:explore:run:ess": "yarn cypress:ess --spec './cypress/e2e/explore/**/*.cy.ts'", - "cypress:changed-specs-only:ess": "yarn cypress:ess --changed-specs-only --env burn=5", - "cypress:burn:ess": "yarn cypress:ess --env burn=5", - "junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-security-solution/cypress/results/mochawesome*.json > ../../../target/kibana-security-solution/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-security-solution/cypress/results/output.json --reportDir ../../../target/kibana-security-solution/cypress/results && yarn junit:transform && mkdir -p ../../../target/junit && cp ../../../target/kibana-security-solution/cypress/results/*.xml ../../../target/junit/", - "junit:transform": "node ../../plugins/security_solution/scripts/junit_transformer --pathPattern '../../../target/kibana-security-solution/cypress/results/*.xml' --rootDirectory ../../../ --reportName 'Security Solution Cypress' --writeInPlace", - "cypress:serverless": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../plugins/security_solution/scripts/start_cypress_parallel --config-file ../../test/security_solution_cypress/cypress/cypress_ci_serverless.config.ts --ftr-config-file ../../test/security_solution_cypress/serverless_config", - "cypress:cloud:serverless": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider NODE_TLS_REJECT_UNAUTHORIZED=0 ../../../node_modules/.bin/cypress", - "cypress:open:cloud:serverless": "yarn cypress:cloud:serverless open --config-file ./cypress/cypress_serverless.config.ts --env CLOUD_SERVERLESS=true", - "cypress:open:serverless": "yarn cypress:serverless open --config-file ../../test/security_solution_cypress/cypress/cypress_serverless.config.ts --spec './cypress/e2e/**/*.cy.ts'", - "cypress:run:serverless": "yarn cypress:serverless --spec './cypress/e2e/!(investigations|explore)/**/*.cy.ts'", - "cypress:run:cloud:serverless": "yarn cypress:cloud:serverless run --config-file ./cypress/cypress_ci_serverless.config.ts --env CLOUD_SERVERLESS=true", - "cypress:run:qa:serverless": "yarn cypress:cloud:serverless run --config-file ./cypress/cypress_ci_serverless_qa.config.ts --env CLOUD_SERVERLESS=true", - "cypress:investigations:run:serverless": "yarn cypress:serverless --spec './cypress/e2e/investigations/**/*.cy.ts'", - "cypress:explore:run:serverless": "yarn cypress:serverless --spec './cypress/e2e/explore/**/*.cy.ts'", - "cypress:changed-specs-only:serverless": "yarn cypress:serverless --changed-specs-only --env burn=5", - "cypress:burn:serverless": "yarn cypress:serverless --env burn=5" - } + "author": "Elastic", + "name": "@kbn/security-solution-plugin", + "version": "1.0.0", + "private": true, + "license": "Elastic License 2.0", + "scripts": { + "cypress": "NODE_OPTIONS=--openssl-legacy-provider ../../../node_modules/.bin/cypress", + "cypress:open:ess": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../plugins/security_solution/scripts/start_cypress_parallel open --spec './cypress/e2e/**/*.cy.ts' --config-file ../../test/security_solution_cypress/cypress/cypress.config.ts --ftr-config-file ../../test/security_solution_cypress/cli_config", + "cypress:run:ess": "yarn cypress:ess --spec './cypress/e2e/!(investigations|explore)/**/*.cy.ts'", + "cypress:run:cases:ess": "yarn cypress:ess --spec './cypress/e2e/explore/cases/*.cy.ts'", + "cypress:ess": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../plugins/security_solution/scripts/start_cypress_parallel run --config-file ../../test/security_solution_cypress/cypress/cypress_ci.config.ts --ftr-config-file ../../test/security_solution_cypress/cli_config", + "cypress:run:respops:ess": "yarn cypress:ess --spec './cypress/e2e/(detection_alerts|detection_rules|exceptions)/*.cy.ts'", + "cypress:investigations:run:ess": "yarn cypress:ess --spec './cypress/e2e/investigations/**/*.cy.ts'", + "cypress:explore:run:ess": "yarn cypress:ess --spec './cypress/e2e/explore/**/*.cy.ts'", + "cypress:changed-specs-only:ess": "yarn cypress:ess --changed-specs-only --env burn=5", + "cypress:burn:ess": "yarn cypress:ess --env burn=5", + "junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-security-solution/cypress/results/mochawesome*.json > ../../../target/kibana-security-solution/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-security-solution/cypress/results/output.json --reportDir ../../../target/kibana-security-solution/cypress/results && yarn junit:transform && mkdir -p ../../../target/junit && cp ../../../target/kibana-security-solution/cypress/results/*.xml ../../../target/junit/", + "junit:transform": "node ../../plugins/security_solution/scripts/junit_transformer --pathPattern '../../../target/kibana-security-solution/cypress/results/*.xml' --rootDirectory ../../../ --reportName 'Security Solution Cypress' --writeInPlace", + "cypress:serverless": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../plugins/security_solution/scripts/start_cypress_parallel --config-file ../../test/security_solution_cypress/cypress/cypress_ci_serverless.config.ts --ftr-config-file ../../test/security_solution_cypress/serverless_config", + "cypress:cloud:serverless": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider NODE_TLS_REJECT_UNAUTHORIZED=0 ../../../node_modules/.bin/cypress", + "cypress:open:cloud:serverless": "yarn cypress:cloud:serverless open --config-file ./cypress/cypress_serverless.config.ts --env CLOUD_SERVERLESS=true", + "cypress:open:serverless": "yarn cypress:serverless open --config-file ../../test/security_solution_cypress/cypress/cypress_serverless.config.ts --spec './cypress/e2e/**/*.cy.ts'", + "cypress:run:serverless": "yarn cypress:serverless --spec './cypress/e2e/!(investigations|explore)/**/*.cy.ts'", + "cypress:run:cloud:serverless": "yarn cypress:cloud:serverless run --config-file ./cypress/cypress_ci_serverless.config.ts --env CLOUD_SERVERLESS=true", + "cypress:run:qa:serverless": "yarn cypress:cloud:serverless run --config-file ./cypress/cypress_ci_serverless_qa.config.ts --env CLOUD_SERVERLESS=true", + "cypress:investigations:run:serverless": "yarn cypress:serverless --spec './cypress/e2e/investigations/**/*.cy.ts'", + "cypress:explore:run:serverless": "yarn cypress:serverless --spec './cypress/e2e/explore/**/*.cy.ts'", + "cypress:changed-specs-only:serverless": "yarn cypress:serverless --changed-specs-only --env burn=5", + "cypress:burn:serverless": "yarn cypress:serverless --env burn=5" } +} \ No newline at end of file From d7b9a2ab719148bec97387b6153b4ac8fd3fe38c Mon Sep 17 00:00:00 2001 From: Marco Liberati Date: Tue, 17 Oct 2023 13:33:56 +0200 Subject: [PATCH 46/87] [ES|QL] Improve warning handling for messages without positioning (#169066) ## Summary This PR improves the warning unmarshalling for ES|QL providing support for messages without positioning (`Line x:xx: ...`). Screenshot 2023-10-17 at 10 11 12 ### 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 --- .../kbn-text-based-editor/src/helpers.test.ts | 67 +++++++++++++++ packages/kbn-text-based-editor/src/helpers.ts | 85 ++++++++++++------- 2 files changed, 119 insertions(+), 33 deletions(-) diff --git a/packages/kbn-text-based-editor/src/helpers.test.ts b/packages/kbn-text-based-editor/src/helpers.test.ts index f7b100419b2c78..f0a4268f857bc6 100644 --- a/packages/kbn-text-based-editor/src/helpers.test.ts +++ b/packages/kbn-text-based-editor/src/helpers.test.ts @@ -114,6 +114,73 @@ describe('helpers', function () { }, ]); }); + + it('should return the correct array of warnings if multiple warnins are detected without line indicators', function () { + const warning = + '299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Field [geo.coordinates] cannot be retrieved, it is unsupported or not indexed; returning null.", 299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Field [ip_range] cannot be retrieved, it is unsupported or not indexed; returning null.", 299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Field [timestamp_range] cannot be retrieved, it is unsupported or not indexed; returning null."'; + expect(parseWarning(warning)).toEqual([ + { + endColumn: 10, + endLineNumber: 1, + message: + 'Field [geo.coordinates] cannot be retrieved, it is unsupported or not indexed; returning null.', + severity: 8, + startColumn: 1, + startLineNumber: 1, + }, + { + endColumn: 10, + endLineNumber: 1, + message: + 'Field [ip_range] cannot be retrieved, it is unsupported or not indexed; returning null.', + severity: 8, + startColumn: 1, + startLineNumber: 1, + }, + { + endColumn: 10, + endLineNumber: 1, + message: + 'Field [timestamp_range] cannot be retrieved, it is unsupported or not indexed; returning null.', + severity: 8, + startColumn: 1, + startLineNumber: 1, + }, + ]); + }); + it('should return the correct array of warnings if multiple warnins of different types', function () { + const warning = + '299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Field [geo.coordinates] cannot be retrieved, it is unsupported or not indexed; returning null.", 299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Field [ip_range] cannot be retrieved, it is unsupported or not indexed; returning null.", 299 Elasticsearch-8.10.0-SNAPSHOT-adb9fce96079b421c2575f0d2d445f492eb5f075 "Line 1:52: evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded."'; + expect(parseWarning(warning)).toEqual([ + { + endColumn: 10, + endLineNumber: 1, + message: + 'Field [geo.coordinates] cannot be retrieved, it is unsupported or not indexed; returning null.', + severity: 8, + startColumn: 1, + startLineNumber: 1, + }, + { + endColumn: 10, + endLineNumber: 1, + message: + 'Field [ip_range] cannot be retrieved, it is unsupported or not indexed; returning null.', + severity: 8, + startColumn: 1, + startLineNumber: 1, + }, + { + endColumn: 138, + endLineNumber: 1, + message: + 'evaluation of [date_parse(geo.dest)] failed, treating result as null. Only first 20 failures recorded.', + severity: 8, + startColumn: 52, + startLineNumber: 1, + }, + ]); + }); }); describe('getInlineEditorText', function () { diff --git a/packages/kbn-text-based-editor/src/helpers.ts b/packages/kbn-text-based-editor/src/helpers.ts index 89322766951175..234a5ae0089abf 100644 --- a/packages/kbn-text-based-editor/src/helpers.ts +++ b/packages/kbn-text-based-editor/src/helpers.ts @@ -43,41 +43,60 @@ export const useDebounceWithOptions = ( ); }; +const quotedWarningMessageRegexp = /"(.*?)"/g; + export const parseWarning = (warning: string): MonacoError[] => { - if (warning.includes('Line')) { - const splitByLine = warning.split('Line'); - splitByLine.shift(); - return splitByLine.map((item) => { - const [lineNumber, startPosition, warningMessage] = item.split(':'); - const [trimmedMessage] = warningMessage.split('"'); - // initialize the length to 10 in case no error word found - let errorLength = 10; - const [_, wordWithError] = trimmedMessage.split('['); - if (wordWithError) { - errorLength = wordWithError.length - 1; - } - return { - message: trimmedMessage.trimStart(), - startColumn: Number(startPosition), - startLineNumber: Number(lineNumber), - endColumn: Number(startPosition) + errorLength, - endLineNumber: Number(lineNumber), - severity: monaco.MarkerSeverity.Error, - }; - }); - } else { - // unknown warning message - return [ - { - message: warning, - startColumn: 1, - startLineNumber: 1, - endColumn: 10, - endLineNumber: 1, - severity: monaco.MarkerSeverity.Error, - }, - ]; + if (quotedWarningMessageRegexp.test(warning)) { + const matches = warning.match(quotedWarningMessageRegexp); + if (matches) { + return matches.map((message) => { + // start extracting the quoted message and with few default positioning + let warningMessage = message.replace(/"/g, ''); + let startColumn = 1; + let startLineNumber = 1; + // initialize the length to 10 in case no error word found + let errorLength = 10; + // if there's line number encoded in the message use it as new positioning + // and replace the actual message without it + if (/Line (\d+):(\d+):/.test(warningMessage)) { + const [encodedLine, encodedColumn, innerMessage] = warningMessage.split(':'); + warningMessage = innerMessage; + if (!Number.isNaN(Number(encodedColumn))) { + startColumn = Number(encodedColumn); + startLineNumber = Number(encodedLine.replace('Line ', '')); + } + // extract the length of the "expression" within the message + // and try to guess the correct size for the editor marker to highlight + if (/\[.*\]/.test(warningMessage)) { + const [_, wordWithError] = warningMessage.split('['); + if (wordWithError) { + errorLength = wordWithError.length; + } + } + } + + return { + message: warningMessage.trimStart(), + startColumn, + startLineNumber, + endColumn: startColumn + errorLength - 1, + endLineNumber: startLineNumber, + severity: monaco.MarkerSeverity.Error, + }; + }); + } } + // unknown warning message + return [ + { + message: warning, + startColumn: 1, + startLineNumber: 1, + endColumn: 10, + endLineNumber: 1, + severity: monaco.MarkerSeverity.Error, + }, + ]; }; export const parseErrors = (errors: Error[], code: string): MonacoError[] => { From 6caf0327ad2479a1abac892afff0b997d43beace Mon Sep 17 00:00:00 2001 From: Jorge Sanz Date: Tue, 17 Oct 2023 13:46:14 +0200 Subject: [PATCH 47/87] [EMS] Update EMS Client with serverless version and header (#163098) Part of #157094 Fixes #161790 ## Summary * Upgrade to `@elastic/ems-client@8.5.0` * Updates the instantiation of the EMS Client to pass the version and HTTP header on Serverless builds. ### 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 ## Testing The serverless update to EMS Tile Service is ready in Production. Running Kibana in serverless mode, you can check for requests to `https://tiles.maps.elastic.dev/latest/manifest` and the associated `elastic-api-version` header being accepted. EMS File Service already accepts the `latest/manifest` endpoint in our production environment. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- package.json | 2 +- src/dev/license_checker/config.ts | 2 +- src/plugins/maps_ems/common/ems_defaults.ts | 2 + src/plugins/maps_ems/common/index.ts | 1 + .../create_ems_client.test.ts | 116 ++++++++++++++++++ .../lazy_load_bundle/create_ems_client.ts | 19 ++- src/plugins/maps_ems/tsconfig.json | 1 + yarn.lock | 17 ++- 8 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 src/plugins/maps_ems/public/lazy_load_bundle/create_ems_client.test.ts diff --git a/package.json b/package.json index 5718ec17493f3d..fcd74c483ebcda 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "@elastic/charts": "60.0.0", "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.9.1-canary.1", - "@elastic/ems-client": "8.4.0", + "@elastic/ems-client": "8.5.0", "@elastic/eui": "89.0.0", "@elastic/filesaver": "1.1.2", "@elastic/node-crypto": "1.2.1", diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index 037ea764083efd..73c089e29d5d04 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -84,7 +84,7 @@ export const PER_PACKAGE_ALLOWED_LICENSES = { export const LICENSE_OVERRIDES = { 'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint - '@elastic/ems-client@8.4.0': ['Elastic License 2.0'], + '@elastic/ems-client@8.5.0': ['Elastic License 2.0'], '@elastic/eui@89.0.0': ['SSPL-1.0 OR Elastic License 2.0'], 'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry 'buffers@0.1.1': ['MIT'], // license in importing module https://www.npmjs.com/package/binary diff --git a/src/plugins/maps_ems/common/ems_defaults.ts b/src/plugins/maps_ems/common/ems_defaults.ts index f434434ba542ff..93b4e2574c73bd 100644 --- a/src/plugins/maps_ems/common/ems_defaults.ts +++ b/src/plugins/maps_ems/common/ems_defaults.ts @@ -17,3 +17,5 @@ export const DEFAULT_EMS_ROADMAP_DESATURATED_ID = 'road_map_desaturated'; export const DEFAULT_EMS_DARKMAP_ID = 'dark_map'; export const EMS_APP_NAME = 'kibana'; // app-name submitted as the `app`-param to EMS + +export const DEFAULT_EMS_REST_VERSION = '2023-10-31'; diff --git a/src/plugins/maps_ems/common/index.ts b/src/plugins/maps_ems/common/index.ts index 4ec8250cfc6765..a766a321296d1e 100644 --- a/src/plugins/maps_ems/common/index.ts +++ b/src/plugins/maps_ems/common/index.ts @@ -14,6 +14,7 @@ export { DEFAULT_EMS_ROADMAP_ID, DEFAULT_EMS_ROADMAP_DESATURATED_ID, DEFAULT_EMS_DARKMAP_ID, + DEFAULT_EMS_REST_VERSION, EMS_APP_NAME, } from './ems_defaults'; diff --git a/src/plugins/maps_ems/public/lazy_load_bundle/create_ems_client.test.ts b/src/plugins/maps_ems/public/lazy_load_bundle/create_ems_client.test.ts new file mode 100644 index 00000000000000..c30c7f1df97f34 --- /dev/null +++ b/src/plugins/maps_ems/public/lazy_load_bundle/create_ems_client.test.ts @@ -0,0 +1,116 @@ +/* + * 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 { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; +import { EMSSettings } from '../../common/ems_settings'; +import { + DEFAULT_EMS_FILE_API_URL, + DEFAULT_EMS_FONT_LIBRARY_URL, + DEFAULT_EMS_LANDING_PAGE_URL, + DEFAULT_EMS_TILE_API_URL, + DEFAULT_EMS_REST_VERSION, +} from '../../common/ems_defaults'; +import { createEMSClient } from './create_ems_client'; + +import type { EMSConfig } from '../../common/ems_settings'; +import { BuildFlavor } from '@kbn/config/src/types'; +import { LATEST_API_URL_PATH } from '@elastic/ems-client'; + +const IS_ENTERPRISE_PLUS = () => true; + +describe('createEMSClient', () => { + const mockConfig: EMSConfig = { + includeElasticMapsService: true, + emsUrl: '', + emsFileApiUrl: DEFAULT_EMS_FILE_API_URL, + emsTileApiUrl: DEFAULT_EMS_TILE_API_URL, + emsLandingPageUrl: DEFAULT_EMS_LANDING_PAGE_URL, + emsFontLibraryUrl: DEFAULT_EMS_FONT_LIBRARY_URL, + }; + const emsSettings = new EMSSettings(mockConfig, IS_ENTERPRISE_PLUS); + + describe('settings for traditional (SemVer)', () => { + const kbnVersion = '8.7.6'; + const minorKbnVersion = 'v8.7'; + const build: BuildFlavor = 'traditional'; + const emsClient = createEMSClient(emsSettings, kbnVersion, build); + + test('should point to the /vX.Y folder on traditional SemVer (X.Y.Z)', () => { + expect(emsClient.getLandingPageUrl()).toBe( + DEFAULT_EMS_LANDING_PAGE_URL + '/' + minorKbnVersion + ); + }); + + test('client should use the Kibana Version as my_app_version query param', () => { + const clientParams = new URLSearchParams(emsClient.extendUrlWithParams('https://my.host')); + expect(clientParams.get('my_app_version')).toBe(kbnVersion); + }); + + test('client should point to /vX.Y on the services URLs ', async () => { + const { services } = await emsClient.getMainManifest(); + + ['tms', 'file'].map((type) => { + const service = services.find((s) => s.type === type); + expect(service?.manifest.match(minorKbnVersion)); + }); + }); + + test('fetch function should not include the serverless header', async () => { + global.fetch = jest.fn((_, { headers }: { headers: Headers }) => { + expect(headers.has(ELASTIC_HTTP_VERSION_HEADER)).toBeFalsy(); + return Promise.resolve({ + ok: true, + json: () => Promise.resolve({ layers: [{ layer_id: 'mock_1' }] }), + }); + }) as jest.Mock; + + const mocked = await emsClient.getFileLayers(); + // Ensure we ran the mocked function + expect(mocked[0].getId()).toBe('mock_1'); + }); + }); + + describe('Override settings for serverless', () => { + const kbnVersion: string = 'foo'; + const build: BuildFlavor = 'serverless'; + + const emsClient = createEMSClient(emsSettings, kbnVersion, build); + + test('should point to the root', () => { + expect(emsClient.getLandingPageUrl()).toBe(DEFAULT_EMS_LANDING_PAGE_URL); + }); + + test('client should use DEFAULT_EMS_REST_VERSION as my_app_version query param ', () => { + const clientParams = new URLSearchParams(emsClient.extendUrlWithParams('https://my.host')); + expect(clientParams.get('my_app_version')).toBe(DEFAULT_EMS_REST_VERSION); + }); + + test('client should point to /LATEST_API_URL_PATH on the services URLs ', async () => { + const { services } = await emsClient.getMainManifest(); + + ['tms', 'file'].map((type) => { + const service = services.find((s) => s.type === type); + expect(service?.manifest.match(LATEST_API_URL_PATH)); + }); + }); + + test('fetch function should include the serverless header', async () => { + global.fetch = jest.fn((_, { headers }: { headers: Headers }) => { + expect(headers.get(ELASTIC_HTTP_VERSION_HEADER)).toBe(DEFAULT_EMS_REST_VERSION); + return Promise.resolve({ + ok: true, + json: () => Promise.resolve({ layers: [{ layer_id: 'mock_2' }] }), + }); + }) as jest.Mock; + + const mocked = await emsClient.getFileLayers(); + // Ensure we ran the mocked function + expect(mocked[0].getId()).toBe('mock_2'); + }); + }); +}); diff --git a/src/plugins/maps_ems/public/lazy_load_bundle/create_ems_client.ts b/src/plugins/maps_ems/public/lazy_load_bundle/create_ems_client.ts index aad9ca3933e76f..b86f674b6be201 100644 --- a/src/plugins/maps_ems/public/lazy_load_bundle/create_ems_client.ts +++ b/src/plugins/maps_ems/public/lazy_load_bundle/create_ems_client.ts @@ -8,10 +8,11 @@ import coerce from 'semver/functions/coerce'; +import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { BuildFlavor } from '@kbn/config/src/types'; import { i18n } from '@kbn/i18n'; import { EMSClient } from '@elastic/ems-client'; -import { EMS_APP_NAME, EMSSettings } from '../../common'; +import { EMS_APP_NAME, EMSSettings, DEFAULT_EMS_REST_VERSION } from '../../common'; export function createEMSClient( emsSettings: EMSSettings, @@ -20,22 +21,30 @@ export function createEMSClient( ): EMSClient { let landingPageUrl = emsSettings!.getEMSLandingPageUrl(); const kbnSemVer = coerce(kbnVersion); + const isServerless = buildFlavor === 'serverless'; + const headers = new Headers(); - if (buildFlavor === 'traditional' && kbnSemVer) { + if (!isServerless && kbnSemVer) { landingPageUrl = `${landingPageUrl}/v${kbnSemVer.major}.${kbnSemVer.minor}`; } + if (isServerless) { + headers.append(ELASTIC_HTTP_VERSION_HEADER, DEFAULT_EMS_REST_VERSION); + } + + const version = isServerless ? DEFAULT_EMS_REST_VERSION : kbnVersion; + return new EMSClient({ language: i18n.getLocale(), - appVersion: kbnVersion, + appVersion: version, + emsVersion: version, appName: EMS_APP_NAME, tileApiUrl: emsSettings!.getEMSTileApiUrl(), fileApiUrl: emsSettings!.getEMSFileApiUrl(), landingPageUrl, fetchFunction(url: string) { - return fetch(url); + return fetch(url, { headers }); }, proxyPath: '', - emsVersion: kbnVersion, }); } diff --git a/src/plugins/maps_ems/tsconfig.json b/src/plugins/maps_ems/tsconfig.json index c9d4ccde9d8368..7d32dacb6d55ab 100644 --- a/src/plugins/maps_ems/tsconfig.json +++ b/src/plugins/maps_ems/tsconfig.json @@ -10,6 +10,7 @@ "@kbn/i18n", "@kbn/config-schema", "@kbn/config", + "@kbn/core-http-common", ], "exclude": [ "target/**/*", diff --git a/yarn.lock b/yarn.lock index d704bf985e9ada..bf30fbda1764d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1605,10 +1605,10 @@ "@elastic/transport" "^8.3.3" tslib "^2.4.0" -"@elastic/ems-client@8.4.0": - version "8.4.0" - resolved "https://registry.yarnpkg.com/@elastic/ems-client/-/ems-client-8.4.0.tgz#e77bbddda998a77e29b86767fe4ff403c5a62133" - integrity sha512-uMxZl6BxCPLvIJiG80gqQbOlxKqNLYCo0KtHDFVwUGpTgUQnrVzAZUJ9PZ7fSD7cUDW6pE+QekDddDxB2nOCwA== +"@elastic/ems-client@8.5.0": + version "8.5.0" + resolved "https://registry.yarnpkg.com/@elastic/ems-client/-/ems-client-8.5.0.tgz#5e3988ab01dee54bace9f8c2f9e71470b26a1bfa" + integrity sha512-uEI8teyS3gWErlEL4mEYh0MDHms9Rp3eEHKnMMSdMtAkaa3xs60SOm3Vd0ld9sIPsyarQHrAybAw30GXVXXRjw== dependencies: "@types/geojson" "^7946.0.10" "@types/lru-cache" "^5.1.0" @@ -1617,7 +1617,7 @@ chroma-js "^2.1.0" lodash "^4.17.15" lru-cache "^6.0.0" - semver "^7.3.8" + semver "7.5.4" topojson-client "^3.1.0" "@elastic/eslint-plugin-eui@0.0.2": @@ -27141,6 +27141,13 @@ semver@5.6.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== +semver@7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" From b6f62f6822e65bf5c1d46752f07a0ca67d28b3f5 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Tue, 17 Oct 2023 14:15:07 +0200 Subject: [PATCH 48/87] [Security Solution] Unskipping `x-pack/test/security_solution_cypress/cypress/e2e/explore/hosts/` working tests on serverless (#168398) --- .../cypress/e2e/explore/hosts/events_viewer.cy.ts | 2 +- .../cypress/e2e/explore/hosts/host_risk_tab.cy.ts | 8 ++------ .../cypress/e2e/explore/hosts/hosts_risk_column.cy.ts | 2 +- .../cypress/tasks/security_header.ts | 2 +- 4 files changed, 5 insertions(+), 9 deletions(-) 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 82bc6251b276f6..20884e070cf9ae 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 @@ -46,7 +46,7 @@ const defaultHeadersInDefaultEcsCategory = [ { id: 'destination.ip' }, ]; -describe('Events Viewer', { tags: ['@ess', '@brokenInServerless'] }, () => { +describe('Events Viewer', { tags: ['@ess', '@serverless'] }, () => { before(() => { cy.task('esArchiverLoad', { archiveName: 'auditbeat_big' }); }); 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 695f261c599d0a..6a11e27bcc81ac 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 @@ -20,12 +20,12 @@ import { import { login } from '../../../tasks/login'; import { visitWithTimeRange } from '../../../tasks/navigation'; import { hostsUrl } from '../../../urls/navigation'; -import { clearSearchBar, kqlSearch } from '../../../tasks/security_header'; +import { kqlSearch } from '../../../tasks/security_header'; import { deleteRiskEngineConfiguration } from '../../../tasks/api_calls/risk_engine'; import { enableRiskEngine } from '../../../tasks/entity_analytics'; // Tracked by https://github.com/elastic/security-team/issues/7696 -describe('risk tab', { tags: ['@ess', '@brokenInServerless'] }, () => { +describe('risk tab', { tags: ['@ess', '@serverless'] }, () => { describe('with legacy risk score', () => { before(() => { cleanKibana(); @@ -52,7 +52,6 @@ describe('risk tab', { tags: ['@ess', '@brokenInServerless'] }, () => { cy.get(HOST_BY_RISK_TABLE_CELL).eq(3).should('have.text', 'siem-kibana'); cy.get(HOST_BY_RISK_TABLE_CELL).eq(4).should('have.text', '21'); cy.get(HOST_BY_RISK_TABLE_CELL).eq(5).should('have.text', 'Low'); - clearSearchBar(); }); it.skip('filters the table', () => { @@ -73,7 +72,6 @@ describe('risk tab', { tags: ['@ess', '@brokenInServerless'] }, () => { it('should not allow page change when page is empty', () => { kqlSearch('host.name: "nonexistent_host" {enter}'); cy.get(HOST_BY_RISK_TABLE_NEXT_PAGE_BUTTON).should(`not.exist`); - clearSearchBar(); }); }); @@ -104,7 +102,6 @@ describe('risk tab', { tags: ['@ess', '@brokenInServerless'] }, () => { cy.get(HOST_BY_RISK_TABLE_CELL).eq(3).should('have.text', 'siem-kibana'); cy.get(HOST_BY_RISK_TABLE_CELL).eq(4).should('have.text', '90'); cy.get(HOST_BY_RISK_TABLE_CELL).eq(5).should('have.text', 'Critical'); - clearSearchBar(); }); it.skip('filters the table', () => { @@ -125,7 +122,6 @@ describe('risk tab', { tags: ['@ess', '@brokenInServerless'] }, () => { it('should not allow page change when page is empty', () => { kqlSearch('host.name: "nonexistent_host" {enter}'); cy.get(HOST_BY_RISK_TABLE_NEXT_PAGE_BUTTON).should(`not.exist`); - clearSearchBar(); }); }); }); 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 a1bdff9a350725..d5ca12dc63f6f5 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'; import { deleteRiskEngineConfiguration } from '../../../tasks/api_calls/risk_engine'; import { enableRiskEngine } from '../../../tasks/entity_analytics'; -describe('All hosts table', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { +describe('All hosts table', { tags: ['@ess', '@serverless'] }, () => { describe('with legacy risk score', () => { before(() => { cleanKibana(); diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/security_header.ts b/x-pack/test/security_solution_cypress/cypress/tasks/security_header.ts index 8824d41536a8eb..4cca17aa18dae5 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/security_header.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/security_header.ts @@ -14,7 +14,7 @@ export const clearSearchBar = () => { }; export const kqlSearch = (search: string) => { - cy.get(KQL_INPUT).type(search); + cy.get(KQL_INPUT).type(search, { force: true }); }; export const navigateFromHeaderTo = (page: string) => { From 50cb94fd5c82283a5d542ed8f0eb41e0a77449cd Mon Sep 17 00:00:00 2001 From: Marta Bondyra <4283304+mbondyra@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:16:50 +0200 Subject: [PATCH 49/87] [Lens] Mosaic - make vertical axis dimension required (#168833) ## Summary Fixes https://github.com/elastic/kibana/issues/165004 --- .../lens/public/visualizations/partition/visualization.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx b/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx index da42517ad30cc8..267c014ae1a6ca 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx @@ -284,6 +284,7 @@ export const getPieVisualization = ({ case PieChartTypes.MOSAIC: return { ...primaryGroupConfigBaseProps, + requiredMinDimensionCount: 1, groupLabel: i18n.translate('xpack.lens.pie.verticalAxisLabel', { defaultMessage: 'Vertical axis', }), From d70e4c7b6a234f03225d529068c578f67b5f72be Mon Sep 17 00:00:00 2001 From: Jill Guyonnet Date: Tue, 17 Oct 2023 14:27:21 +0200 Subject: [PATCH 50/87] [Fleet] Elastic Agent upgrade states UI (#167539) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Closes https://github.com/elastic/ingest-dev/issues/1937 This PR implements the UI side of the new Elastic Agent upgrade states. Note: the following changes will be present regardless of whether Elastic Agent has upgrade details: - Wider `Version` column - `Upgrade available` text is now a badge ### Screenshots Screenshot 2023-10-05 at 14 23 46 Screenshot 2023-10-05 at 11 36 08 Screenshot 2023-10-05 at 17 09 03 Screenshot 2023-10-05 at 11 36 23 Screenshot 2023-10-05 at 11 36 30 Screenshot 2023-10-05 at 11 36 40 Screenshot 2023-10-05 at 11 36 47 Screenshot 2023-10-05 at 11 36 53 Screenshot 2023-10-05 at 11 36 58 Screenshot 2023-10-05 at 11 37 05 Screenshot 2023-10-05 at 11 37 35 ### Steps to reproduce Note: the [Elastic Agent changes](https://github.com/elastic/elastic-agent/issues/3119) are not ready yet, so the proposed testing steps aim to mock the upgrade states by editing the agent document(s) manually. 1. Run Kibana on this branch. 2. Enroll at least one agent (or more to test more quickly). 3. Create a "super duper user" in order to edit the agent document(s) (see below). Use this user to edit your agent document(s) and add upgrade details (see below for examples). ⚠️ These upgrade details won't stay for very long, so make sure to check the UI immediately. 4. In Fleet UI, check that the UI correctly reflects the upgrade state (badge and tooltip). 5. Check that an upgrading agent with no upgrade details correctly gets a tooltip informing that the upgrade details are not available. This can be mocked by editing the agent document again and setting `upgrade_started_at` to some timestamp and `upgraded_at` to `null`. #### How to create a "super duper user" In dev tools, run the following two commands: ``` PUT _security/role/super_duper_user { "cluster" : [ "all" ], "indices" : [ { "names" : [ "*" ], "privileges" : [ "all" ], "field_security" : { "grant" : [ "*" ], "except" : [ ] }, "allow_restricted_indices" : true } ], "applications" : [ ], "run_as" : [ ], "metadata" : { }, "transient_metadata" : { "enabled" : true } } PUT _security/user/strong_user { "roles": [ "super_duper_user", "superuser" ], "full_name": "Super Duper User", "email": "super@elastic.co", "password": "changeme", "metadata": {}, "enabled": true } ``` #### Adding upgrade details to an agent Example commands: ``` POST .fleet-agents/_update/ { "doc": { "upgrade_details": { "target_version": "8.11", "action_id": "xxxxxxxx", "state": "UPG_SCHEDULED", "metadata": { "scheduled_at": "2023-10-04T16:34:12Z" // edit this to a better time to check that the number of hours in the tooltip message is correct } } } } ``` ``` POST .fleet-agents/_update/ "doc": { "upgrade_details": { "target_version": "8.11", "action_id": "xxxxxxxx", "state": "UPG_DOWNLOADING", "metadata": { "download_percent": 16.4 } } } } ``` ``` POST .fleet-agents/_update/ { "doc": { "upgrade_details": { "target_version": "8.11", "action_id": "xxxxxxxx", "state": "UPG_FAILED", "metadata": { "failed_state": "UPG_DOWNLOADING", "error_msg": "Something went BOOM" } } } } ``` ### Checklist - [ ] 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 - [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 - [ ] 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) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../fleet/common/types/models/agent.ts | 29 ++ .../components/agent_list_table.tsx | 44 +-- .../components/agent_upgrade_status.test.tsx | 274 ++++++++++++++++++ .../components/agent_upgrade_status.tsx | 269 +++++++++++++++++ .../fleet/server/constants/mappings.ts | 41 +++ .../fleet/server/services/agents/helpers.ts | 1 + .../fleet/server/types/so_attributes.ts | 2 + 7 files changed, 642 insertions(+), 18 deletions(-) create mode 100644 x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_upgrade_status.test.tsx create mode 100644 x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_upgrade_status.tsx diff --git a/x-pack/plugins/fleet/common/types/models/agent.ts b/x-pack/plugins/fleet/common/types/models/agent.ts index f8ed69d6d4d339..934ca7ecd2641d 100644 --- a/x-pack/plugins/fleet/common/types/models/agent.ts +++ b/x-pack/plugins/fleet/common/types/models/agent.ts @@ -48,6 +48,17 @@ export type AgentActionType = | 'POLICY_CHANGE' | 'INPUT_ACTION'; +export type AgentUpgradeStateType = + | 'UPG_REQUESTED' + | 'UPG_SCHEDULED' + | 'UPG_DOWNLOADING' + | 'UPG_EXTRACTING' + | 'UPG_REPLACING' + | 'UPG_RESTARTING' + | 'UPG_WATCHING' + | 'UPG_ROLLBACK' + | 'UPG_FAILED'; + type FleetServerAgentComponentStatusTuple = typeof FleetServerAgentComponentStatuses; export type FleetServerAgentComponentStatus = FleetServerAgentComponentStatusTuple[number]; @@ -89,6 +100,7 @@ interface AgentBase { unenrollment_started_at?: string; upgraded_at?: string | null; upgrade_started_at?: string | null; + upgrade_details?: AgentUpgradeDetails; access_api_key_id?: string; default_api_key?: string; default_api_key_id?: string; @@ -249,6 +261,10 @@ export interface FleetServerAgent { /** * ID of the API key the Elastic Agent must used to contact Fleet Server */ + /** + * Upgrade state of the Elastic Agent + */ + upgrade_details?: AgentUpgradeDetails; access_api_key_id?: string; agent?: FleetServerAgentMetadata; /** @@ -328,6 +344,7 @@ export interface FleetServerAgent { */ outputs?: OutputMap; } + /** * An Elastic Agent metadata */ @@ -421,3 +438,15 @@ export interface ActionStatusOptions { page?: number; perPage?: number; } + +export interface AgentUpgradeDetails { + target_version: string; + action_id: string; + state: AgentUpgradeStateType; + metadata: { + scheduled_at?: string; + download_percent?: number; + failed_state?: AgentUpgradeStateType; + error_msg?: string; + }; +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_list_table.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_list_table.tsx index afc4dd80a7f76e..c52f1bb6588aee 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_list_table.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_list_table.tsx @@ -31,6 +31,8 @@ import { Tags } from '../../components/tags'; import type { AgentMetrics } from '../../../../../../../common/types'; import { formatAgentCPU, formatAgentMemory } from '../../services/agent_metrics'; +import { AgentUpgradeStatus } from './agent_upgrade_status'; + import { EmptyPrompt } from './empty_prompt'; const VERSION_FIELD = 'local_metadata.elastic.agent.version'; @@ -175,7 +177,7 @@ export const AgentListTable: React.FC = (props: Props) => { name: i18n.translate('xpack.fleet.agentList.policyColumnTitle', { defaultMessage: 'Agent policy', }), - width: '260px', + width: '185px', render: (policyId: string, agent: Agent) => { const agentPolicy = agentPoliciesIndexedById[policyId]; const showWarning = agent.policy_revision && agentPolicy?.revision > agent.policy_revision; @@ -276,29 +278,35 @@ export const AgentListTable: React.FC = (props: Props) => { { field: VERSION_FIELD, sortable: true, - width: '70px', + width: '180px', name: i18n.translate('xpack.fleet.agentList.versionTitle', { defaultMessage: 'Version', }), render: (version: string, agent: Agent) => ( - - {safeMetadata(version)} - - {isAgentSelectable(agent) && - latestAgentVersion && - isAgentUpgradeable(agent, latestAgentVersion) ? ( - - - -   - + + + + {safeMetadata(version)} + + + + - - - ) : null} + + + ), }, diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_upgrade_status.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_upgrade_status.test.tsx new file mode 100644 index 00000000000000..9937126213c918 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_upgrade_status.test.tsx @@ -0,0 +1,274 @@ +/* + * 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 { fireEvent, waitFor } from '@testing-library/dom'; +import React from 'react'; + +import { createFleetTestRendererMock } from '../../../../../../mock'; + +import { + AgentUpgradeStatus, + getDownloadEstimate, + getUpgradeStartDelay, +} from './agent_upgrade_status'; + +function getDateString(futureOffsetInMinutes: number): string { + return new Date(Date.now() + futureOffsetInMinutes * 6e4).toISOString(); +} + +describe('getUpgradeStartDelay', () => { + it('should return a user-friendly time estimation', () => { + expect(getUpgradeStartDelay(getDateString(9))).toEqual( + ' The upgrade will start in less than 15 minutes.' + ); + expect(getUpgradeStartDelay(getDateString(25))).toEqual( + ' The upgrade will start in less than 30 minutes.' + ); + expect(getUpgradeStartDelay(getDateString(55))).toEqual( + ' The upgrade will start in less than 1 hour.' + ); + expect(getUpgradeStartDelay(getDateString(61))).toEqual( + ' The upgrade will start in less than 2 hours.' + ); + expect(getUpgradeStartDelay(getDateString(119))).toEqual( + ' The upgrade will start in less than 2 hours.' + ); + expect(getUpgradeStartDelay(getDateString(121))).toEqual( + ' The upgrade will start in less than 3 hours.' + ); + }); +}); + +describe('getDownloadEstimate', () => { + it('should return an empty string if the agent does not have a download percent', () => { + expect(getDownloadEstimate()).toEqual(''); + }); + + it('should return an empty string if the agent has a zero download percent', () => { + expect(getDownloadEstimate(0)).toEqual(''); + }); + + it('should return a formatted string if the agent has a positive download percent', () => { + expect(getDownloadEstimate(16.4)).toEqual(' (16.4%)'); + }); +}); + +describe('AgentUpgradeStatus', () => { + function render(props: any) { + const renderer = createFleetTestRendererMock(); + + return renderer.render(); + } + + const badgeLabels = [ + 'Upgrade requested', + 'Upgrade scheduled', + 'Upgrade downloading', + 'Upgrade extracting', + 'Upgrade replacing', + 'Upgrade restarting', + 'Upgrade monitoring', + 'Upgrade rolled back', + 'Upgrade failed', + ]; + + function expectNotInDocument(results: any, texts: string[]) { + texts.forEach((text) => { + expect(results.queryByText(text)).not.toBeInTheDocument(); + }); + } + + function expectUpgradeStatusBadgeLabel(results: any, text: string) { + expect(results.queryByText(text)).toBeInTheDocument(); + expectNotInDocument( + results, + badgeLabels.filter((label) => label !== text) + ); + } + + function expectNoUpgradeStatusBadges(results: any) { + expectNotInDocument(results, badgeLabels); + } + + async function expectTooltip(results: any, text: string) { + fireEvent.mouseOver(results.getByText('Info')); + await waitFor(() => { + expect(results.getByText(text)).toBeInTheDocument(); + }); + } + + describe('with agent upgrade details', () => { + it('should render UPG_REQUESTED state correctly', async () => { + const results = render({ + agentUpgradeDetails: { + target_version: 'XXX', + action_id: 'xxx', + state: 'UPG_REQUESTED', + }, + }); + + expectUpgradeStatusBadgeLabel(results, 'Upgrade requested'); + await expectTooltip(results, 'The agent has requested an upgrade.'); + }); + + it('should render UPG_SCHEDULED state correctly', async () => { + const results = render({ + agentUpgradeDetails: { + target_version: 'XXX', + action_id: 'xxx', + state: 'UPG_SCHEDULED', + metadata: { + scheduled_at: getDateString(200), + }, + }, + }); + + expectUpgradeStatusBadgeLabel(results, 'Upgrade scheduled'); + await expectTooltip( + results, + 'The agent has been instructed to upgrade. The upgrade will start in less than 4 hours.' + ); + }); + + it('should render UPG_DOWNLOADING state correctly', async () => { + const results = render({ + agentUpgradeDetails: { + target_version: 'XXX', + action_id: 'xxx', + state: 'UPG_DOWNLOADING', + metadata: { + download_percent: 16.4, + }, + }, + }); + + expectUpgradeStatusBadgeLabel(results, 'Upgrade downloading'); + await expectTooltip(results, 'Downloading the new agent artifact version (16.4%).'); + }); + + it('should render UPG_EXTRACTING state correctly', async () => { + const results = render({ + agentUpgradeDetails: { + target_version: 'XXX', + action_id: 'xxx', + state: 'UPG_EXTRACTING', + }, + }); + + expectUpgradeStatusBadgeLabel(results, 'Upgrade extracting'); + await expectTooltip(results, 'The new agent artifact is extracting.'); + }); + + it('should render UPG_REPLACING state correctly', async () => { + const results = render({ + agentUpgradeDetails: { + target_version: 'XXX', + action_id: 'xxx', + state: 'UPG_REPLACING', + }, + }); + + expectUpgradeStatusBadgeLabel(results, 'Upgrade replacing'); + await expectTooltip(results, 'Replacing the agent artifact version.'); + }); + + it('should render UPG_RESTARTING state correctly', async () => { + const results = render({ + agentUpgradeDetails: { + target_version: 'XXX', + action_id: 'xxx', + state: 'UPG_RESTARTING', + }, + }); + + expectUpgradeStatusBadgeLabel(results, 'Upgrade restarting'); + await expectTooltip(results, 'The agent is restarting to apply the update.'); + }); + + it('should render UPG_WATCHING state correctly', async () => { + const results = render({ + agentUpgradeDetails: { + target_version: 'XXX', + action_id: 'xxx', + state: 'UPG_WATCHING', + }, + }); + + expectUpgradeStatusBadgeLabel(results, 'Upgrade monitoring'); + await expectTooltip(results, 'Monitoring the new agent version for errors.'); + }); + + it('should render UPG_ROLLBACK state correctly', async () => { + const results = render({ + agentUpgradeDetails: { + target_version: 'XXX', + action_id: 'xxx', + state: 'UPG_ROLLBACK', + }, + }); + + expectUpgradeStatusBadgeLabel(results, 'Upgrade rolled back'); + await expectTooltip(results, 'Upgrade unsuccessful. Rolling back to previous version.'); + }); + + it('should render UPG_FAILED state correctly', async () => { + const results = render({ + agentUpgradeDetails: { + target_version: 'XXX', + action_id: 'xxx', + state: 'UPG_FAILED', + metadata: { + failed_state: 'UPG_DOWNLOADING', + error_msg: 'Something went wrong', + }, + }, + }); + + expectUpgradeStatusBadgeLabel(results, 'Upgrade failed'); + await expectTooltip(results, 'Upgrade failed: Something went wrong.'); + }); + }); + + describe('with no agent upgrade details', () => { + it('should render a badge with no tooltip if the agent is upgradable', () => { + const results = render({ + isAgentUpgradable: true, + }); + + expectNoUpgradeStatusBadges(results); + expect(results.queryByText('Upgrade available')).toBeInTheDocument(); + expect(results.queryAllByText('Info')).toEqual([]); + }); + + // Unskip this test when minVersion is set. + it.skip('should render an icon with tooltip if the agent is upgrading', async () => { + const results = render({ + agentUpgradeStartedAt: '2023-10-03T14:34:12Z', + agentUpgradedAt: null, + }); + + expectNoUpgradeStatusBadges(results); + expect(results.getByText('Info')).toBeInTheDocument(); + + await expectTooltip( + results, + 'Detailed upgrade status is available for Elastic Agents on version 8.12 and higher.' + ); + }); + + it('should not render anything if the agent is neither upgrading nor upgradable', () => { + const results = render({ + agentUpgradeStartedAt: null, + agentUpgradedAt: '2023-10-03T14:34:12Z', + }); + expectNoUpgradeStatusBadges(results); + expect( + results.container.querySelector('[data-euiicon-type="iInCircle"]') + ).not.toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_upgrade_status.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_upgrade_status.tsx new file mode 100644 index 00000000000000..de9767c2f0b548 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/agent_upgrade_status.tsx @@ -0,0 +1,269 @@ +/* + * 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, { useMemo } from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; + +import type { AgentUpgradeDetails } from '../../../../../../../common/types'; + +/** + * Returns a user-friendly string for the estimated remaining time until the upgrade is scheduled. + */ +export function getUpgradeStartDelay(scheduledAt?: string): string { + const timeDiffMillis = Date.parse(scheduledAt || '') - Date.now(); + + if (timeDiffMillis < 0) { + // The scheduled time should not be in the past, this would indicate an issue. + // We choose not to provide a time estimation rather than negative duration. + return ''; + } + + if (timeDiffMillis < 15 * 6e4) { + return ' The upgrade will start in less than 15 minutes.'; + } + if (timeDiffMillis < 30 * 6e4) { + return ' The upgrade will start in less than 30 minutes.'; + } + if (timeDiffMillis < 60 * 6e4) { + return ' The upgrade will start in less than 1 hour.'; + } + return ` The upgrade will start in less than ${Math.ceil(timeDiffMillis / 36e5)} hours.`; +} + +export function getDownloadEstimate(downloadPercent?: number): string { + if (!downloadPercent || downloadPercent === 0) { + return ''; + } + + return ` (${downloadPercent}%)`; +} + +function getStatusComponents(agentUpgradeDetails?: AgentUpgradeDetails) { + switch (agentUpgradeDetails?.state) { + case 'UPG_REQUESTED': + return { + Badge: ( + + + + ), + TooltipText: ( + + ), + }; + case 'UPG_SCHEDULED': + return { + Badge: ( + + + + ), + TooltipText: ( + + ), + }; + case 'UPG_DOWNLOADING': + return { + Badge: ( + + + + ), + TooltipText: ( + + ), + }; + case 'UPG_EXTRACTING': + return { + Badge: ( + + + + ), + TooltipText: ( + + ), + }; + case 'UPG_REPLACING': + return { + Badge: ( + + + + ), + TooltipText: ( + + ), + }; + case 'UPG_RESTARTING': + return { + Badge: ( + + + + ), + TooltipText: ( + + ), + }; + case 'UPG_WATCHING': + return { + Badge: ( + + + + ), + TooltipText: ( + + ), + }; + case 'UPG_ROLLBACK': + return { + Badge: ( + + + + ), + TooltipText: ( + + ), + }; + case 'UPG_FAILED': + return { + Badge: ( + + + + ), + TooltipText: ( + + ), + }; + default: + return null; + } +} + +export const AgentUpgradeStatus: React.FC<{ + isAgentUpgradable: boolean; + agentUpgradeStartedAt?: string | null; + agentUpgradedAt?: string | null; + agentUpgradeDetails?: AgentUpgradeDetails; +}> = ({ isAgentUpgradable, agentUpgradeStartedAt, agentUpgradedAt, agentUpgradeDetails }) => { + const isAgentUpgrading = useMemo( + () => agentUpgradeStartedAt && !agentUpgradedAt, + [agentUpgradeStartedAt, agentUpgradedAt] + ); + const status = useMemo(() => getStatusComponents(agentUpgradeDetails), [agentUpgradeDetails]); + const minVersion = undefined; // Change this to a string in order for a tooltip to render for upgrading agents with no upgrade details. + + if (isAgentUpgradable) { + return ( + + + + ); + } + + if (agentUpgradeDetails && status) { + return ( + + {status.Badge} + + + + + ); + } + + if (minVersion && isAgentUpgrading) { + return ( + + } + color="subdued" + /> + ); + } + + return null; +}; diff --git a/x-pack/plugins/fleet/server/constants/mappings.ts b/x-pack/plugins/fleet/server/constants/mappings.ts index 9ae93533968034..75ff9cbb549be8 100644 --- a/x-pack/plugins/fleet/server/constants/mappings.ts +++ b/x-pack/plugins/fleet/server/constants/mappings.ts @@ -298,6 +298,47 @@ export const AGENT_MAPPINGS = { upgrade_status: { type: 'keyword', }, + upgrade_details: { + properties: { + target_version: { + type: 'text', + fields: { + keyword: { + type: 'keyword', + ignore_above: 16, + }, + }, + }, + action_id: { + type: 'keyword', + }, + state: { + type: 'keyword', + }, + metadata: { + properties: { + scheduled_at: { + type: 'date', + }, + download_percent: { + type: 'double', + }, + failed_state: { + type: 'keyword', + }, + error_msg: { + type: 'text', + fields: { + keyword: { + type: 'keyword', + ignore_above: 1024, + }, + }, + }, + }, + }, + }, + }, // added to allow validation on status field status: { type: 'keyword', diff --git a/x-pack/plugins/fleet/server/services/agents/helpers.ts b/x-pack/plugins/fleet/server/services/agents/helpers.ts index 4aaab95e9d1acf..6da24cdbfb55ce 100644 --- a/x-pack/plugins/fleet/server/services/agents/helpers.ts +++ b/x-pack/plugins/fleet/server/services/agents/helpers.ts @@ -66,6 +66,7 @@ export function searchHitToAgent( unenrollment_started_at: hit._source?.unenrollment_started_at, upgraded_at: hit._source?.upgraded_at, upgrade_started_at: hit._source?.upgrade_started_at, + upgrade_details: hit._source?.upgrade_details, access_api_key_id: hit._source?.access_api_key_id, default_api_key_id: hit._source?.default_api_key_id, policy_id: hit._source?.policy_id, diff --git a/x-pack/plugins/fleet/server/types/so_attributes.ts b/x-pack/plugins/fleet/server/types/so_attributes.ts index 8a53ed18ff4336..f6e7506d81ecf8 100644 --- a/x-pack/plugins/fleet/server/types/so_attributes.ts +++ b/x-pack/plugins/fleet/server/types/so_attributes.ts @@ -15,6 +15,7 @@ import type { ShipperOutput, KafkaAcknowledgeReliabilityLevel, KafkaConnectionTypeType, + AgentUpgradeDetails, } from '../../common/types'; import type { AgentType, FleetServerAgentComponent } from '../../common/types/models'; @@ -73,6 +74,7 @@ export interface AgentSOAttributes { unenrollment_started_at?: string; upgraded_at?: string | null; upgrade_started_at?: string | null; + upgrade_details?: AgentUpgradeDetails; access_api_key_id?: string; default_api_key?: string; default_api_key_id?: string; From 841eb0a63361e9bbf51d01a2b5e0173148b44e5e Mon Sep 17 00:00:00 2001 From: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:28:55 +0200 Subject: [PATCH 51/87] Update fleet-settings.asciidoc with supported output types (#167042) Updated output types in doc. --- docs/settings/fleet-settings.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/settings/fleet-settings.asciidoc b/docs/settings/fleet-settings.asciidoc index a222e4e5af5789..d3cad6b4dfdbc9 100644 --- a/docs/settings/fleet-settings.asciidoc +++ b/docs/settings/fleet-settings.asciidoc @@ -188,7 +188,7 @@ NOTE: The `xpack.fleet.outputs` settings are intended for advanced configuration `name`::: Output name. `type`::: - Type of Output. Currently we only support "elasticsearch". + Type of Output. Currently we support "elasticsearch", "logstash", "kafka". `hosts`::: Array that contains the list of host for that output. `config`::: From f660af7923de350a85d0989b889e65a9dd036c3d Mon Sep 17 00:00:00 2001 From: Coen Warmer Date: Tue, 17 Oct 2023 14:31:16 +0200 Subject: [PATCH 52/87] ESLint i18n Helper Rule: Documentation fixes (#169076) --- .eslintrc.js | 17 +++++++++++++++++ packages/kbn-eslint-plugin-i18n/README.mdx | 4 ++++ .../get_i18n_identifier_from_file_path.ts | 2 +- packages/kbn-eslint-plugin-i18n/index.ts | 2 +- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 67cb263bcf4938..700a9de2a5a769 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -924,6 +924,23 @@ module.exports = { ], rules: { '@kbn/telemetry/event_generating_elements_should_be_instrumented': 'error', + }, + }, + { + files: [ + 'x-pack/plugins/aiops/**/*.{tsx}', + 'x-pack/plugins/apm/**/*.{tsx}', + 'x-pack/plugins/exploratory_view/**/*.{tsx}', + 'x-pack/plugins/infra/**/*.{tsx}', + 'x-pack/plugins/observability/**/*.{tsx}', + 'x-pack/plugins/observability_ai_assistant/**/*.{tsx}', + 'x-pack/plugins/observability_onboarding/**/*.{tsx}', + 'x-pack/plugins/observability_shared/**/*.{tsx}', + 'x-pack/plugins/profiling/**/*.{tsx}', + 'x-pack/plugins/synthetics/**/*.{tsx}', + 'x-pack/plugins/ux/**/*.{tsx}', + ], + rules: { '@kbn/i18n/strings_should_be_translated_with_i18n': 'warn', '@kbn/i18n/strings_should_be_translated_with_formatted_message': 'warn', }, diff --git a/packages/kbn-eslint-plugin-i18n/README.mdx b/packages/kbn-eslint-plugin-i18n/README.mdx index 0a22ff846726ee..f72f01c06a632d 100644 --- a/packages/kbn-eslint-plugin-i18n/README.mdx +++ b/packages/kbn-eslint-plugin-i18n/README.mdx @@ -8,6 +8,10 @@ tags: ['kibana', 'dev', 'contributor', 'operations', 'eslint', 'i18n'] `@kbn/eslint-plugin-i18n` is an ESLint plugin providing custom rules for validating JSXCode in the Kibana repo to make sure they are translated. +Note: At the moment these rules only work for apps that are inside `/x-pack/plugins`. + +If you want to enable this rule on code that is outside of this path, adjust `/helpers/get_i18n_identifier_from_file_path.ts`. + ## `@kbn/i18n/strings_should_be_translated_with_i18n` This rule warns engineers to translate their strings by using i18n.translate from the '@kbn/i18n' package. It provides an autofix that takes into account the context of the translatable string in the JSX tree to generate a translation ID. diff --git a/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_identifier_from_file_path.ts b/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_identifier_from_file_path.ts index 360f70e0b3fa82..288e2692bd76af 100644 --- a/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_identifier_from_file_path.ts +++ b/packages/kbn-eslint-plugin-i18n/helpers/get_i18n_identifier_from_file_path.ts @@ -25,5 +25,5 @@ export function getI18nIdentifierFromFilePath(fileName: string, cwd: string) { return i18nrc && i18nrc.paths ? findKey(i18nrc.paths, (v) => v === path) ?? 'app_not_found_in_i18nrc' - : 'app_not_found_in_i18nrc'; + : 'could_not_find_i18nrc'; } diff --git a/packages/kbn-eslint-plugin-i18n/index.ts b/packages/kbn-eslint-plugin-i18n/index.ts index d6fba728b7d219..be5661cf46dec8 100644 --- a/packages/kbn-eslint-plugin-i18n/index.ts +++ b/packages/kbn-eslint-plugin-i18n/index.ts @@ -10,7 +10,7 @@ import { StringsShouldBeTranslatedWithI18n } from './rules/strings_should_be_tra import { StringsShouldBeTranslatedWithFormattedMessage } from './rules/strings_should_be_translated_with_formatted_message'; /** - * Custom ESLint rules, add `'@kbn/eslint-plugin-telemetry'` to your eslint config to use them + * Custom ESLint rules, add `'@kbn/eslint-plugin-i18n'` to your eslint config to use them * @internal */ export const rules = { From a94fd4f9e08a6313a04778c6690d60ff7c4f1778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20FOUCRET?= Date: Tue, 17 Oct 2023 14:33:18 +0200 Subject: [PATCH 53/87] [Observability - AI Assistant] Hide indices used to store conversations and knowledge base. (#168845) --- .../plugins/observability_ai_assistant/server/service/index.ts | 2 ++ 1 file changed, 2 insertions(+) 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 978a8a2de6111e..e2f6354725f1aa 100644 --- a/x-pack/plugins/observability_ai_assistant/server/service/index.ts +++ b/x-pack/plugins/observability_ai_assistant/server/service/index.ts @@ -119,6 +119,7 @@ export class ObservabilityAIAssistantService { number_of_shards: 1, auto_expand_replicas: '0-1', refresh_interval: '1s', + hidden: true, }, }, }); @@ -176,6 +177,7 @@ export class ObservabilityAIAssistantService { number_of_shards: 1, auto_expand_replicas: '0-1', refresh_interval: '1s', + hidden: true, }, }, }); From 9cc7b8cda5ca99641b865ea6158e9b82981f27d7 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 17 Oct 2023 08:45:16 -0400 Subject: [PATCH 54/87] feat(slo): store search state in url (#168528) --- .../burn_rate_rule_editor.tsx | 2 +- .../embeddable/slo/overview/slo_overview.tsx | 7 ++- .../embeddable/slo/overview/slo_selector.tsx | 6 ++- .../__storybook_mocks__/use_fetch_slo_list.ts | 2 +- .../public/hooks/slo/use_fetch_slo_details.ts | 6 +-- .../public/hooks/slo/use_fetch_slo_list.ts | 11 ++--- .../pages/slo_details/slo_details.test.tsx | 26 +++++------ .../public/pages/slo_details/slo_details.tsx | 2 +- .../public/pages/slo_edit/slo_edit.test.tsx | 22 ++++----- .../public/pages/slo_edit/slo_edit.tsx | 2 +- .../public/pages/slos/components/slo_list.tsx | 43 ++++++++++------- ...es.tsx => slo_list_search_bar.stories.tsx} | 19 ++++---- ...r_sort_bar.tsx => slo_list_search_bar.tsx} | 31 +++++++------ .../pages/slos/hooks/use_url_search_state.ts | 46 +++++++++++++++++++ .../public/pages/slos/slos.test.tsx | 41 ++++++++--------- .../observability/public/pages/slos/slos.tsx | 4 +- .../pages/slos_welcome/slos_welcome.test.tsx | 6 +-- .../pages/slos_welcome/slos_welcome.tsx | 4 +- 18 files changed, 170 insertions(+), 110 deletions(-) rename x-pack/plugins/observability/public/pages/slos/components/{slo_list_search_filter_sort_bar.stories.tsx => slo_list_search_bar.stories.tsx} (55%) rename x-pack/plugins/observability/public/pages/slos/components/{slo_list_search_filter_sort_bar.tsx => slo_list_search_bar.tsx} (88%) create mode 100644 x-pack/plugins/observability/public/pages/slos/hooks/use_url_search_state.ts diff --git a/x-pack/plugins/observability/public/components/burn_rate_rule_editor/burn_rate_rule_editor.tsx b/x-pack/plugins/observability/public/components/burn_rate_rule_editor/burn_rate_rule_editor.tsx index 7e0e88d6c148d3..3aa7651320bc3c 100644 --- a/x-pack/plugins/observability/public/components/burn_rate_rule_editor/burn_rate_rule_editor.tsx +++ b/x-pack/plugins/observability/public/components/burn_rate_rule_editor/burn_rate_rule_editor.tsx @@ -31,7 +31,7 @@ type Props = Pick< export function BurnRateRuleEditor(props: Props) { const { setRuleParams, ruleParams, errors } = props; - const { isLoading: loadingInitialSlo, slo: initialSlo } = useFetchSloDetails({ + const { isLoading: loadingInitialSlo, data: initialSlo } = useFetchSloDetails({ sloId: ruleParams?.sloId, }); diff --git a/x-pack/plugins/observability/public/embeddable/slo/overview/slo_overview.tsx b/x-pack/plugins/observability/public/embeddable/slo/overview/slo_overview.tsx index e190196acd794c..9ee756c0235b80 100644 --- a/x-pack/plugins/observability/public/embeddable/slo/overview/slo_overview.tsx +++ b/x-pack/plugins/observability/public/embeddable/slo/overview/slo_overview.tsx @@ -26,7 +26,12 @@ export function SloOverview({ sloId, sloInstanceId, lastReloadRequestTime }: Emb application: { navigateToUrl }, http: { basePath }, } = useKibana().services; - const { isLoading, slo, refetch, isRefetching } = useFetchSloDetails({ + const { + isLoading, + data: slo, + refetch, + isRefetching, + } = useFetchSloDetails({ sloId, instanceId: sloInstanceId, }); diff --git a/x-pack/plugins/observability/public/embeddable/slo/overview/slo_selector.tsx b/x-pack/plugins/observability/public/embeddable/slo/overview/slo_selector.tsx index 468358127bd18f..8ad4985e0096d6 100644 --- a/x-pack/plugins/observability/public/embeddable/slo/overview/slo_selector.tsx +++ b/x-pack/plugins/observability/public/embeddable/slo/overview/slo_selector.tsx @@ -26,7 +26,11 @@ export function SloSelector({ initialSlo, onSelected, hasError }: Props) { const [options, setOptions] = useState>>([]); const [selectedOptions, setSelectedOptions] = useState>>(); const [searchValue, setSearchValue] = useState(''); - const { isInitialLoading, isLoading, sloList } = useFetchSloList({ + const { + isInitialLoading, + isLoading, + data: sloList, + } = useFetchSloList({ kqlQuery: `slo.name: ${searchValue.replaceAll(' ', '*')}*`, }); diff --git a/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_slo_list.ts b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_slo_list.ts index 2faa0887b82ea6..4e7d1889e5bb04 100644 --- a/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_slo_list.ts +++ b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_slo_list.ts @@ -15,7 +15,7 @@ export const useFetchSloList = (): UseFetchSloListResponse => { isRefetching: false, isError: false, isSuccess: true, - sloList, + data: sloList, refetch: function () {} as UseFetchSloListResponse['refetch'], }; }; diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_details.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_details.ts index 38f980ee1bdc95..ad5511433522ec 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_details.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_details.ts @@ -5,13 +5,13 @@ * 2.0. */ +import { ALL_VALUE, GetSLOResponse } from '@kbn/slo-schema'; import { QueryObserverResult, RefetchOptions, RefetchQueryFilters, useQuery, } from '@tanstack/react-query'; -import { ALL_VALUE, GetSLOResponse, SLOWithSummaryResponse } from '@kbn/slo-schema'; import { useKibana } from '../../utils/kibana_react'; import { sloKeys } from './query_key_factory'; @@ -21,7 +21,7 @@ export interface UseFetchSloDetailsResponse { isRefetching: boolean; isSuccess: boolean; isError: boolean; - slo: SLOWithSummaryResponse | undefined; + data: GetSLOResponse | undefined; refetch: ( options?: (RefetchOptions & RefetchQueryFilters) | undefined ) => Promise>; @@ -65,7 +65,7 @@ export function useFetchSloDetails({ ); return { - slo: data, + data, isLoading, isInitialLoading, isRefetching, diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts index 22a918eb231279..a4a67b0aecceb5 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts @@ -33,7 +33,7 @@ export interface UseFetchSloListResponse { isRefetching: boolean; isSuccess: boolean; isError: boolean; - sloList: FindSLOResponse | undefined; + data: FindSLOResponse | undefined; refetch: ( options?: (RefetchOptions & RefetchQueryFilters) | undefined ) => Promise>; @@ -48,16 +48,13 @@ export function useFetchSloList({ sortBy = 'status', sortDirection = 'desc', shouldRefetch, -}: SLOListParams | undefined = {}): UseFetchSloListResponse { +}: SLOListParams = {}): UseFetchSloListResponse { const { http, notifications: { toasts }, } = useKibana().services; const queryClient = useQueryClient(); - - const [stateRefetchInterval, setStateRefetchInterval] = useState( - SHORT_REFETCH_INTERVAL - ); + const [stateRefetchInterval, setStateRefetchInterval] = useState(SHORT_REFETCH_INTERVAL); const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data, refetch } = useQuery( { @@ -115,7 +112,7 @@ export function useFetchSloList({ ); return { - sloList: data, + data, isInitialLoading, isLoading, isRefetching, diff --git a/x-pack/plugins/observability/public/pages/slo_details/slo_details.test.tsx b/x-pack/plugins/observability/public/pages/slo_details/slo_details.test.tsx index 5dad78763fe040..f31d36c8222648 100644 --- a/x-pack/plugins/observability/public/pages/slo_details/slo_details.test.tsx +++ b/x-pack/plugins/observability/public/pages/slo_details/slo_details.test.tsx @@ -124,7 +124,7 @@ describe('SLO Details Page', () => { it('navigates to the SLO List page', async () => { const slo = buildSlo(); useParamsMock.mockReturnValue(slo.id); - useFetchSloDetailsMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); useLicenseMock.mockReturnValue({ hasAtLeast: () => false }); render(); @@ -135,7 +135,7 @@ describe('SLO Details Page', () => { it('renders the PageNotFound when the SLO cannot be found', async () => { useParamsMock.mockReturnValue('nonexistent'); - useFetchSloDetailsMock.mockReturnValue({ isLoading: false, slo: undefined }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: undefined }); useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); render(); @@ -146,7 +146,7 @@ describe('SLO Details Page', () => { it('renders the loading spinner when fetching the SLO', async () => { const slo = buildSlo(); useParamsMock.mockReturnValue(slo.id); - useFetchSloDetailsMock.mockReturnValue({ isLoading: true, slo: undefined }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: true, data: undefined }); useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); render(); @@ -159,7 +159,7 @@ describe('SLO Details Page', () => { it('renders the SLO details page with loading charts when summary data is loading', async () => { const slo = buildSlo({ id: HEALTHY_STEP_DOWN_ROLLING_SLO }); useParamsMock.mockReturnValue(slo.id); - useFetchSloDetailsMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); useFetchHistoricalSummaryMock.mockReturnValue({ isLoading: true, @@ -178,7 +178,7 @@ describe('SLO Details Page', () => { it('renders the SLO details page with the overview and chart panels', async () => { const slo = buildSlo({ id: HEALTHY_STEP_DOWN_ROLLING_SLO }); useParamsMock.mockReturnValue(slo.id); - useFetchSloDetailsMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); render(); @@ -194,7 +194,7 @@ describe('SLO Details Page', () => { it("renders a 'Edit' button under actions menu", async () => { const slo = buildSlo(); useParamsMock.mockReturnValue(slo.id); - useFetchSloDetailsMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); render(); @@ -206,7 +206,7 @@ describe('SLO Details Page', () => { it("renders a 'Create alert rule' button under actions menu", async () => { const slo = buildSlo(); useParamsMock.mockReturnValue(slo.id); - useFetchSloDetailsMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); render(); @@ -218,7 +218,7 @@ describe('SLO Details Page', () => { it("renders a 'Manage rules' button under actions menu", async () => { const slo = buildSlo(); useParamsMock.mockReturnValue(slo.id); - useFetchSloDetailsMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); render(); @@ -230,7 +230,7 @@ describe('SLO Details Page', () => { it("renders a 'Clone' button under actions menu", async () => { const slo = buildSlo(); useParamsMock.mockReturnValue(slo.id); - useFetchSloDetailsMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); render(); @@ -271,7 +271,7 @@ describe('SLO Details Page', () => { it("renders a 'Delete' button under actions menu", async () => { const slo = buildSlo(); useParamsMock.mockReturnValue(slo.id); - useFetchSloDetailsMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); render(); @@ -301,7 +301,7 @@ describe('SLO Details Page', () => { it('renders the Overview tab by default', async () => { const slo = buildSlo(); useParamsMock.mockReturnValue(slo.id); - useFetchSloDetailsMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); useFetchActiveAlertsMock.mockReturnValue({ isLoading: false, @@ -320,7 +320,7 @@ describe('SLO Details Page', () => { it("renders a 'Explore in APM' button under actions menu", async () => { const slo = buildSlo({ indicator: buildApmAvailabilityIndicator() }); useParamsMock.mockReturnValue(slo.id); - useFetchSloDetailsMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); render(); @@ -334,7 +334,7 @@ describe('SLO Details Page', () => { it("does not render a 'Explore in APM' button under actions menu", async () => { const slo = buildSlo(); useParamsMock.mockReturnValue(slo.id); - useFetchSloDetailsMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloDetailsMock.mockReturnValue({ isLoading: false, data: slo }); useLicenseMock.mockReturnValue({ hasAtLeast: () => true }); render(); diff --git a/x-pack/plugins/observability/public/pages/slo_details/slo_details.tsx b/x-pack/plugins/observability/public/pages/slo_details/slo_details.tsx index 6b50fbde29268b..195cb164e5197b 100644 --- a/x-pack/plugins/observability/public/pages/slo_details/slo_details.tsx +++ b/x-pack/plugins/observability/public/pages/slo_details/slo_details.tsx @@ -45,7 +45,7 @@ export function SloDetailsPage() { const sloInstanceId = useGetInstanceIdQueryParam(); const { storeAutoRefreshState, getAutoRefreshState } = useAutoRefreshStorage(); const [isAutoRefreshing, setIsAutoRefreshing] = useState(getAutoRefreshState()); - const { isLoading, slo } = useFetchSloDetails({ + const { isLoading, data: slo } = useFetchSloDetails({ sloId, instanceId: sloInstanceId, shouldRefetch: isAutoRefreshing, diff --git a/x-pack/plugins/observability/public/pages/slo_edit/slo_edit.test.tsx b/x-pack/plugins/observability/public/pages/slo_edit/slo_edit.test.tsx index c38689200a164b..b158094a67aabe 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/slo_edit.test.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/slo_edit.test.tsx @@ -147,7 +147,7 @@ describe('SLO Edit Page', () => { .spyOn(Router, 'useLocation') .mockReturnValue({ pathname: 'foo', search: '', state: '', hash: '' }); - useFetchSloMock.mockReturnValue({ isLoading: false, slo: undefined }); + useFetchSloMock.mockReturnValue({ isLoading: false, data: undefined }); useFetchIndicesMock.mockReturnValue({ isLoading: false, @@ -201,7 +201,7 @@ describe('SLO Edit Page', () => { .spyOn(Router, 'useLocation') .mockReturnValue({ pathname: 'foo', search: '', state: '', hash: '' }); - useFetchSloMock.mockReturnValue({ isLoading: false, slo: undefined }); + useFetchSloMock.mockReturnValue({ isLoading: false, data: undefined }); useFetchIndicesMock.mockReturnValue({ isLoading: false, @@ -237,7 +237,7 @@ describe('SLO Edit Page', () => { .spyOn(Router, 'useLocation') .mockReturnValue({ pathname: 'foo', search: '', state: '', hash: '' }); - useFetchSloMock.mockReturnValue({ isLoading: false, slo: undefined }); + useFetchSloMock.mockReturnValue({ isLoading: false, data: undefined }); useFetchIndicesMock.mockReturnValue({ isLoading: false, @@ -287,7 +287,7 @@ describe('SLO Edit Page', () => { data: ['some-index'], }); - useFetchSloMock.mockReturnValue({ isLoading: false, slo: undefined }); + useFetchSloMock.mockReturnValue({ isLoading: false, data: undefined }); const mockCreate = jest.fn(); const mockUpdate = jest.fn(); @@ -377,7 +377,7 @@ describe('SLO Edit Page', () => { .spyOn(Router, 'useLocation') .mockReturnValue({ pathname: 'foo', search: '', state: '', hash: '' }); - useFetchSloMock.mockReturnValue({ isLoading: false, slo: undefined }); + useFetchSloMock.mockReturnValue({ isLoading: false, data: undefined }); useFetchApmSuggestionsMock.mockReturnValue({ suggestions: ['cartService'], @@ -428,7 +428,7 @@ describe('SLO Edit Page', () => { .spyOn(Router, 'useLocation') .mockReturnValue({ pathname: 'foo', search: '', state: '', hash: '' }); - useFetchSloMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloMock.mockReturnValue({ isLoading: false, data: slo }); useFetchIndicesMock.mockReturnValue({ isLoading: false, @@ -496,7 +496,7 @@ describe('SLO Edit Page', () => { data: ['some-index'], }); - useFetchSloMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloMock.mockReturnValue({ isLoading: false, data: slo }); const mockCreate = jest.fn(); const mockUpdate = jest.fn(); @@ -537,7 +537,7 @@ describe('SLO Edit Page', () => { .spyOn(Router, 'useLocation') .mockReturnValue({ pathname: 'foo', search: '', state: '', hash: '' }); - useFetchSloMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloMock.mockReturnValue({ isLoading: false, data: slo }); useFetchApmSuggestionsMock.mockReturnValue({ suggestions: ['cartService'], @@ -607,7 +607,7 @@ describe('SLO Edit Page', () => { .spyOn(Router, 'useLocation') .mockReturnValue({ pathname: 'foo', search: '', state: '', hash: '' }); - useFetchSloMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloMock.mockReturnValue({ isLoading: false, data: slo }); useFetchIndicesMock.mockReturnValue({ isLoading: false, @@ -648,7 +648,7 @@ describe('SLO Edit Page', () => { .spyOn(Router, 'useLocation') .mockReturnValue({ pathname: 'foo', search: '', state: '', hash: '' }); - useFetchSloMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloMock.mockReturnValue({ isLoading: false, data: slo }); useFetchIndicesMock.mockReturnValue({ isLoading: false, @@ -693,7 +693,7 @@ describe('SLO Edit Page', () => { .spyOn(Router, 'useLocation') .mockReturnValue({ pathname: 'foo', search: 'create-rule=true', state: '', hash: '' }); - useFetchSloMock.mockReturnValue({ isLoading: false, slo }); + useFetchSloMock.mockReturnValue({ isLoading: false, data: slo }); useFetchIndicesMock.mockReturnValue({ isLoading: false, diff --git a/x-pack/plugins/observability/public/pages/slo_edit/slo_edit.tsx b/x-pack/plugins/observability/public/pages/slo_edit/slo_edit.tsx index a9da5c0c0ee972..1f5cc7f38ed3c0 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/slo_edit.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/slo_edit.tsx @@ -33,7 +33,7 @@ export function SloEditPage() { const { sloId } = useParams<{ sloId: string | undefined }>(); const { hasAtLeast } = useLicense(); const hasRightLicense = hasAtLeast('platinum'); - const { slo, isInitialLoading } = useFetchSloDetails({ sloId }); + const { data: slo, isInitialLoading } = useFetchSloDetails({ sloId }); useBreadcrumbs([ { diff --git a/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx b/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx index 651a97d3644391..380d0100db1a1b 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx @@ -9,27 +9,35 @@ import { EuiFlexGroup, EuiFlexItem, EuiPagination } from '@elastic/eui'; import { useIsMutating } from '@tanstack/react-query'; import React, { useState } from 'react'; import { useFetchSloList } from '../../../hooks/slo/use_fetch_slo_list'; +import { useUrlSearchState } from '../hooks/use_url_search_state'; import { SloListItems } from './slo_list_items'; -import { SloListSearchFilterSortBar, SortField } from './slo_list_search_filter_sort_bar'; +import { SloListSearchBar, SortField } from './slo_list_search_bar'; export interface Props { autoRefresh: boolean; } export function SloList({ autoRefresh }: Props) { - const [activePage, setActivePage] = useState(0); - const [query, setQuery] = useState(''); - const [sort, setSort] = useState('status'); + const { state, store: storeState } = useUrlSearchState(); + const [page, setPage] = useState(state.page); + const [query, setQuery] = useState(state.kqlQuery); + const [sort, setSort] = useState(state.sort.by); + const [direction] = useState<'asc' | 'desc'>(state.sort.direction); - const { isLoading, isRefetching, isError, sloList } = useFetchSloList({ - page: activePage + 1, + const { + isLoading, + isRefetching, + isError, + data: sloList, + } = useFetchSloList({ + page: page + 1, kqlQuery: query, sortBy: sort, - sortDirection: 'desc', + sortDirection: direction, shouldRefetch: autoRefresh, }); - const { results = [], total = 0, perPage = 0 } = sloList || {}; + const { results = [], total = 0, perPage = 0 } = sloList ?? {}; const isCreatingSlo = Boolean(useIsMutating(['creatingSlo'])); const isCloningSlo = Boolean(useIsMutating(['cloningSlo'])); @@ -37,40 +45,43 @@ export function SloList({ autoRefresh }: Props) { const isDeletingSlo = Boolean(useIsMutating(['deleteSlo'])); const handlePageClick = (pageNumber: number) => { - setActivePage(pageNumber); + setPage(pageNumber); + storeState({ page: pageNumber }); }; const handleChangeQuery = (newQuery: string) => { - setActivePage(0); + setPage(0); setQuery(newQuery); + storeState({ page: 0, kqlQuery: newQuery }); }; - const handleChangeSort = (newSort: SortField | undefined) => { - setActivePage(0); + const handleChangeSort = (newSort: SortField) => { + setPage(0); setSort(newSort); + storeState({ page: 0, sort: { by: newSort, direction: state.sort.direction } }); }; return ( - - - {results.length ? ( + {total > 0 ? ( diff --git a/x-pack/plugins/observability/public/pages/slos/components/slo_list_search_filter_sort_bar.stories.tsx b/x-pack/plugins/observability/public/pages/slos/components/slo_list_search_bar.stories.tsx similarity index 55% rename from x-pack/plugins/observability/public/pages/slos/components/slo_list_search_filter_sort_bar.stories.tsx rename to x-pack/plugins/observability/public/pages/slos/components/slo_list_search_bar.stories.tsx index 4b1c31209de3bc..fb39f46e81e966 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/slo_list_search_filter_sort_bar.stories.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/slo_list_search_bar.stories.tsx @@ -9,26 +9,23 @@ import React from 'react'; import { ComponentStory } from '@storybook/react'; import { KibanaReactStorybookDecorator } from '../../../utils/kibana_react.storybook_decorator'; -import { - SloListSearchFilterSortBar as Component, - SloListSearchFilterSortBarProps, -} from './slo_list_search_filter_sort_bar'; +import { SloListSearchBar as Component, Props } from './slo_list_search_bar'; +import { DEFAULT_STATE } from '../hooks/use_url_search_state'; export default { component: Component, - title: 'app/SLO/ListPage/SloListSearchFilterSortBar', + title: 'app/SLO/ListPage/SloListSearchBar', decorators: [KibanaReactStorybookDecorator], }; -const Template: ComponentStory = (props: SloListSearchFilterSortBarProps) => ( - -); +const Template: ComponentStory = (props: Props) => ; -const defaultProps: SloListSearchFilterSortBarProps = { +const defaultProps: Props = { loading: false, onChangeQuery: () => {}, onChangeSort: () => {}, + initialState: DEFAULT_STATE, }; -export const SloListSearchFilterSortBar = Template.bind({}); -SloListSearchFilterSortBar.args = defaultProps; +export const SloListSearchBar = Template.bind({}); +SloListSearchBar.args = defaultProps; diff --git a/x-pack/plugins/observability/public/pages/slos/components/slo_list_search_filter_sort_bar.tsx b/x-pack/plugins/observability/public/pages/slos/components/slo_list_search_bar.tsx similarity index 88% rename from x-pack/plugins/observability/public/pages/slos/components/slo_list_search_filter_sort_bar.tsx rename to x-pack/plugins/observability/public/pages/slos/components/slo_list_search_bar.tsx index c1d9c6b3c3a07d..dc6aebfd3eae70 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/slo_list_search_filter_sort_bar.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/slo_list_search_bar.tsx @@ -22,11 +22,13 @@ import { QueryStringInput } from '@kbn/unified-search-plugin/public'; import React, { useState } from 'react'; import { useCreateDataView } from '../../../hooks/use_create_data_view'; import { useKibana } from '../../../utils/kibana_react'; +import { SearchState } from '../hooks/use_url_search_state'; -export interface SloListSearchFilterSortBarProps { +export interface Props { loading: boolean; + initialState: SearchState; onChangeQuery: (query: string) => void; - onChangeSort: (sort: SortField | undefined) => void; + onChangeSort: (sort: SortField) => void; } export type SortField = 'sli_value' | 'error_budget_consumed' | 'error_budget_remaining' | 'status'; @@ -49,7 +51,6 @@ const SORT_OPTIONS: Array> = [ defaultMessage: 'SLO status', }), type: 'status', - checked: 'on', }, { label: i18n.translate('xpack.observability.slo.list.sortBy.errorBudgetConsumed', { @@ -65,26 +66,26 @@ const SORT_OPTIONS: Array> = [ }, ]; -export function SloListSearchFilterSortBar({ - loading, - onChangeQuery, - onChangeSort, -}: SloListSearchFilterSortBarProps) { +export function SloListSearchBar({ loading, onChangeQuery, onChangeSort, initialState }: Props) { const { data, dataViews, docLinks, http, notifications, storage, uiSettings, unifiedSearch } = useKibana().services; const { dataView } = useCreateDataView({ indexPatternString: '.slo-observability.summary-*' }); + const [query, setQuery] = useState(initialState.kqlQuery); const [isSortPopoverOpen, setSortPopoverOpen] = useState(false); - const [sortOptions, setSortOptions] = useState(SORT_OPTIONS); - const [query, setQuery] = useState(''); - + const [sortOptions, setSortOptions] = useState>>( + SORT_OPTIONS.map((option) => ({ + ...option, + checked: option.type === initialState.sort.by ? 'on' : undefined, + })) + ); const selectedSort = sortOptions.find((option) => option.checked === 'on'); - const handleToggleSortButton = () => setSortPopoverOpen(!isSortPopoverOpen); + const handleToggleSortButton = () => setSortPopoverOpen(!isSortPopoverOpen); const handleChangeSort = (newOptions: Array>) => { setSortOptions(newOptions); setSortPopoverOpen(false); - onChangeSort(newOptions.find((o) => o.checked)?.type); + onChangeSort(newOptions.find((o) => o.checked)!.type); }; return ( @@ -133,7 +134,7 @@ export function SloListSearchFilterSortBar({ > {i18n.translate('xpack.observability.slo.list.sortByType', { defaultMessage: 'Sort by {type}', - values: { type: selectedSort?.label.toLowerCase() || '' }, + values: { type: selectedSort?.label.toLowerCase() ?? '' }, })} } @@ -149,7 +150,7 @@ export function SloListSearchFilterSortBar({ })} > - singleSelection + singleSelection="always" options={sortOptions} onChange={handleChangeSort} isLoading={loading} diff --git a/x-pack/plugins/observability/public/pages/slos/hooks/use_url_search_state.ts b/x-pack/plugins/observability/public/pages/slos/hooks/use_url_search_state.ts new file mode 100644 index 00000000000000..2d7fb860900faf --- /dev/null +++ b/x-pack/plugins/observability/public/pages/slos/hooks/use_url_search_state.ts @@ -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 { useHistory } from 'react-router-dom'; +import { createKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public'; +import deepmerge from 'deepmerge'; +import { SortField } from '../components/slo_list_search_bar'; + +export interface SearchState { + kqlQuery: string; + page: number; + sort: { + by: SortField; + direction: 'asc' | 'desc'; + }; +} + +export const DEFAULT_STATE = { + kqlQuery: '', + page: 0, + sort: { by: 'status' as const, direction: 'desc' as const }, +}; + +export function useUrlSearchState(): { + state: SearchState; + store: (state: Partial) => Promise; +} { + const history = useHistory(); + const urlStateStorage = createKbnUrlStateStorage({ + history, + useHash: false, + useHashQuery: false, + }); + + const searchState = urlStateStorage.get('search') ?? DEFAULT_STATE; + + return { + state: deepmerge(DEFAULT_STATE, searchState), + store: (state: Partial) => + urlStateStorage.set('search', deepmerge(searchState, state), { replace: true }), + }; +} diff --git a/x-pack/plugins/observability/public/pages/slos/slos.test.tsx b/x-pack/plugins/observability/public/pages/slos/slos.test.tsx index 09d5af66b55dc6..3e19b7a466be59 100644 --- a/x-pack/plugins/observability/public/pages/slos/slos.test.tsx +++ b/x-pack/plugins/observability/public/pages/slos/slos.test.tsx @@ -5,25 +5,25 @@ * 2.0. */ +import { act, screen, waitFor } from '@testing-library/react'; import React from 'react'; -import { screen, act, waitFor } from '@testing-library/react'; -import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; +import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; -import { render } from '../../utils/test_helper'; -import { useKibana } from '../../utils/kibana_react'; -import { useCreateSlo } from '../../hooks/slo/use_create_slo'; +import { paths } from '../../../common/locators/paths'; +import { historicalSummaryData } from '../../data/slo/historical_summary_data'; +import { emptySloList, sloList } from '../../data/slo/slo'; +import { useCapabilities } from '../../hooks/slo/use_capabilities'; import { useCloneSlo } from '../../hooks/slo/use_clone_slo'; +import { useCreateSlo } from '../../hooks/slo/use_create_slo'; import { useDeleteSlo } from '../../hooks/slo/use_delete_slo'; -import { useFetchSloList } from '../../hooks/slo/use_fetch_slo_list'; import { useFetchHistoricalSummary } from '../../hooks/slo/use_fetch_historical_summary'; +import { useFetchSloList } from '../../hooks/slo/use_fetch_slo_list'; import { useLicense } from '../../hooks/use_license'; +import { useKibana } from '../../utils/kibana_react'; +import { render } from '../../utils/test_helper'; import { SlosPage } from './slos'; -import { emptySloList, sloList } from '../../data/slo/slo'; -import { historicalSummaryData } from '../../data/slo/historical_summary_data'; -import { useCapabilities } from '../../hooks/slo/use_capabilities'; -import { paths } from '../../../common/locators/paths'; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), @@ -51,11 +51,10 @@ const useCapabilitiesMock = useCapabilities as jest.Mock; const mockCreateSlo = jest.fn(); const mockCloneSlo = jest.fn(); +const mockDeleteSlo = jest.fn(); useCreateSloMock.mockReturnValue({ mutate: mockCreateSlo }); useCloneSloMock.mockReturnValue({ mutate: mockCloneSlo }); - -const mockDeleteSlo = jest.fn(); useDeleteSloMock.mockReturnValue({ mutate: mockDeleteSlo }); const mockNavigate = jest.fn(); @@ -155,7 +154,7 @@ describe('SLOs Page', () => { }); it('navigates to the SLOs Welcome Page when the API has finished loading and there are no results', async () => { - useFetchSloListMock.mockReturnValue({ isLoading: false, sloList: emptySloList }); + useFetchSloListMock.mockReturnValue({ isLoading: false, data: emptySloList }); useFetchHistoricalSummaryMock.mockReturnValue({ isLoading: false, data: {}, @@ -171,7 +170,7 @@ describe('SLOs Page', () => { }); it('should have a create new SLO button', async () => { - useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); + useFetchSloListMock.mockReturnValue({ isLoading: false, data: sloList }); useFetchHistoricalSummaryMock.mockReturnValue({ isLoading: false, @@ -186,7 +185,7 @@ describe('SLOs Page', () => { }); it('should have an Auto Refresh button', async () => { - useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); + useFetchSloListMock.mockReturnValue({ isLoading: false, data: sloList }); useFetchHistoricalSummaryMock.mockReturnValue({ isLoading: false, @@ -202,7 +201,7 @@ describe('SLOs Page', () => { describe('when API has returned results', () => { it('renders the SLO list with SLO items', async () => { - useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); + useFetchSloListMock.mockReturnValue({ isLoading: false, data: sloList }); useFetchHistoricalSummaryMock.mockReturnValue({ isLoading: false, @@ -220,7 +219,7 @@ describe('SLOs Page', () => { }); it('allows editing an SLO', async () => { - useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); + useFetchSloListMock.mockReturnValue({ isLoading: false, data: sloList }); useFetchHistoricalSummaryMock.mockReturnValue({ isLoading: false, @@ -247,7 +246,7 @@ describe('SLOs Page', () => { }); it('allows creating a new rule for an SLO', async () => { - useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); + useFetchSloListMock.mockReturnValue({ isLoading: false, data: sloList }); useFetchHistoricalSummaryMock.mockReturnValue({ isLoading: false, @@ -272,7 +271,7 @@ describe('SLOs Page', () => { }); it('allows managing rules for an SLO', async () => { - useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); + useFetchSloListMock.mockReturnValue({ isLoading: false, data: sloList }); useFetchHistoricalSummaryMock.mockReturnValue({ isLoading: false, @@ -297,7 +296,7 @@ describe('SLOs Page', () => { }); it('allows deleting an SLO', async () => { - useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); + useFetchSloListMock.mockReturnValue({ isLoading: false, data: sloList }); useFetchHistoricalSummaryMock.mockReturnValue({ isLoading: false, @@ -327,7 +326,7 @@ describe('SLOs Page', () => { }); it('allows cloning an SLO', async () => { - useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); + useFetchSloListMock.mockReturnValue({ isLoading: false, data: sloList }); useFetchHistoricalSummaryMock.mockReturnValue({ isLoading: false, diff --git a/x-pack/plugins/observability/public/pages/slos/slos.tsx b/x-pack/plugins/observability/public/pages/slos/slos.tsx index a183d7941f7e1a..18fa418e4358bd 100644 --- a/x-pack/plugins/observability/public/pages/slos/slos.tsx +++ b/x-pack/plugins/observability/public/pages/slos/slos.tsx @@ -32,8 +32,8 @@ export function SlosPage() { const { hasWriteCapabilities } = useCapabilities(); const { hasAtLeast } = useLicense(); - const { isInitialLoading, isLoading, isError, sloList } = useFetchSloList(); - const { total } = sloList || { total: 0 }; + const { isInitialLoading, isLoading, isError, data: sloList } = useFetchSloList(); + const { total } = sloList ?? { total: 0 }; const { storeAutoRefreshState, getAutoRefreshState } = useAutoRefreshStorage(); const [isAutoRefreshing, setIsAutoRefreshing] = useState(getAutoRefreshState()); 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 fbeae4cb872b26..a6b4f671d306cd 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 @@ -56,7 +56,7 @@ describe('SLOs Welcome Page', () => { describe('when the incorrect license is found', () => { it('renders the welcome message with subscription buttons', async () => { - useFetchSloListMock.mockReturnValue({ isLoading: false, sloList: emptySloList }); + useFetchSloListMock.mockReturnValue({ isLoading: false, data: emptySloList }); useLicenseMock.mockReturnValue({ hasAtLeast: () => false }); useGlobalDiagnosisMock.mockReturnValue({ data: { @@ -82,7 +82,7 @@ describe('SLOs Welcome Page', () => { describe('when loading is done and no results are found', () => { beforeEach(() => { - useFetchSloListMock.mockReturnValue({ isLoading: false, emptySloList }); + useFetchSloListMock.mockReturnValue({ isLoading: false, data: emptySloList }); }); it('disables the create slo button when no write capabilities', async () => { @@ -146,7 +146,7 @@ describe('SLOs Welcome Page', () => { describe('when loading is done and results are found', () => { beforeEach(() => { - useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); + useFetchSloListMock.mockReturnValue({ isLoading: false, data: sloList }); useGlobalDiagnosisMock.mockReturnValue({ data: { userPrivileges: { 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 5c4317cd4e138c..16f4a75974453f 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 @@ -40,8 +40,8 @@ export function SlosWelcomePage() { const { hasAtLeast } = useLicense(); const hasRightLicense = hasAtLeast('platinum'); - const { isLoading, sloList } = useFetchSloList(); - const { total } = sloList || { total: 0 }; + const { isLoading, data: sloList } = useFetchSloList(); + const { total } = sloList ?? { total: 0 }; const hasRequiredWritePrivileges = !!globalDiagnosis?.userPrivileges.write.has_all_requested; const hasRequiredReadPrivileges = !!globalDiagnosis?.userPrivileges.read.has_all_requested; From ad82e982209cba955c4b815a0b5f7b6ea2c0f392 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 17 Oct 2023 08:49:15 -0400 Subject: [PATCH 55/87] chore(slo): improve SLO form index selector field (#168726) --- .../use_fetch_data_views.ts | 25 +++ .../public/hooks/slo/use_fetch_slo_list.ts | 24 ++- .../public/hooks/use_fetch_data_views.ts | 23 +-- .../public/hooks/use_fetch_indices.ts | 13 +- .../custom_common/index_selection.stories.tsx | 2 +- .../custom_common/index_selection.tsx | 146 +++++++----------- .../translations/translations/fr-FR.json | 2 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 9 files changed, 108 insertions(+), 131 deletions(-) create mode 100644 x-pack/plugins/observability/public/hooks/__storybook_mocks__/use_fetch_data_views.ts diff --git a/x-pack/plugins/observability/public/hooks/__storybook_mocks__/use_fetch_data_views.ts b/x-pack/plugins/observability/public/hooks/__storybook_mocks__/use_fetch_data_views.ts new file mode 100644 index 00000000000000..5affe18c75d03a --- /dev/null +++ b/x-pack/plugins/observability/public/hooks/__storybook_mocks__/use_fetch_data_views.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { DataView } from '@kbn/data-views-plugin/public'; +import { UseFetchDataViewsResponse } from '../use_fetch_data_views'; + +export const useFetchDataViews = (): UseFetchDataViewsResponse => { + return { + isLoading: false, + isError: false, + isSuccess: true, + data: Array(20) + .fill(0) + .map((_, i) => ({ + title: `dataview-${i}`, + type: 'foo', + getName: () => `dataview-${i}`, + getIndexPattern: () => `.index-pattern-dataview-${i}`, + })) as DataView[], + }; +}; diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts index a4a67b0aecceb5..f97c2398b8efca 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts @@ -60,21 +60,17 @@ export function useFetchSloList({ { queryKey: sloKeys.list({ kqlQuery, page, sortBy, sortDirection }), queryFn: async ({ signal }) => { - try { - const response = await http.get(`/api/observability/slos`, { - query: { - ...(kqlQuery && { kqlQuery }), - ...(sortBy && { sortBy }), - ...(sortDirection && { sortDirection }), - ...(page && { page }), - }, - signal, - }); + const response = await http.get(`/api/observability/slos`, { + query: { + ...(kqlQuery && { kqlQuery }), + ...(sortBy && { sortBy }), + ...(sortDirection && { sortDirection }), + ...(page && { page }), + }, + signal, + }); - return response; - } catch (error) { - throw error; - } + return response; }, keepPreviousData: true, refetchOnWindowFocus: false, diff --git a/x-pack/plugins/observability/public/hooks/use_fetch_data_views.ts b/x-pack/plugins/observability/public/hooks/use_fetch_data_views.ts index 1da32948e2e504..bff276181e95f1 100644 --- a/x-pack/plugins/observability/public/hooks/use_fetch_data_views.ts +++ b/x-pack/plugins/observability/public/hooks/use_fetch_data_views.ts @@ -5,12 +5,7 @@ * 2.0. */ -import { - QueryObserverResult, - RefetchOptions, - RefetchQueryFilters, - useQuery, -} from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; import { DataView } from '@kbn/data-views-plugin/public'; import { useKibana } from '../utils/kibana_react'; @@ -19,9 +14,6 @@ export interface UseFetchDataViewsResponse { isSuccess: boolean; isError: boolean; data: DataView[] | undefined; - refetch: ( - options?: (RefetchOptions & RefetchQueryFilters) | undefined - ) => Promise>; } interface Params { @@ -33,16 +25,15 @@ export function useFetchDataViews({ name = '', size = 10 }: Params): UseFetchDat const { dataViews } = useKibana().services; const search = name.endsWith('*') ? name : `${name}*`; - const { isLoading, isError, isSuccess, data, refetch } = useQuery({ + const { isLoading, isError, isSuccess, data } = useQuery({ queryKey: ['fetchDataViews', search], queryFn: async () => { - try { - return await dataViews.find(search, size); - } catch (error) { - throw new Error(`Something went wrong. Error: ${error}`); - } + return dataViews.find(search, size); }, + retry: false, + keepPreviousData: true, + refetchOnWindowFocus: false, }); - return { isLoading, isError, isSuccess, data, refetch }; + return { isLoading, isError, isSuccess, data }; } diff --git a/x-pack/plugins/observability/public/hooks/use_fetch_indices.ts b/x-pack/plugins/observability/public/hooks/use_fetch_indices.ts index 2d622a702a8391..bd5aae9c30df82 100644 --- a/x-pack/plugins/observability/public/hooks/use_fetch_indices.ts +++ b/x-pack/plugins/observability/public/hooks/use_fetch_indices.ts @@ -32,18 +32,15 @@ export function useFetchIndices({ search }: Params): UseFetchIndicesResponse { queryKey: ['fetchIndices', search], queryFn: async () => { const searchPattern = search?.endsWith('*') ? search : `${search}*`; - try { - const response = await http.get( - `/internal/index-pattern-management/resolve_index/${searchPattern}` - ); - return response.indices.map((index) => index.name); - } catch (error) { - throw new Error(`Something went wrong. Error: ${error}`); - } + const response = await http.get( + `/internal/index-pattern-management/resolve_index/${searchPattern}` + ); + return response.indices.map((index) => index.name); }, retry: false, enabled: Boolean(search), refetchOnWindowFocus: false, + keepPreviousData: true, }); return { isLoading, isError, isSuccess, data }; diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/custom_common/index_selection.stories.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/custom_common/index_selection.stories.tsx index b5f4848fe303d0..4b8dce62f43bb5 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/custom_common/index_selection.stories.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/custom_common/index_selection.stories.tsx @@ -15,7 +15,7 @@ import { SLO_EDIT_FORM_DEFAULT_VALUES } from '../../constants'; export default { component: Component, - title: 'app/SLO/EditPage/CustomKQL/IndexSelection', + title: 'app/SLO/EditPage/Common/IndexSelection', decorators: [KibanaReactStorybookDecorator], }; diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/custom_common/index_selection.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/custom_common/index_selection.tsx index 7dda62122b1b42..b0fe7120521915 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/custom_common/index_selection.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/custom_common/index_selection.tsx @@ -9,7 +9,7 @@ import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; import { DataView } from '@kbn/data-views-plugin/public'; import { i18n } from '@kbn/i18n'; import { debounce } from 'lodash'; -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useState } from 'react'; import { Controller, useFormContext } from 'react-hook-form'; import { useFetchDataViews } from '../../../../hooks/use_fetch_data_views'; import { useFetchIndices } from '../../../../hooks/use_fetch_indices'; @@ -22,10 +22,7 @@ interface Option { export function IndexSelection() { const { control, getFieldState } = useFormContext(); - const [searchValue, setSearchValue] = useState(''); - const [dataViewOptions, setDataViewOptions] = useState([]); - const [indexPatternOption, setIndexPatternOption] = useState {!isInsideModal && ( - + {i18n.translate('cloud.deploymentDetails.learnMoreButtonLabel', { defaultMessage: 'Learn more', })} diff --git a/packages/cloud/deployment_details/deployment_details_cloudid_input.tsx b/packages/cloud/deployment_details/deployment_details_cloudid_input.tsx index a749fe43717154..802e11aa05fcf5 100644 --- a/packages/cloud/deployment_details/deployment_details_cloudid_input.tsx +++ b/packages/cloud/deployment_details/deployment_details_cloudid_input.tsx @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import React, { type FC } from 'react'; +import React, { useState, type FC } from 'react'; import { EuiFormRow, EuiFieldText, @@ -13,17 +13,68 @@ import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, + EuiText, + EuiLink, + EuiPopover, } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; -export const DeploymentDetailsCloudIdInput: FC<{ cloudId: string }> = ({ cloudId }) => { +const LearnMoreLink: FC<{ learnMoreUrl: string }> = ({ learnMoreUrl }) => ( + + {i18n.translate('cloud.deploymentDetails.cloudIDLabelToolip.learnMoreLink', { + defaultMessage: 'Learn more', + })} + +); + +const Label: FC<{ learnMoreUrl: string }> = ({ learnMoreUrl }) => { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + return ( + + + + {i18n.translate('cloud.deploymentDetails.cloudIDLabel', { + defaultMessage: 'Cloud ID', + })} + + + + { + setIsPopoverOpen(true); + }} + /> + } + isOpen={isPopoverOpen} + closePopover={() => { + setIsPopoverOpen(false); + }} + anchorPosition="upCenter" + > +

+ }} + /> +

+
+
+
+ ); +}; + +export const DeploymentDetailsCloudIdInput: FC<{ cloudId: string; learnMoreUrl: string }> = ({ + cloudId, + learnMoreUrl, +}) => { return ( - + } fullWidth> = ({ return ( diff --git a/packages/cloud/deployment_details/deployment_details_modal.tsx b/packages/cloud/deployment_details/deployment_details_modal.tsx index 2f3d628c2ca471..c715b2d830c85d 100644 --- a/packages/cloud/deployment_details/deployment_details_modal.tsx +++ b/packages/cloud/deployment_details/deployment_details_modal.tsx @@ -26,7 +26,7 @@ interface Props { } export const DeploymentDetailsModal: FC = ({ closeModal }) => { - const { learnMoreUrl } = useDeploymentDetails(); + const { apiKeysLearnMoreUrl } = useDeploymentDetails(); return ( = ({ closeModal }) => { - + {i18n.translate('cloud.deploymentDetails.modal.learnMoreButtonLabel', { defaultMessage: 'Learn more', })} diff --git a/packages/cloud/deployment_details/services.tsx b/packages/cloud/deployment_details/services.tsx index c4e8be12bb5475..f25575cf8b01da 100644 --- a/packages/cloud/deployment_details/services.tsx +++ b/packages/cloud/deployment_details/services.tsx @@ -12,7 +12,8 @@ export interface DeploymentDetailsContextValue { cloudId?: string; elasticsearchUrl?: string; managementUrl?: string; - learnMoreUrl: string; + apiKeysLearnMoreUrl: string; + cloudIdLearnMoreUrl: string; navigateToUrl(url: string): Promise; } @@ -64,6 +65,9 @@ export interface DeploymentDetailsKibanaDependencies { fleet: { apiKeysLearnMore: string; }; + cloud: { + beatsAndLogstashConfiguration: string; + }; }; }; } @@ -86,6 +90,7 @@ export const DeploymentDetailsKibanaProvider: FC {children} diff --git a/packages/cloud/tsconfig.json b/packages/cloud/tsconfig.json index c4703bc51cf6c6..f56351356720a6 100644 --- a/packages/cloud/tsconfig.json +++ b/packages/cloud/tsconfig.json @@ -17,5 +17,6 @@ ], "kbn_references": [ "@kbn/i18n", + "@kbn/i18n-react", ] } diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index 65183620e756d7..1f668ce162728e 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -65,6 +65,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { guide: `${KIBANA_DOCS}canvas.html`, }, cloud: { + beatsAndLogstashConfiguration: `${ELASTIC_WEBSITE_URL}guide/en/cloud/current/ec-cloud-id.html`, indexManagement: `${ELASTIC_WEBSITE_URL}guide/en/cloud/current/ec-configure-index-management.html`, }, console: { diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index 6d4245b769a272..555167bf8574e9 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -46,6 +46,7 @@ export interface DocLinks { readonly guide: string; }; readonly cloud: { + readonly beatsAndLogstashConfiguration: string; readonly indexManagement: string; }; readonly console: { From b207f24dab62b4f0a206e59d341937d8a9265d1a Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Tue, 17 Oct 2023 14:58:56 +0200 Subject: [PATCH 57/87] [Serverless] Improve observability project empty state in analytics apps (#168598) ## Summary fix https://github.com/elastic/kibana/issues/166233 (this is a short term fix that removes "analytics" references from the empty state page in serverless observability analytics apps) ![Screenshot 2023-10-17 at 12 12 53](https://github.com/elastic/kibana/assets/7784120/6912940e-11ba-440d-a67d-241737f20e5d) --- config/serverless.oblt.yml | 3 ++ .../analytics_no_data_page.component.test.tsx | 20 +++++++++++ .../src/analytics_no_data_page.component.tsx | 25 ++++++++++++++ .../page/analytics_no_data/types/index.d.ts | 2 +- .../page/no_data/impl/src/no_data_page.tsx | 33 ++++++++++--------- .../shared-ux/page/no_data/types/index.d.ts | 4 +++ src/plugins/no_data_page/config.ts | 8 ++++- src/plugins/no_data_page/public/types.ts | 2 +- 8 files changed, 79 insertions(+), 18 deletions(-) diff --git a/config/serverless.oblt.yml b/config/serverless.oblt.yml index ed011cd90063a1..666f8abbf3f87c 100644 --- a/config/serverless.oblt.yml +++ b/config/serverless.oblt.yml @@ -16,6 +16,9 @@ xpack.serverless.observability.enabled: true ## Set the home route uiSettings.overrides.defaultRoute: /app/observability/landing +# Customize empty page state for analytics apps +no_data_page.analyticsNoDataPageFlavor: 'serverless_observability' + ## Set the dev project switch current type xpack.serverless.plugin.developer.projectSwitcher.currentType: 'observability' 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 4e16dd6c38bc0a..ac59185e25ef92 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 @@ -147,5 +147,25 @@ describe('AnalyticsNoDataPageComponent', () => { await screen.findByTestId('kbnOverviewElasticsearchGettingStarted'); }); }); + + describe('serverless_observability flavor', () => { + it('renders getting started card', async () => { + render( + + false }}> + path} + /> + + + ); + + await screen.findByTestId('kbnObservabilityNoData'); + }); + }); }); }); 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 4c22a0acb2475c..a7cb75e2c1fb0b 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 @@ -79,6 +79,31 @@ const flavors: { }, }, }), + serverless_observability: ({ prependBasePath }) => ({ + solution: i18n.translate('sharedUXPackages.noDataConfig.observability', { + defaultMessage: 'Observability', + }), + pageTitle: i18n.translate('sharedUXPackages.noDataConfig.observabilityPageTitle', { + defaultMessage: 'Welcome to Elastic Observability!', + }), + pageDescription: i18n.translate('sharedUXPackages.noDataConfig.observabilityPageDescription', { + defaultMessage: + 'Converge metrics, logs, and traces to monitor the health of your applications.', + }), + logo: 'logoObservability', + action: { + observability: { + title: i18n.translate('sharedUXPackages.noDataConfig.observabilityTitle', { + defaultMessage: 'Add data', + }), + description: i18n.translate('sharedUXPackages.noDataConfig.observabilityDescription', { + defaultMessage: 'Get started by collecting data using one of our many integrations.', + }), + 'data-test-subj': 'kbnObservabilityNoData', + href: prependBasePath('/app/observabilityOnboarding/'), + }, + }, + }), }; /** 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 f292e297b6fdc5..1b71ac172f0de7 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 @@ -26,7 +26,7 @@ export interface Services { */ export type AnalyticsNoDataPageServices = Services & KibanaNoDataPageServices; -export type AnalyticsNoDataPageFlavor = 'kibana' | 'serverless_search'; +export type AnalyticsNoDataPageFlavor = 'kibana' | 'serverless_search' | 'serverless_observability'; export interface KibanaDependencies { coreStart: { 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 5aec81d942de64..0ba20b259108d0 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 @@ -24,6 +24,7 @@ export const NoDataPage = ({ action, docsLink, pageTitle, + pageDescription, className, }: NoDataPageProps) => { const title = @@ -39,21 +40,23 @@ export const NoDataPage = ({ ) : null; - const message = link ? ( - - ) : ( - - ); + const message = + pageDescription ?? + (link ? ( + + ) : ( + + )); return ( 'kibana' | 'serverless_search'; + getAnalyticsNoDataPageFlavor: () => 'kibana' | 'serverless_search' | 'serverless_observability'; } export type NoDataPagePluginStart = NoDataPagePluginSetup; From a04852d11058c1922187f1c1e8f905652b1a79a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Efe=20G=C3=BCrkan=20YALAMAN?= Date: Tue, 17 Oct 2023 15:26:57 +0200 Subject: [PATCH 58/87] [Enterprise Search] Disable Access Control Syncs when DLS is disabled (#168987) ## Summary Access Control Sync button is greyed out when Document Level Security is disabled. Added checks on backend code to throw 400 to Frontend when Access Control Sync is requested when Document Level Security is disabled. Screenshot 2023-10-16 at 16 53 35 ## Release Note Fixes an issue caused Access Control Syncs to be scheduled still when Document Level Security is disabled. ### 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 --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/types/error_codes.ts | 1 + .../header_actions/syncs_context_menu.tsx | 6 ++++- .../server/lib/connectors/start_sync.test.ts | 12 +++++++-- .../server/lib/connectors/start_sync.ts | 6 +++++ .../routes/enterprise_search/connectors.ts | 25 ++++++++++++++++--- .../server/utils/identify_exceptions.ts | 4 +++ 6 files changed, 48 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/enterprise_search/common/types/error_codes.ts b/x-pack/plugins/enterprise_search/common/types/error_codes.ts index de38fa1d24f163..1492dc4e763b31 100644 --- a/x-pack/plugins/enterprise_search/common/types/error_codes.ts +++ b/x-pack/plugins/enterprise_search/common/types/error_codes.ts @@ -6,6 +6,7 @@ */ export enum ErrorCode { + ACCESS_CONTROL_DISABLED = 'access_control_disabled', ANALYTICS_COLLECTION_ALREADY_EXISTS = 'analytics_collection_already_exists', ANALYTICS_COLLECTION_NOT_FOUND = 'analytics_collection_not_found', CONNECTOR_DOCUMENT_ALREADY_EXISTS = 'connector_document_already_exists', diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/syncs_context_menu.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/syncs_context_menu.tsx index 0e1ddbf3e84ae0..d49df5e74ef03d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/syncs_context_menu.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/syncs_context_menu.tsx @@ -27,6 +27,7 @@ import { KibanaLogic } from '../../../../../shared/kibana'; import { CancelSyncsApiLogic } from '../../../../api/connector/cancel_syncs_api_logic'; import { IngestionStatus } from '../../../../types'; import { CancelSyncsLogic } from '../../connector/cancel_syncs_logic'; +import { ConnectorConfigurationLogic } from '../../connector/connector_configuration_logic'; import { IndexViewLogic } from '../../index_view_logic'; export const SyncsContextMenu: React.FC = () => { @@ -43,6 +44,7 @@ export const SyncsContextMenu: React.FC = () => { const { cancelSyncs } = useActions(CancelSyncsLogic); const { status } = useValues(CancelSyncsApiLogic); const { startSync, startIncrementalSync, startAccessControlSync } = useActions(IndexViewLogic); + const { configState } = useValues(ConnectorConfigurationLogic); const [isPopoverOpen, setPopover] = useState(false); const togglePopover = () => setPopover(!isPopoverOpen); @@ -124,7 +126,9 @@ export const SyncsContextMenu: React.FC = () => { 'entSearchContent-${ingestionMethod}-header-sync-more-accessControlSync', 'data-test-subj': 'entSearchContent-${ingestionMethod}-header-sync-more-accessControlSync', - disabled: ingestionStatus === IngestionStatus.INCOMPLETE, + disabled: + ingestionStatus === IngestionStatus.INCOMPLETE || + !configState.use_document_level_security?.value, icon: 'play', name: i18n.translate('xpack.enterpriseSearch.index.header.more.accessControlSync', { defaultMessage: 'Access Control', diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/start_sync.test.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/start_sync.test.ts index 6498d3f4d1a030..978896289763f3 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/start_sync.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/start_sync.test.ts @@ -299,7 +299,11 @@ describe('startSync lib function', () => { _id: 'connectorId', _source: { api_key_id: null, - configuration: {}, + configuration: { + use_document_level_security: { + value: true, + }, + }, created_at: null, custom_scheduling: {}, error: null, @@ -334,7 +338,11 @@ describe('startSync lib function', () => { canceled_at: null, completed_at: null, connector: { - configuration: {}, + configuration: { + use_document_level_security: { + value: true, + }, + }, filtering: null, id: 'connectorId', index_name: `${CONNECTORS_ACCESS_CONTROL_INDEX_PREFIX}index_name`, diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/start_sync.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/start_sync.ts index 808fd2fc0d40e2..ab58fd1417b731 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/start_sync.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/start_sync.ts @@ -50,6 +50,12 @@ export const startSync = async ( } : config; const { index_name } = connector; + if ( + jobType === SyncJobType.ACCESS_CONTROL && + !configuration.use_document_level_security?.value + ) { + throw new Error(ErrorCode.ACCESS_CONTROL_DISABLED); + } if (connector.service_type === ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE) { return await client.asCurrentUser.update({ diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts index fea646d9d726e4..a224babe332925 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts @@ -38,6 +38,7 @@ import { updateConnectorPipeline } from '../../lib/pipelines/update_pipeline'; import { RouteDependencies } from '../../plugin'; import { createError } from '../../utils/create_error'; import { elasticsearchErrorHandler } from '../../utils/elasticsearch_error_handler'; +import { isAccessControlDisabledException } from '../../utils/identify_exceptions'; import { validateEnum } from '../../utils/validate_enum'; export function registerConnectorRoutes({ router, log }: RouteDependencies) { @@ -203,9 +204,27 @@ export function registerConnectorRoutes({ router, log }: RouteDependencies) { }, }, elasticsearchErrorHandler(log, async (context, request, response) => { - const { client } = (await context.core).elasticsearch; - await startSync(client, request.params.connectorId, SyncJobType.ACCESS_CONTROL); - return response.ok(); + try { + const { client } = (await context.core).elasticsearch; + await startSync(client, request.params.connectorId, SyncJobType.ACCESS_CONTROL); + return response.ok(); + } catch (error) { + if (isAccessControlDisabledException(error)) { + return createError({ + errorCode: ErrorCode.ACCESS_CONTROL_DISABLED, + message: i18n.translate( + 'xpack.enterpriseSearch.server.connectors.accessControlSync.accessControlDisabledError', + { + defaultMessage: + 'Access control sync cannot be created. You must first enable Document Level Security.', + } + ), + response, + statusCode: 400, + }); + } + throw error; + } }) ); diff --git a/x-pack/plugins/enterprise_search/server/utils/identify_exceptions.ts b/x-pack/plugins/enterprise_search/server/utils/identify_exceptions.ts index 415d81ee8cec7d..a1688520bb593e 100644 --- a/x-pack/plugins/enterprise_search/server/utils/identify_exceptions.ts +++ b/x-pack/plugins/enterprise_search/server/utils/identify_exceptions.ts @@ -52,3 +52,7 @@ export const isMissingAliasException = (error: ElasticsearchResponseError) => error.meta?.statusCode === 404 && typeof error.meta?.body?.error === 'string' && MISSING_ALIAS_ERROR.test(error.meta?.body?.error); + +export const isAccessControlDisabledException = (error: Error) => { + return error.message === ErrorCode.ACCESS_CONTROL_DISABLED; +}; From 2939cf583c7ddc4614cf57b9bb3e7a79d4a922ee Mon Sep 17 00:00:00 2001 From: Chris Cressman Date: Tue, 17 Oct 2023 09:50:33 -0400 Subject: [PATCH 59/87] [Serverless Search] Fix Python client "basic configuration" link (#169002) ## Summary When the Python client is selected, this link sends the user to a doc that isn't relevant to serverless. Replace with a relevant link. ### 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) --- x-pack/plugins/serverless_search/common/doc_links.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/serverless_search/common/doc_links.ts b/x-pack/plugins/serverless_search/common/doc_links.ts index 0c816e3c7a3899..6d97c6aed5bede 100644 --- a/x-pack/plugins/serverless_search/common/doc_links.ts +++ b/x-pack/plugins/serverless_search/common/doc_links.ts @@ -76,7 +76,7 @@ class ESDocLinks { this.phpClient = newDocLinks.serverlessClients.phpGettingStarted; // Python this.pythonApiReference = newDocLinks.serverlessClients.pythonGettingStarted; - this.pythonBasicConfig = newDocLinks.clients.pythonConnecting; + this.pythonBasicConfig = newDocLinks.serverlessClients.pythonGettingStarted; this.pythonClient = newDocLinks.serverlessClients.pythonGettingStarted; // Python this.rubyBasicConfig = newDocLinks.serverlessClients.rubyGettingStarted; From ddaed4238069d1f29e366b1574e8f06702f54b78 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Tue, 17 Oct 2023 16:02:10 +0200 Subject: [PATCH 60/87] [SOR] update: don't deep merge `flattened` fields (#168986) Fix https://github.com/elastic/kibana/issues/168960 Utilize the type's mappings when performing the merge-for-update operation to restore the behavior ES has with `flattened` fields. --- .../src/lib/apis/update.ts | 18 ++- .../lib/apis/utils/merge_for_update.test.ts | 109 +++++++++++++++--- .../src/lib/apis/utils/merge_for_update.ts | 53 +++++++-- 3 files changed, 151 insertions(+), 29 deletions(-) diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/update.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/update.ts index e119d6e6303dbc..fd9c587502d7b9 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/update.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/update.ts @@ -83,7 +83,7 @@ export const executeUpdate = async ( validation: validationHelper, } = helpers; const { securityExtension } = extensions; - + const typeDefinition = registry.getType(type)!; const { version, references, @@ -246,10 +246,18 @@ export const executeUpdate = async ( // at this point, we already know 1. the document exists 2. we're not doing an upsert // therefor we can safely process with the "standard" update sequence. - const updatedAttributes = mergeForUpdate( - { ...migrated!.attributes }, - await encryptionHelper.optionallyEncryptAttributes(type, id, namespace, attributes) - ); + const updatedAttributes = mergeForUpdate({ + targetAttributes: { + ...migrated!.attributes, + }, + updatedAttributes: await encryptionHelper.optionallyEncryptAttributes( + type, + id, + namespace, + attributes + ), + typeMappings: typeDefinition.mappings, + }); const migratedUpdatedSavedObjectDoc = migrationHelper.migrateInputDocument({ ...migrated!, id, diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.test.ts index 7d859f374a5e24..b7a31cb68d9d30 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.test.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.test.ts @@ -6,11 +6,22 @@ * Side Public License, v 1. */ +import type { SavedObjectsTypeMappingDefinition } from '@kbn/core-saved-objects-server'; import { mergeForUpdate } from './merge_for_update'; +const defaultMappings: SavedObjectsTypeMappingDefinition = { + properties: {}, +}; + describe('mergeForUpdate', () => { it('merges top level properties', () => { - expect(mergeForUpdate({ foo: 'bar', hello: 'dolly' }, { baz: 42 })).toEqual({ + expect( + mergeForUpdate({ + targetAttributes: { foo: 'bar', hello: 'dolly' }, + updatedAttributes: { baz: 42 }, + typeMappings: defaultMappings, + }) + ).toEqual({ foo: 'bar', hello: 'dolly', baz: 42, @@ -18,7 +29,13 @@ describe('mergeForUpdate', () => { }); it('overrides top level properties', () => { - expect(mergeForUpdate({ foo: 'bar', hello: 'dolly' }, { baz: 42, foo: '9000' })).toEqual({ + expect( + mergeForUpdate({ + targetAttributes: { foo: 'bar', hello: 'dolly' }, + updatedAttributes: { baz: 42, foo: '9000' }, + typeMappings: defaultMappings, + }) + ).toEqual({ foo: '9000', hello: 'dolly', baz: 42, @@ -26,7 +43,13 @@ describe('mergeForUpdate', () => { }); it('ignores undefined top level properties', () => { - expect(mergeForUpdate({ foo: 'bar', hello: 'dolly' }, { baz: 42, foo: undefined })).toEqual({ + expect( + mergeForUpdate({ + targetAttributes: { foo: 'bar', hello: 'dolly' }, + updatedAttributes: { baz: 42, foo: undefined }, + typeMappings: defaultMappings, + }) + ).toEqual({ foo: 'bar', hello: 'dolly', baz: 42, @@ -35,7 +58,11 @@ describe('mergeForUpdate', () => { it('merges nested properties', () => { expect( - mergeForUpdate({ nested: { foo: 'bar', hello: 'dolly' } }, { nested: { baz: 42 } }) + mergeForUpdate({ + targetAttributes: { nested: { foo: 'bar', hello: 'dolly' } }, + updatedAttributes: { nested: { baz: 42 } }, + typeMappings: defaultMappings, + }) ).toEqual({ nested: { foo: 'bar', @@ -47,10 +74,11 @@ describe('mergeForUpdate', () => { it('overrides nested properties', () => { expect( - mergeForUpdate( - { nested: { foo: 'bar', hello: 'dolly' } }, - { nested: { baz: 42, foo: '9000' } } - ) + mergeForUpdate({ + targetAttributes: { nested: { foo: 'bar', hello: 'dolly' } }, + updatedAttributes: { nested: { baz: 42, foo: '9000' } }, + typeMappings: defaultMappings, + }) ).toEqual({ nested: { foo: '9000', @@ -62,10 +90,11 @@ describe('mergeForUpdate', () => { it('ignores undefined nested properties', () => { expect( - mergeForUpdate( - { nested: { foo: 'bar', hello: 'dolly' } }, - { nested: { baz: 42, foo: undefined } } - ) + mergeForUpdate({ + targetAttributes: { nested: { foo: 'bar', hello: 'dolly' } }, + updatedAttributes: { nested: { baz: 42, foo: undefined } }, + typeMappings: defaultMappings, + }) ).toEqual({ nested: { foo: 'bar', @@ -77,10 +106,17 @@ describe('mergeForUpdate', () => { it('functions with mixed levels of properties', () => { expect( - mergeForUpdate( - { rootPropA: 'A', nested: { foo: 'bar', hello: 'dolly', deep: { deeper: 'we need' } } }, - { rootPropB: 'B', nested: { baz: 42, foo: '9000', deep: { deeper: 'we are' } } } - ) + mergeForUpdate({ + targetAttributes: { + rootPropA: 'A', + nested: { foo: 'bar', hello: 'dolly', deep: { deeper: 'we need' } }, + }, + updatedAttributes: { + rootPropB: 'B', + nested: { baz: 42, foo: '9000', deep: { deeper: 'we are' } }, + }, + typeMappings: defaultMappings, + }) ).toEqual({ rootPropA: 'A', rootPropB: 'B', @@ -94,4 +130,45 @@ describe('mergeForUpdate', () => { }, }); }); + + describe('with flattened fields', () => { + const mappingsWithFlattened: SavedObjectsTypeMappingDefinition = { + properties: { + flattened: { + type: 'flattened', + }, + nested: { + properties: { + deepFlat: { + type: 'flattened', + }, + }, + }, + }, + }; + + it('replaces top level flattened properties', () => { + expect( + mergeForUpdate({ + targetAttributes: { flattened: { before: 42 }, notFlattened: { before: 42 } }, + updatedAttributes: { flattened: { after: 9000 }, notFlattened: { after: 9000 } }, + typeMappings: mappingsWithFlattened, + }) + ).toEqual({ flattened: { after: 9000 }, notFlattened: { before: 42, after: 9000 } }); + }); + + it('replaces nested flattened properties', () => { + expect( + mergeForUpdate({ + targetAttributes: { nested: { deepFlat: { before: 42 }, notFlattened: { before: 42 } } }, + updatedAttributes: { + nested: { deepFlat: { after: 9000 }, notFlattened: { after: 9000 } }, + }, + typeMappings: mappingsWithFlattened, + }) + ).toEqual({ + nested: { deepFlat: { after: 9000 }, notFlattened: { before: 42, after: 9000 } }, + }); + }); + }); }); diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.ts index a3ad081fa74d75..c0c7feaa9e90c5 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/utils/merge_for_update.ts @@ -8,18 +8,38 @@ import { isPlainObject } from 'lodash'; import { set } from '@kbn/safer-lodash-set'; +import type { MappingProperty as EsMappingProperty } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { + SavedObjectsTypeMappingDefinition, + SavedObjectsFieldMapping, +} from '@kbn/core-saved-objects-server'; -export const mergeForUpdate = ( - targetAttributes: Record, - updatedAttributes: any -): Record => { - return recursiveMerge(targetAttributes, updatedAttributes, []); +type MaybeMappings = SavedObjectsFieldMapping | EsMappingProperty | undefined; + +export const mergeForUpdate = ({ + targetAttributes, + updatedAttributes, + typeMappings, +}: { + targetAttributes: Record; + updatedAttributes: any; + typeMappings: SavedObjectsTypeMappingDefinition; +}): Record => { + const rootMappings: SavedObjectsFieldMapping = { + properties: typeMappings.properties, + }; + return recursiveMerge(targetAttributes, updatedAttributes, [], rootMappings); }; -const recursiveMerge = (target: Record, value: any, keys: string[] = []) => { - if (isPlainObject(value) && Object.keys(value).length > 0) { +const recursiveMerge = ( + target: Record, + value: any, + keys: string[], + mappings: MaybeMappings +) => { + if (shouldRecursiveMerge(value, mappings)) { for (const [subKey, subVal] of Object.entries(value)) { - recursiveMerge(target, subVal, [...keys, subKey]); + recursiveMerge(target, subVal, [...keys, subKey], getFieldMapping(mappings, subKey)); } } else if (keys.length > 0 && value !== undefined) { set(target, keys, value); @@ -27,3 +47,20 @@ const recursiveMerge = (target: Record, value: any, keys: string[] return target; }; + +const getFieldMapping = (parentMapping: MaybeMappings, fieldName: string): MaybeMappings => { + if (parentMapping && 'properties' in parentMapping) { + return parentMapping.properties?.[fieldName]; + } + return undefined; +}; + +const shouldRecursiveMerge = (value: any, mappings: MaybeMappings): boolean => { + if (mappings && 'type' in mappings && mappings.type === 'flattened') { + return false; + } + if (isPlainObject(value) && Object.keys(value).length > 0) { + return true; + } + return false; +}; From 8d37876bf22c60682ee81a1c72a031a5acca34c1 Mon Sep 17 00:00:00 2001 From: Brad White Date: Tue, 17 Oct 2023 08:05:22 -0600 Subject: [PATCH 61/87] Fix watcher simulation crash (#169056) ## Summary Closes #163881 See issue for reproducing. This would have been caught by TS, but the type is `any`: https://github.com/elastic/kibana/blob/d0e99258c68d57bc83788724814783ece176aa78/x-pack/plugins/watcher/common/types/watch_types.ts#L11 The better fix would be to update the type as well, but I'm not familiar with the shape of the data returned, so I opted not to. ## Release note Fixes crash when simulating a watch that contains a Painless script with a Debug.explain(). --- .../json_watch_edit/simulate_watch_results_flyout.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit_page/components/json_watch_edit/simulate_watch_results_flyout.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit_page/components/json_watch_edit/simulate_watch_results_flyout.tsx index e48202e80c3047..a4f156afcc14cb 100644 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit_page/components/json_watch_edit/simulate_watch_results_flyout.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit_page/components/json_watch_edit/simulate_watch_results_flyout.tsx @@ -81,6 +81,7 @@ export const SimulateWatchResultsFlyout = ({ return Object.keys(actions).map((actionKey) => { const actionStatus = actionStatuses.find((status) => status.id === actionKey); const isConditionMet = executeResults.details?.result?.condition.met; + return { actionId: actionKey, actionType: getTypeFromAction(actions[actionKey]), @@ -90,7 +91,7 @@ export const SimulateWatchResultsFlyout = ({ actionStatus: (isConditionMet && executeResults.details.result.actions.find((action: any) => action.id === actionKey) - .status) || + ?.status) || conditionNotMetActionStatus(actionModes[actionKey]), }; }); From 0526d79e79bcf2b44292236b825019f8adcf949d Mon Sep 17 00:00:00 2001 From: Jason Rhodes Date: Tue, 17 Oct 2023 10:07:30 -0400 Subject: [PATCH 62/87] Tiered dependencies docs unrevert (#169009) https://github.com/elastic/kibana/pull/166524 was merged and then reverted with https://github.com/elastic/kibana/commit/9080836d6ae882b7287e9bb3cdbd6ac3191e6704 because it failed a CI check for file name casing that wasn't run on the PR branch for some reason. The file has now been properly snake_cased and this will re-apply the change. --- .../dev_docs/how_we_manage_dependencies.md | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 x-pack/plugins/observability_shared/dev_docs/how_we_manage_dependencies.md diff --git a/x-pack/plugins/observability_shared/dev_docs/how_we_manage_dependencies.md b/x-pack/plugins/observability_shared/dev_docs/how_we_manage_dependencies.md new file mode 100644 index 00000000000000..5cd525e97954f9 --- /dev/null +++ b/x-pack/plugins/observability_shared/dev_docs/how_we_manage_dependencies.md @@ -0,0 +1,70 @@ +# Dependency Management in Observability Kibana + +Our goal in observability is to provide as seamless of an experience as possible for our observability users, especially when it comes to navigating between areas owned by different teams. In Kibana, these different teams each own their own experiences inside of a Kibana plugin that provides a public UI interface and, optionally, a back-end server interface. As these plugins begin to share more components, utilities, data clients, and more, the Kibana architecture requires them to depend on each other using runtime dependencies. These dependencies can only be single-direction, which severely limits the types of sharing our plugins can do with one another. + +## Problem summary + +For years, the APM plugin has declared a single-direction runtime dependency on the Infra plugin, allowing APM to make use of components and utilities made available by Infra. Because of this existing dependency, the infra plugin can never make use of similar shared items that could be made available from APM. As Logs+ grows and evolves, Synthetics and Profiling both continue to grow beyond GA, and Elastic begins to fully embrace a unified Observability user experience, we expect this problem to multiply quickly. + +To solve this problem, we need a clear approach for how to organize plugins, packages, and the dependencies between them. + +## Plan summary + +This is the plan we aim to follow, summarized. More details about this plan are found below. + +1. **Resist over-abstraction, but abstract when needed.** If something doesn't need to be shared yet, it's not necessarily good to break it out into its own plugin _or_ package. That said, we will need to break items out of our end user plugins and/or rearrange them, and we shouldn't be scared of doing this because of longtime technical limitations. + - TODO: Add information about possible Kibana event system to consider as a first sharing step, prior to abstraction. +1. **Prefer packages to plugins.** A stateless package is easier to bootstrap, test, and maintain in most cases. If you don't need access to stateful dependencies from core or other plugins, or if you can accept a reasonable number of injected dependencies, make a package. + - TODO: Add link to docs/examples of how to make a Kibana package + - TODO: Add more clarity on the trade-offs between plugin vs package +1. **If you need to make a new plugin, be sure to carefully consider the plugin tiers and how your new plugin will fit.**. In most cases, we should avoid new plugins (with the exception of data access plugins which should only depend on Kibana core.) +1. **Never introduce or add to existing dependencies between plugins in the same tier.** This is the main problem we need to avoid, especially between end user plugins. + +## Plugin tier system + +The system we'll embrace revolves around a "tier system" to help us organize different types of plugins. The plugin tiers look like this: + +Screenshot 2023-09-14 at 3 27 56 PM + +Within this system, a plugin in any tier may ONLY introduce dependencies on other plugins that are in a tier below theirs. They may NOT depend on plugins in the same tier or in tiers above their own. Packages, on the other hand, may be depended on from _any_ plugin, as well as from _any other_ package. + +**Note:** Tiers are NOT currently enforced by any lint rule or other rule. Tiers are a convention that allow us to structure our code in such a way as to avoid the circular dependency problem, but they require manual enforcement via code review. In the near future, we should explore simple ways to codify and enforce this system, either in linting rules, Kibana bundling enforcement, precommit hooks, etc. + +### Tier 1: End user tier + +End user plugins are the plugins that provide visible sections of the Observability UI in Kibana. Each of these plugins may provide one or more navigational areas inside of the Observability product, and they each may provide one or more Kibana server APIs as well. + +These plugins should stop introducing dependencies on each other immediately, and should also stop introducing new functionality that relies on existing dependencies immediately, as well. As soon as possible, existing dependencies between these plugins should be removed and replaced with extracted functionality. + +Screenshot 2023-09-14 at 3 32 17 PM + +### Tier 2: Share tier + +"Share plugins" provide shared functionality (UI components, utility functions, shared logic, etc.) that can be used by multiple end user plugins. Being plugins, they still take advantage of the Kibana runtime lifecycle (setup, start, stop) and have access to Kibana's core functionality and core plugin system. + +This tier is where we would move any shared items, business logic, and stateful dependencies that need access to the plugin lifecycle and, for whatever reason, can't or don't want to accept runtime dependencies as injected parameters. These share plugins can make use of the core-only plugins that typically provide encapsulated access to observability data of other kinds. + +Screenshot 2023-09-14 at 3 32 25 PM + +### Tier 3: Core-only tier (aka data access tier) + +This tier is for plugins that ONLY depend on Kibana core functionality such as scoped ES clients, saved object clients, etc. The main examples of these for now are the new "data access client" plugins which encapsulate the logic for accessing our various types of signal data in observability. By keeping this tier isolated from the other code and only allowing for it to depend on Kibana core, we make data access safely available to any other plugin in the end user or share tiers. + +Screenshot 2023-09-14 at 3 32 30 PM + +### Core: Kibana core + +Anything made available by Kibana core, either in the CoreSetup, CoreStart, or one of the core-maintained plugins such as saved objects, etc. is fair game as a dependency of any observability plugin in any tier. + +### Packages + +Kibana packages are stateless and therefore can be imported into any plugin in any tier. If your shareable item is stateless, or if it can be simply built to accept strongly-typed items using dependency injection, using a package is almost always the best choice. + +## Putting it all together + +Screenshot 2023-09-14 at 3 37 35 PM + +With the exception of package dependencies, all plugin-to-plugin dependencies may only flow _downward_ in the tier diagram. + +Screenshot 2023-09-14 at 3 37 42 PM + From ef092072fb24337065d75a96b99c1d80ad380378 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 17 Oct 2023 16:16:32 +0200 Subject: [PATCH 63/87] [Synthetics] Project monitor, allow max_redirects number input (#169087) --- .../monitor_management/monitor_types_project.ts | 2 +- .../normalizers/http_monitor.test.ts | 5 +++-- .../project_monitor/normalizers/http_monitor.ts | 13 +++++++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts index 23e39660842fae..99082a43f09b31 100644 --- a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts +++ b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts @@ -43,7 +43,7 @@ export const ProjectMonitorCodec = t.intersection([ alert: AlertConfigsCodec, urls: t.union([t.string, t.array(t.string)]), hosts: t.union([t.string, t.array(t.string)]), - max_redirects: t.string, + max_redirects: t.union([t.string, t.number]), wait: t.string, hash: t.string, namespace: t.string, diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.test.ts index 44678ad3b7688c..6db69ae3eebf2e 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.test.ts @@ -78,6 +78,7 @@ describe('http normalizers', () => { supported_protocols: ['TLSv1.2', 'TLSv1.3'], }, hash: testHash, + max_redirects: 2, }, { locations: ['localhost'], @@ -160,7 +161,7 @@ describe('http normalizers', () => { form_monitor_type: 'http', journey_id: 'my-monitor-2', locations: [], - max_redirects: '0', + max_redirects: '2', name: 'My Monitor 2', namespace: 'test_space', origin: 'project', @@ -300,7 +301,7 @@ describe('http normalizers', () => { form_monitor_type: 'http', journey_id: 'my-monitor-2', locations: [], - max_redirects: '0', + max_redirects: '2', name: 'My Monitor 2', namespace: 'test_space', origin: 'project', diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.ts index 892fbd53617a14..c79db2433cb807 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.ts @@ -64,8 +64,7 @@ export const getNormalizeHTTPFields = ({ [ConfigKey.MONITOR_TYPE]: DataStream.HTTP, [ConfigKey.FORM_MONITOR_TYPE]: FormMonitorType.HTTP, [ConfigKey.URLS]: getOptionalArrayField(monitor.urls) || defaultFields[ConfigKey.URLS], - [ConfigKey.MAX_REDIRECTS]: - monitor[ConfigKey.MAX_REDIRECTS] || defaultFields[ConfigKey.MAX_REDIRECTS], + [ConfigKey.MAX_REDIRECTS]: formatMaxRedirects(monitor[ConfigKey.MAX_REDIRECTS]), [ConfigKey.REQUEST_BODY_CHECK]: getRequestBodyField( (yamlConfig as Record)[ConfigKey.REQUEST_BODY_CHECK] as string, defaultFields[ConfigKey.REQUEST_BODY_CHECK] @@ -113,3 +112,13 @@ export const getRequestBodyField = ( value: parsedValue || defaultValue.value, }; }; + +export const formatMaxRedirects = (value?: string | number): string => { + if (typeof value === 'number') { + return `${value}`; + } + + const defaultFields = DEFAULT_FIELDS[DataStream.HTTP]; + + return value ?? defaultFields[ConfigKey.MAX_REDIRECTS]; +}; From d871474d19a78dcd2d564bccf4d06e53cdcc424d Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 17 Oct 2023 07:33:37 -0700 Subject: [PATCH 64/87] [DOCS] Alerts-as-data for index threshold rules (#169049) --- ...index-threshold-example-action-summary.png | Bin 0 -> 131452 bytes ...e-types-index-threshold-example-action.png | Bin 154239 -> 149706 bytes .../alerting/rule-types/es-query.asciidoc | 17 +++---- .../rule-types/geo-rule-types.asciidoc | 10 +++- .../rule-types/index-threshold.asciidoc | 46 +++++++++++++----- .../stack_alerting/index_threshold_rule.ts | 19 +++++++- 6 files changed, 69 insertions(+), 23 deletions(-) create mode 100644 docs/user/alerting/images/rule-types-index-threshold-example-action-summary.png diff --git a/docs/user/alerting/images/rule-types-index-threshold-example-action-summary.png b/docs/user/alerting/images/rule-types-index-threshold-example-action-summary.png new file mode 100644 index 0000000000000000000000000000000000000000..337171d995676fa9bb9293248b429d1b68e783a4 GIT binary patch literal 131452 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 literal 0 HcmV?d00001 diff --git a/docs/user/alerting/images/rule-types-index-threshold-example-action.png b/docs/user/alerting/images/rule-types-index-threshold-example-action.png index 278a7229217575e27decb9dbbe748f6d7923a56e..da4fb66dc6400a4ca6b9a9ffc5b0e46fd9807c1d 100644 GIT binary patch literal 149706 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

ynq-Q%@i?Ai`uY8u}Aw)EDw~Gr?q(hye>J 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 literal 154239 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 RHVD9vtfZ1ek(gn?{{a2UQW*dM diff --git a/docs/user/alerting/rule-types/es-query.asciidoc b/docs/user/alerting/rule-types/es-query.asciidoc index 029ec2e1eaa46c..2f5e53b7b342db 100644 --- a/docs/user/alerting/rule-types/es-query.asciidoc +++ b/docs/user/alerting/rule-types/es-query.asciidoc @@ -1,18 +1,17 @@ [[rule-type-es-query]] -== {es} query - -:frontmatter-description: Create an {es} query rule, which generates alerts when your query meets a threshold. +== Create an {es} query rule +:frontmatter-description: Generate alerts when an {es} query meets a threshold. :frontmatter-tags-products: [kibana,alerting] -:frontmatter-tags-content-type: [overview] +:frontmatter-tags-content-type: [how-to] :frontmatter-tags-user-goals: [analyze] +++++ +{es} query +++++ The {es} query rule type runs a user-configured query, compares the number of matches to a configured threshold, and schedules actions to run when the threshold condition is met. -[float] -=== Create the rule - In *{stack-manage-app}* > *{rules-ui}*, click *Create rule*, fill in the name and optional tags, then select *{es} query*. An {es} query rule can be defined using KQL/Lucene or Query DSL. @@ -66,14 +65,14 @@ image::images/es-query-rule-action-summary.png[UI for defining alert summary act Alternatively, you can set the action frequency such that actions run for each alert. Choose how often the action runs (at each check interval, only when the alert status changes, or at a custom action interval). You must also choose an action group, which indicates whether the action runs when the query is matched or when the alert is recovered. +Each connector supports a specific set of actions for each action group. For example: [role="screenshot"] image::images/es-query-rule-action-query-matched.png[UI for defining a recovery action] // NOTE: This is an autogenerated screenshot. Do not edit it directly. -Each connector supports a specific set of actions for each action group. -For more details, refer to <>. +You can further refine the conditions under which actions run by specifying that actions only run they match a KQL query or when an alert occurs within a specific time frame. [float] === Add action variables diff --git a/docs/user/alerting/rule-types/geo-rule-types.asciidoc b/docs/user/alerting/rule-types/geo-rule-types.asciidoc index f8c750acea62c0..95fd9e0625881b 100644 --- a/docs/user/alerting/rule-types/geo-rule-types.asciidoc +++ b/docs/user/alerting/rule-types/geo-rule-types.asciidoc @@ -1,6 +1,12 @@ -[role="xpack"] [[geo-alerting]] -== Tracking containment +== Create a tracking containment rule +:frontmatter-description: Generate alerts when a geographic entity is contained or no longer contained within a boundary. +:frontmatter-tags-products: [kibana,alerting] +:frontmatter-tags-content-type: [how-to] +:frontmatter-tags-user-goals: [analyze] +++++ +Tracking containment +++++ The tracking containment rule alerts when an entity is contained or no longer contained within a boundary. diff --git a/docs/user/alerting/rule-types/index-threshold.asciidoc b/docs/user/alerting/rule-types/index-threshold.asciidoc index 69cdd2c3bbbcc0..9945b58df8bb7e 100644 --- a/docs/user/alerting/rule-types/index-threshold.asciidoc +++ b/docs/user/alerting/rule-types/index-threshold.asciidoc @@ -1,13 +1,17 @@ [[rule-type-index-threshold]] -== Index threshold - -:frontmatter-description: An index threshold rule generates alerts when an aggregated query meets a threshold. +== Create an index threshold rule +:frontmatter-description: Generate alerts when an aggregated query meets a threshold. :frontmatter-tags-products: [kibana,alerting] -:frontmatter-tags-content-type: [overview] +:frontmatter-tags-content-type: [how-to] :frontmatter-tags-user-goals: [analyze] +++++ +Index threshold +++++ The index threshold rule type runs an {es} query. It aggregates field values from documents, compares them to threshold values, and schedules actions to run when the thresholds are met. +In *{stack-manage-app}* > *{rules-ui}*, click *Create rule*, fill in the name and optional tags, then select *Index threshold*. + [float] === Define the conditions @@ -31,13 +35,35 @@ If data is available and all clauses have been defined, a preview chart will ren [[actions-index-threshold]] === Add actions -You can <> to your rule to generate notifications. +You can optionally send notifications when the rule conditions are met and when they are no longer met. +In particular, this rule type supports: + +* alert summaries +* actions that run when the threshold is met +* recovery actions that run when the rule conditions are no longer met + +For each action, you must choose a connector, which provides connection information for a {kib} service or third party integration. +For more information about all the supported connectors, go to <>. + +After you select a connector, you must set the action frequency. +You can choose to create a summary of alerts on each check interval or on a custom interval. +For example, summarize the new, ongoing, and recovered alerts at a custom interval: + +[role="screenshot"] +image::user/alerting/images/rule-types-index-threshold-example-action-summary.png[UI for defining alert summary action in an index threshold rule] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. + +Alternatively, you can set the action frequency such that actions run for each alert. +Choose how often the action runs (at each check interval, only when the alert status changes, or at a custom action interval). +You must also choose an action group, which indicates whether the action runs when the threshold is met or when the alert is recovered. +Each connector supports a specific set of actions for each action group. +For example: -Each action uses a connector, which provides connection information for a {kib} service or third party integration, depending on where you want to send the notifications. +[role="screenshot"] +image::user/alerting/images/rule-types-index-threshold-example-action.png[UI for defining an action for each alert] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. -After you choose a connector, you must choose an action group, which affects when the action runs. -The valid action groups for an index threshold rule are: `Threshold met` and `Recovered`. -Each connector supports a specific set of actions for each action group. For more details, refer to <>. +You can further refine the conditions under which actions run by specifying that actions only run they match a KQL query or when an alert occurs within a specific time frame. [float] [[action-variables-index-threshold]] @@ -118,8 +144,6 @@ For example, add an action that uses a server log connector to write an entry to image::user/alerting/images/rule-types-index-threshold-example-action.png[Add an action to the rule] // NOTE: This is an autogenerated screenshot. Do not edit it directly. -NOTE: The index threshold rule does not support alert summaries; therefore they do not appear in the action frequency options. - The unique action variables that you can use in the notification are listed in <>. For more information, refer to <> and <>. -- diff --git a/x-pack/test/screenshot_creation/apps/response_ops_docs/stack_alerting/index_threshold_rule.ts b/x-pack/test/screenshot_creation/apps/response_ops_docs/stack_alerting/index_threshold_rule.ts index a09333154bc0e6..9ca11a5a2dc450 100644 --- a/x-pack/test/screenshot_creation/apps/response_ops_docs/stack_alerting/index_threshold_rule.ts +++ b/x-pack/test/screenshot_creation/apps/response_ops_docs/stack_alerting/index_threshold_rule.ts @@ -79,7 +79,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.click('overExpressionSelect'); await testSubjects.setValue('overExpressionSelect', 'top'); await testSubjects.setValue('fieldsNumberSelect', '4'); - await testSubjects.setValue('fieldsExpressionSelect', 'host.keyword'); + await comboBox.set('fieldsExpressionSelect', 'host.keyword'); await commonScreenshots.takeScreenshot( 'rule-types-index-threshold-example-grouping', screenshotDirectories, @@ -128,6 +128,23 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 1024 ); + const actionFrequency = await testSubjects.find('summaryOrPerRuleSelect'); + await actionFrequency.click(); + const actionSummary = await testSubjects.find('actionNotifyWhen-option-summary'); + await actionSummary.click(); + const notifyWhen = await testSubjects.find('notifyWhenSelect'); + await notifyWhen.click(); + const customInterval = await testSubjects.find('onThrottleInterval'); + await customInterval.click(); + await testSubjects.setValue('throttleInput', '24'); + await testSubjects.scrollIntoView('addAlertActionButton'); + await commonScreenshots.takeScreenshot( + 'rule-types-index-threshold-example-action-summary', + screenshotDirectories, + 1400, + 1024 + ); + const saveButton = await testSubjects.find('saveRuleButton'); await saveButton.click(); const flyOutCancelButton = await testSubjects.find('euiFlyoutCloseButton'); From b7f1bb9c180be9ee09836e42a2bac13168cb1e5b Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Tue, 17 Oct 2023 08:41:27 -0600 Subject: [PATCH 65/87] [Controls] Remove `labs:dashboard:dashboardControls` UI setting (#168997) Closes https://github.com/elastic/kibana/issues/162978 ## Summary This PR removes the `labs:dashboard:dashboardControls` advanced UI setting. The removal of this setting is **not** a breaking change, as it hasn't functioned properly for quite some time; it is completely safe to remove this setting **regardless** of the previous value. Telemetry tracking for this setting is also no longer required. ### 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 ### 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> --- .../settings/setting_ids/index.ts | 1 - .../component/viewport/dashboard_viewport.tsx | 7 +----- .../server/collectors/management/schema.ts | 4 ---- .../server/collectors/management/types.ts | 1 - src/plugins/presentation_util/common/labs.ts | 22 +------------------ src/plugins/telemetry/schema/oss_plugins.json | 6 ----- .../controls/common/index.ts | 4 +--- .../controls/common/range_slider.ts | 2 -- .../page_objects/dashboard_page_controls.ts | 15 ------------- .../translations/translations/fr-FR.json | 2 -- .../translations/translations/ja-JP.json | 2 -- .../translations/translations/zh-CN.json | 2 -- .../controls_migration_smoke_test.ts | 1 - 13 files changed, 3 insertions(+), 66 deletions(-) diff --git a/packages/kbn-management/settings/setting_ids/index.ts b/packages/kbn-management/settings/setting_ids/index.ts index 9a1188b8689616..1ef2c6b223df44 100644 --- a/packages/kbn-management/settings/setting_ids/index.ts +++ b/packages/kbn-management/settings/setting_ids/index.ts @@ -52,7 +52,6 @@ export const TIMEPICKER_TIME_DEFAULTS_ID = 'timepicker:timeDefaults'; // Presentation labs settings export const LABS_CANVAS_BY_VALUE_EMBEDDABLE_ID = 'labs:canvas:byValueEmbeddable'; export const LABS_CANVAS_ENABLE_UI_ID = 'labs:canvas:enable_ui'; -export const LABS_DASHBOARD_CONTROLS_ID = 'labs:dashboard:dashboardControls'; export const LABS_DASHBOARD_DEFER_BELOW_FOLD_ID = 'labs:dashboard:deferBelowFold'; export const LABS_DASHBOARDS_ENABLE_UI_ID = 'labs:dashboard:enable_ui'; diff --git a/src/plugins/dashboard/public/dashboard_container/component/viewport/dashboard_viewport.tsx b/src/plugins/dashboard/public/dashboard_container/component/viewport/dashboard_viewport.tsx index e37f14ee5b9775..2072f3b630bbf6 100644 --- a/src/plugins/dashboard/public/dashboard_container/component/viewport/dashboard_viewport.tsx +++ b/src/plugins/dashboard/public/dashboard_container/component/viewport/dashboard_viewport.tsx @@ -16,7 +16,6 @@ import { ViewMode } from '@kbn/embeddable-plugin/public'; import { ExitFullScreenButton } from '@kbn/shared-ux-button-exit-full-screen'; import { DashboardGrid } from '../grid'; -import { pluginServices } from '../../../services/plugin_services'; import { useDashboardContainer } from '../../embeddable/dashboard_container'; import { DashboardEmptyScreen } from '../empty_screen/dashboard_empty_screen'; @@ -35,9 +34,6 @@ export const useDebouncedWidthObserver = (skipDebounce = false, wait = 100) => { }; export const DashboardViewportComponent = () => { - const { - settings: { isProjectEnabledInLabs }, - } = pluginServices.getServices(); const controlsRoot = useRef(null); const dashboard = useDashboardContainer(); @@ -60,7 +56,6 @@ export const DashboardViewportComponent = () => { const description = dashboard.select((state) => state.explicitInput.description); const focusedPanelId = dashboard.select((state) => state.componentState.focusedPanelId); const expandedPanelId = dashboard.select((state) => state.componentState.expandedPanelId); - const controlsEnabled = isProjectEnabledInLabs('labs:dashboard:dashboardControls'); const { ref: resizeRef, width: viewportWidth } = useDebouncedWidthObserver(!!focusedPanelId); @@ -71,7 +66,7 @@ export const DashboardViewportComponent = () => { return (

- {controlsEnabled && controlGroup && viewMode !== ViewMode.PRINT ? ( + {controlGroup && viewMode !== ViewMode.PRINT ? (
0 ? 'dshDashboardViewport-controls' : ''} ref={controlsRoot} diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index d9a7f95108e47d..0862d6ece004a4 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -489,10 +489,6 @@ export const stackManagementSchema: MakeSchemaFrom = { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, }, - 'labs:dashboard:dashboardControls': { - type: 'boolean', - _meta: { description: 'Non-default value of setting.' }, - }, 'labs:dashboard:linksPanel': { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts index 013b3de0574226..3499471e0d5a82 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -137,7 +137,6 @@ export interface UsageStats { 'labs:dashboard:enable_ui': boolean; 'labs:dashboard:linksPanel': boolean; 'labs:dashboard:deferBelowFold': boolean; - 'labs:dashboard:dashboardControls': boolean; 'discover:rowHeightOption': number; hideAnnouncements: boolean; isDefaultIndexMigrated: boolean; diff --git a/src/plugins/presentation_util/common/labs.ts b/src/plugins/presentation_util/common/labs.ts index 18fd77a3644294..a6ac9c7d8ae71c 100644 --- a/src/plugins/presentation_util/common/labs.ts +++ b/src/plugins/presentation_util/common/labs.ts @@ -11,15 +11,9 @@ import { i18n } from '@kbn/i18n'; export const LABS_PROJECT_PREFIX = 'labs:'; export const DEFER_BELOW_FOLD = `${LABS_PROJECT_PREFIX}dashboard:deferBelowFold` as const; export const DASHBOARD_LINKS_PANEL = `${LABS_PROJECT_PREFIX}dashboard:linksPanel` as const; -export const DASHBOARD_CONTROLS = `${LABS_PROJECT_PREFIX}dashboard:dashboardControls` as const; export const BY_VALUE_EMBEDDABLE = `${LABS_PROJECT_PREFIX}canvas:byValueEmbeddable` as const; -export const projectIDs = [ - DEFER_BELOW_FOLD, - DASHBOARD_CONTROLS, - BY_VALUE_EMBEDDABLE, - DASHBOARD_LINKS_PANEL, -] as const; +export const projectIDs = [DEFER_BELOW_FOLD, BY_VALUE_EMBEDDABLE, DASHBOARD_LINKS_PANEL] as const; export const environmentNames = ['kibana', 'browser', 'session'] as const; export const solutionNames = ['canvas', 'dashboard', 'presentation'] as const; @@ -49,20 +43,6 @@ export const projects: { [ID in ProjectID]: ProjectConfig & { id: ID } } = { }), solutions: ['dashboard'], }, - [DASHBOARD_CONTROLS]: { - id: DASHBOARD_CONTROLS, - isActive: true, - isDisplayed: true, - environments: ['kibana', 'browser', 'session'], - name: i18n.translate('presentationUtil.labs.enableDashboardControlsProjectName', { - defaultMessage: 'Enable dashboard controls', - }), - description: i18n.translate('presentationUtil.labs.enableDashboardControlsProjectDescription', { - defaultMessage: - 'Enables the controls system for dashboard, which allows dashboard authors to more easily build interactive elements for their users.', - }), - solutions: ['dashboard'], - }, [DASHBOARD_LINKS_PANEL]: { id: DASHBOARD_LINKS_PANEL, isActive: true, diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 8f2a80e5009869..0854944f394042 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -9923,12 +9923,6 @@ "description": "Non-default value of setting." } }, - "labs:dashboard:dashboardControls": { - "type": "boolean", - "_meta": { - "description": "Non-default value of setting." - } - }, "labs:dashboard:linksPanel": { "type": "boolean", "_meta": { diff --git a/test/functional/apps/dashboard_elements/controls/common/index.ts b/test/functional/apps/dashboard_elements/controls/common/index.ts index 8a9a7b8a548340..74e64052f1663b 100644 --- a/test/functional/apps/dashboard_elements/controls/common/index.ts +++ b/test/functional/apps/dashboard_elements/controls/common/index.ts @@ -13,7 +13,7 @@ export default function ({ loadTestFile, getService, getPageObjects }: FtrProvid const kibanaServer = getService('kibanaServer'); const security = getService('security'); - const { dashboardControls, dashboard } = getPageObjects(['dashboardControls', 'dashboard']); + const { dashboard } = getPageObjects(['dashboard']); async function setup() { await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/dashboard/current/data'); @@ -28,8 +28,6 @@ export default function ({ loadTestFile, getService, getPageObjects }: FtrProvid // enable the controls lab and navigate to the dashboard listing page to start await dashboard.navigateToApp(); - await dashboardControls.enableControlsLab(); - await dashboard.navigateToApp(); await dashboard.preserveCrossAppState(); } diff --git a/test/functional/apps/dashboard_elements/controls/common/range_slider.ts b/test/functional/apps/dashboard_elements/controls/common/range_slider.ts index b97acde63f40bb..17a1873ed098fe 100644 --- a/test/functional/apps/dashboard_elements/controls/common/range_slider.ts +++ b/test/functional/apps/dashboard_elements/controls/common/range_slider.ts @@ -50,8 +50,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { to: 'Dec 3, 2018 @ 00:00:00.000', }); await dashboard.navigateToApp(); - await dashboardControls.enableControlsLab(); - await dashboard.navigateToApp(); await dashboard.preserveCrossAppState(); await dashboard.gotoDashboardLandingPage(); await dashboard.clickNewDashboard(); diff --git a/test/functional/page_objects/dashboard_page_controls.ts b/test/functional/page_objects/dashboard_page_controls.ts index 720ff928b5605a..f3d828a04d9cc9 100644 --- a/test/functional/page_objects/dashboard_page_controls.ts +++ b/test/functional/page_objects/dashboard_page_controls.ts @@ -54,26 +54,11 @@ export class DashboardPageControls extends FtrService { private readonly testSubjects = this.ctx.getService('testSubjects'); private readonly common = this.ctx.getPageObject('common'); - private readonly header = this.ctx.getPageObject('header'); - private readonly settings = this.ctx.getPageObject('settings'); /* ----------------------------------------------------------- General controls functions ----------------------------------------------------------- */ - public async enableControlsLab() { - await this.header.clickStackManagement(); - await this.settings.clickKibanaSettings(); - - const currentValue = await this.settings.getAdvancedSettingAriaCheckbox( - 'labs:dashboard:dashboardControls' - ); - - if (currentValue !== 'true') { - await this.settings.toggleAdvancedSettingCheckbox('labs:dashboard:dashboardControls'); - } - } - public async expectControlsEmpty() { await this.testSubjects.existOrFail('controls-empty'); } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 861c6ddbca41bd..ec61fc696fd779 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -4792,8 +4792,6 @@ "presentationUtil.labs.components.titleLabel": "Ateliers", "presentationUtil.labs.enableByValueEmbeddableDescription": "Active la prise en charge pour les éléments d'incorporation by-value dans Canvas", "presentationUtil.labs.enableByValueEmbeddableName": "Éléments d'incorporation By-Value", - "presentationUtil.labs.enableDashboardControlsProjectDescription": "Active le système de contrôles pour le tableau de bord, ce qui permet à ses auteurs de créer plus facilement des éléments interactifs pour leurs utilisateurs.", - "presentationUtil.labs.enableDashboardControlsProjectName": "Activer les contrôles pour le tableau de bord", "presentationUtil.labs.enableDeferBelowFoldProjectDescription": "Les panneaux sous \"le pli\" (la zone masquée en dessous de la fenêtre accessible en faisant défiler), ne se chargeront pas immédiatement, mais seulement lorsqu'ils entreront dans la fenêtre d'affichage.", "presentationUtil.labs.enableDeferBelowFoldProjectName": "Différer le chargement des panneaux sous \"le pli\"", "presentationUtil.saveModalDashboard.addToDashboardLabel": "Ajouter au tableau de bord", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index ea24659866ab8b..ecf2b3716ddec2 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4808,8 +4808,6 @@ "presentationUtil.labs.components.titleLabel": "ラボ", "presentationUtil.labs.enableByValueEmbeddableDescription": "キャンバスでby-value埋め込み可能オブジェクトのサポートを有効にします", "presentationUtil.labs.enableByValueEmbeddableName": "By-Value埋め込み可能オブジェクト", - "presentationUtil.labs.enableDashboardControlsProjectDescription": "ダッシュボードのコントロールシステムを有効にします。これにより、ダッシュボードの作成者は、ユーザー向けのインタラクティブな要素をより簡単に構築できます。", - "presentationUtil.labs.enableDashboardControlsProjectName": "ダッシュボードコントロールを有効にする", "presentationUtil.labs.enableDeferBelowFoldProjectDescription": "「区切り」の下のすべてのパネル(ウィンドウ下部の下にある非表示の領域)はすぐに読み込まれません。ビューポートを入力するときにのみ読み込まれます", "presentationUtil.labs.enableDeferBelowFoldProjectName": "「区切り」の下のパネルの読み込みを延期", "presentationUtil.saveModalDashboard.addToDashboardLabel": "ダッシュボードに追加", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 1ba93d83b83df7..65c962b7db7f1e 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4807,8 +4807,6 @@ "presentationUtil.labs.components.titleLabel": "实验", "presentationUtil.labs.enableByValueEmbeddableDescription": "在 Canvas 中启用按值嵌入的支持", "presentationUtil.labs.enableByValueEmbeddableName": "按值嵌入", - "presentationUtil.labs.enableDashboardControlsProjectDescription": "为仪表板启用控件系统,这允许仪表板作者更轻松地为其用户构建交互式元素。", - "presentationUtil.labs.enableDashboardControlsProjectName": "启用仪表板控件", "presentationUtil.labs.enableDeferBelowFoldProjectDescription": "“折叠”下的任何面板即可通过滚动访问的窗口底部隐藏的区域,将不会立即加载,而仅在进入视区时加载", "presentationUtil.labs.enableDeferBelowFoldProjectName": "推迟加载“折叠”下的面板", "presentationUtil.saveModalDashboard.addToDashboardLabel": "添加到仪表板", diff --git a/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/controls_migration_smoke_test.ts b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/controls_migration_smoke_test.ts index f2c8d67d16b7e0..848be6a7838492 100644 --- a/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/controls_migration_smoke_test.ts +++ b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/controls_migration_smoke_test.ts @@ -55,7 +55,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should render all panels on the dashboard', async () => { - await dashboardControls.enableControlsLab(); await dashboard.navigateToApp(); await dashboard.loadSavedDashboard('[8.0.0] Controls Dashboard'); From fb387ba7fbcb6168ab228d18657b12cabf22176d Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 17 Oct 2023 07:47:17 -0700 Subject: [PATCH 66/87] [OAS] Add serverless connector APIs (#168661) --- x-pack/plugins/actions/docs/openapi/README.md | 24 +- .../plugins/actions/docs/openapi/bundled.json | 1582 ++++--- .../plugins/actions/docs/openapi/bundled.yaml | 983 ++-- .../docs/openapi/bundled_serverless.json | 4155 +++++++++++++++++ .../docs/openapi/bundled_serverless.yaml | 2985 ++++++++++++ .../examples/get_connector_response.yaml | 2 +- ...connector_types_generativeai_response.yaml | 20 + .../openapi/components/responses/400.yaml | 15 + .../connector_response_properties.yaml | 1 + ...tor_response_properties_cases_webhook.yaml | 3 +- ...nector_response_properties_d3security.yaml | 3 +- .../connector_response_properties_email.yaml | 3 +- .../connector_response_properties_genai.yaml | 3 +- .../connector_response_properties_index.yaml | 5 +- .../connector_response_properties_jira.yaml | 3 +- ...onnector_response_properties_opsgenie.yaml | 3 +- ...nnector_response_properties_pagerduty.yaml | 3 +- ...nnector_response_properties_resilient.yaml | 3 +- ...nnector_response_properties_serverlog.yaml | 3 +- ...nector_response_properties_servicenow.yaml | 3 +- ...r_response_properties_servicenow_itom.yaml | 3 +- ...or_response_properties_servicenow_sir.yaml | 3 +- ...nnector_response_properties_slack_api.yaml | 2 + ...tor_response_properties_slack_webhook.yaml | 2 + ...onnector_response_properties_swimlane.yaml | 3 +- .../connector_response_properties_teams.yaml | 2 + .../connector_response_properties_tines.yaml | 3 +- .../connector_response_properties_torq.yaml | 3 +- ...connector_response_properties_webhook.yaml | 4 +- ...onnector_response_properties_xmatters.yaml | 3 +- .../schemas/create_connector_request.yaml | 28 + .../openapi/components/schemas/features.yaml | 7 +- .../components/schemas/is_preconfigured.yaml | 4 +- .../schemas/referenced_by_count.yaml | 6 + .../schemas/run_connector_request.yaml | 26 + .../schemas/update_connector_request.yaml | 24 + .../actions/docs/openapi/entrypoint.yaml | 28 +- .../docs/openapi/entrypoint_serverless.yaml | 33 + .../openapi/paths/api@actions@connector.yaml | 44 + .../api@actions@connector@{connectorid}.yaml | 116 + ...ions@connector@{connectorid}@_execute.yaml | 75 + .../paths/api@actions@connector_types.yaml | 66 + .../openapi/paths/api@actions@connectors.yaml | 23 + .../s@{spaceid}@api@actions@connector.yaml | 30 +- ...}@api@actions@connector@{connectorid}.yaml | 109 +- ...ions@connector@{connectorid}@_execute.yaml | 29 +- ...{spaceid}@api@actions@connector_types.yaml | 2 +- .../s@{spaceid}@api@actions@connectors.yaml | 42 +- 48 files changed, 9414 insertions(+), 1108 deletions(-) create mode 100644 x-pack/plugins/actions/docs/openapi/bundled_serverless.json create mode 100644 x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/components/examples/get_connector_types_generativeai_response.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/components/responses/400.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/components/schemas/referenced_by_count.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_request.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/entrypoint_serverless.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/paths/api@actions@connector.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}@_execute.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/paths/api@actions@connector_types.yaml create mode 100644 x-pack/plugins/actions/docs/openapi/paths/api@actions@connectors.yaml diff --git a/x-pack/plugins/actions/docs/openapi/README.md b/x-pack/plugins/actions/docs/openapi/README.md index cb0ebce1448765..2bce08f0b1a4c6 100644 --- a/x-pack/plugins/actions/docs/openapi/README.md +++ b/x-pack/plugins/actions/docs/openapi/README.md @@ -16,19 +16,23 @@ A guide about the openApi specification can be found at [https://swagger.io/docs It is possible to validate the docs before bundling them with the following command in the `x-pack/plugins/actions/docs/openapi/` folder: - ``` - npx swagger-cli validate entrypoint.yaml - ``` +``` +npx swagger-cli validate entrypoint.yaml +npx swagger-cli validate entrypoint_serverless.yaml +``` Then you can generate the `bundled` files by running the following commands: - ``` - npx @redocly/cli bundle entrypoint.yaml --output bundled.yaml --ext yaml - npx @redocly/cli bundle entrypoint.yaml --output bundled.json --ext json - ``` +``` +npx @redocly/cli bundle entrypoint.yaml --output bundled.yaml --ext yaml +npx @redocly/cli bundle entrypoint.yaml --output bundled.json --ext json +npx @redocly/cli bundle entrypoint_serverless.yaml --output bundled_serverless.yaml --ext yaml +npx @redocly/cli bundle entrypoint_serverless.yaml --output bundled_serverless.json --ext json +``` You can run additional linting with the following command: - ``` - npx @redocly/cli lint bundled.json - ``` +``` +npx @redocly/cli lint bundled.json +npx @redocly/cli lint bundled_serverless.json +``` diff --git a/x-pack/plugins/actions/docs/openapi/bundled.json b/x-pack/plugins/actions/docs/openapi/bundled.json index 1db5f55b1c7441..06ef16a71f200f 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled.json +++ b/x-pack/plugins/actions/docs/openapi/bundled.json @@ -33,10 +33,546 @@ } ], "paths": { + "/api/actions/connector": { + "post": { + "summary": "Creates a connector.", + "operationId": "createConnector", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_connector_request" + }, + "examples": { + "createEmailConnectorRequest": { + "$ref": "#/components/examples/create_email_connector_request" + }, + "createIndexConnectorRequest": { + "$ref": "#/components/examples/create_index_connector_request" + }, + "createWebhookConnectorRequest": { + "$ref": "#/components/examples/create_webhook_connector_request" + }, + "createXmattersConnectorRequest": { + "$ref": "#/components/examples/create_xmatters_connector_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connector_response_properties" + }, + "examples": { + "createEmailConnectorResponse": { + "$ref": "#/components/examples/create_email_connector_response" + }, + "createIndexConnectorResponse": { + "$ref": "#/components/examples/create_index_connector_response" + }, + "createWebhookConnectorResponse": { + "$ref": "#/components/examples/create_webhook_connector_response" + }, + "createXmattersConnectorResponse": { + "$ref": "#/components/examples/create_xmatters_connector_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/actions/connector/{connectorId}": { + "get": { + "summary": "Retrieves a connector by ID.", + "operationId": "getConnector", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/connector_id" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connector_response_properties" + }, + "examples": { + "getConnectorResponse": { + "$ref": "#/components/examples/get_connector_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + }, + "404": { + "$ref": "#/components/responses/404" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "delete": { + "summary": "Deletes a connector.", + "operationId": "deleteConnector", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/connector_id" + } + ], + "responses": { + "204": { + "description": "Indicates a successful call." + }, + "401": { + "$ref": "#/components/responses/401" + }, + "404": { + "$ref": "#/components/responses/404" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "post": { + "summary": "Creates a connector.", + "operationId": "createConnectorId", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "in": "path", + "name": "connectorId", + "description": "A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated.\n", + "required": true, + "schema": { + "type": "string", + "example": "ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_connector_request" + }, + "examples": { + "createIndexConnectorRequest": { + "$ref": "#/components/examples/create_index_connector_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connector_response_properties" + }, + "examples": { + "createIndexConnectorResponse": { + "$ref": "#/components/examples/create_index_connector_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "put": { + "summary": "Updates the attributes for a connector.", + "operationId": "updateConnector", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/connector_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/update_connector_request" + }, + "examples": { + "updateIndexConnectorRequest": { + "$ref": "#/components/examples/update_index_connector_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connector_response_properties" + } + } + } + }, + "400": { + "$ref": "#/components/responses/401" + }, + "401": { + "$ref": "#/components/responses/401" + }, + "404": { + "$ref": "#/components/responses/404" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/actions/connector/{connectorId}/_execute": { + "post": { + "summary": "Runs a connector.", + "operationId": "runConnector", + "description": "You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. If you use an index connector, you must also have `all`, `create`, `index`, or `write` indices privileges.\n", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/connector_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/run_connector_request" + }, + "examples": { + "runIndexConnectorRequest": { + "$ref": "#/components/examples/run_index_connector_request" + }, + "runJiraConnectorRequest": { + "$ref": "#/components/examples/run_jira_connector_request" + }, + "runServerLogConnectorRequest": { + "$ref": "#/components/examples/run_server_log_connector_request" + }, + "runServiceNowITOMConnectorRequest": { + "$ref": "#/components/examples/run_servicenow_itom_connector_request" + }, + "runSwimlaneConnectorRequest": { + "$ref": "#/components/examples/run_swimlane_connector_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "connector_id", + "status" + ], + "properties": { + "connector_id": { + "type": "string", + "description": "The identifier for the connector." + }, + "data": { + "oneOf": [ + { + "type": "object", + "description": "Information returned from the action.", + "additionalProperties": true + }, + { + "type": "array", + "description": "An array of information returned from the action.", + "items": { + "type": "object" + } + } + ] + }, + "status": { + "type": "string", + "description": "The status of the action.", + "enum": [ + "error", + "ok" + ] + } + } + }, + "examples": { + "runIndexConnectorResponse": { + "$ref": "#/components/examples/run_index_connector_response" + }, + "runJiraConnectorResponse": { + "$ref": "#/components/examples/run_jira_connector_response" + }, + "runServerLogConnectorResponse": { + "$ref": "#/components/examples/run_server_log_connector_response" + }, + "runServiceNowITOMConnectorResponse": { + "$ref": "#/components/examples/run_servicenow_itom_connector_response" + }, + "runSwimlaneConnectorResponse": { + "$ref": "#/components/examples/run_swimlane_connector_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/actions/connectors": { + "get": { + "summary": "Retrieves all connectors.", + "operationId": "getConnectors", + "tags": [ + "connectors" + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/connector_response_properties" + } + }, + "examples": { + "getConnectorsResponse": { + "$ref": "#/components/examples/get_connectors_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/actions/connector_types": { + "get": { + "summary": "Retrieves a list of all connector types.", + "operationId": "getConnectorTypes", + "tags": [ + "connectors" + ], + "parameters": [ + { + "in": "query", + "name": "feature_id", + "description": "A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases).", + "schema": { + "$ref": "#/components/schemas/features" + } + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "title": "Get connector types response body properties", + "description": "The properties vary for each connector type.", + "type": "array", + "items": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Indicates whether the connector type is enabled in Kibana.", + "example": true + }, + "enabled_in_config": { + "type": "boolean", + "description": "Indicates whether the connector type is enabled in the Kibana configuration file.", + "example": true + }, + "enabled_in_license": { + "type": "boolean", + "description": "Indicates whether the connector is enabled in the license.", + "example": true + }, + "id": { + "$ref": "#/components/schemas/connector_types" + }, + "is_system_action_type": { + "type": "boolean", + "example": false + }, + "minimum_license_required": { + "type": "string", + "description": "The license that is required to use the connector type.", + "example": "basic" + }, + "name": { + "type": "string", + "description": "The name of the connector type.", + "example": "Index" + }, + "supported_feature_ids": { + "type": "array", + "description": "The features that are supported by the connector type.", + "items": { + "$ref": "#/components/schemas/features" + }, + "example": [ + "alerting", + "cases", + "siem" + ] + } + } + } + }, + "examples": { + "getConnectorTypesServerlessResponse": { + "$ref": "#/components/examples/get_connector_types_generativeai_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, "/s/{spaceId}/api/actions/connector": { "post": { "summary": "Creates a connector.", - "operationId": "createConnector", + "operationId": "createConnectorWithSpaceId", "description": "You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", "tags": [ "connectors" @@ -54,79 +590,7 @@ "content": { "application/json": { "schema": { - "title": "Create connector request body properties", - "description": "The properties vary depending on the connector type.", - "oneOf": [ - { - "$ref": "#/components/schemas/create_connector_request_bedrock" - }, - { - "$ref": "#/components/schemas/create_connector_request_cases_webhook" - }, - { - "$ref": "#/components/schemas/create_connector_request_d3security" - }, - { - "$ref": "#/components/schemas/create_connector_request_email" - }, - { - "$ref": "#/components/schemas/create_connector_request_genai" - }, - { - "$ref": "#/components/schemas/create_connector_request_index" - }, - { - "$ref": "#/components/schemas/create_connector_request_jira" - }, - { - "$ref": "#/components/schemas/create_connector_request_opsgenie" - }, - { - "$ref": "#/components/schemas/create_connector_request_pagerduty" - }, - { - "$ref": "#/components/schemas/create_connector_request_resilient" - }, - { - "$ref": "#/components/schemas/create_connector_request_serverlog" - }, - { - "$ref": "#/components/schemas/create_connector_request_servicenow" - }, - { - "$ref": "#/components/schemas/create_connector_request_servicenow_itom" - }, - { - "$ref": "#/components/schemas/create_connector_request_servicenow_sir" - }, - { - "$ref": "#/components/schemas/create_connector_request_slack_api" - }, - { - "$ref": "#/components/schemas/create_connector_request_slack_webhook" - }, - { - "$ref": "#/components/schemas/create_connector_request_swimlane" - }, - { - "$ref": "#/components/schemas/create_connector_request_teams" - }, - { - "$ref": "#/components/schemas/create_connector_request_tines" - }, - { - "$ref": "#/components/schemas/create_connector_request_torq" - }, - { - "$ref": "#/components/schemas/create_connector_request_webhook" - }, - { - "$ref": "#/components/schemas/create_connector_request_xmatters" - } - ], - "discriminator": { - "propertyName": "connector_type_id" - } + "$ref": "#/components/schemas/create_connector_request" }, "examples": { "createEmailConnectorRequest": { @@ -189,7 +653,7 @@ "/s/{spaceId}/api/actions/connector/{connectorId}": { "get": { "summary": "Retrieves a connector by ID.", - "operationId": "getConnector", + "operationId": "getConnectorWithSpaceId", "description": "You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", "tags": [ "connectors" @@ -222,28 +686,7 @@ "$ref": "#/components/responses/401" }, "404": { - "description": "Object is not found.", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "error": { - "type": "string", - "example": "Not Found" - }, - "message": { - "type": "string", - "example": "Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found" - }, - "statusCode": { - "type": "integer", - "example": 404 - } - } - } - } - } + "$ref": "#/components/responses/404" } }, "servers": [ @@ -254,7 +697,7 @@ }, "delete": { "summary": "Deletes a connector.", - "operationId": "deleteConnector", + "operationId": "deleteConnectorWithSpaceId", "description": "You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. WARNING: When you delete a connector, it cannot be recovered.\n", "tags": [ "connectors" @@ -278,28 +721,7 @@ "$ref": "#/components/responses/401" }, "404": { - "description": "Object is not found.", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "error": { - "type": "string", - "example": "Not Found" - }, - "message": { - "type": "string", - "example": "Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found" - }, - "statusCode": { - "type": "integer", - "example": 404 - } - } - } - } - } + "$ref": "#/components/responses/404" } }, "servers": [ @@ -310,7 +732,7 @@ }, "post": { "summary": "Creates a connector.", - "operationId": "createConnectorId", + "operationId": "createConnectorIdWithSpaceId", "description": "You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", "tags": [ "connectors" @@ -338,79 +760,7 @@ "content": { "application/json": { "schema": { - "title": "Create connector request body properties", - "description": "The properties vary depending on the connector type.", - "oneOf": [ - { - "$ref": "#/components/schemas/create_connector_request_bedrock" - }, - { - "$ref": "#/components/schemas/create_connector_request_cases_webhook" - }, - { - "$ref": "#/components/schemas/create_connector_request_d3security" - }, - { - "$ref": "#/components/schemas/create_connector_request_email" - }, - { - "$ref": "#/components/schemas/create_connector_request_genai" - }, - { - "$ref": "#/components/schemas/create_connector_request_index" - }, - { - "$ref": "#/components/schemas/create_connector_request_jira" - }, - { - "$ref": "#/components/schemas/create_connector_request_opsgenie" - }, - { - "$ref": "#/components/schemas/create_connector_request_pagerduty" - }, - { - "$ref": "#/components/schemas/create_connector_request_resilient" - }, - { - "$ref": "#/components/schemas/create_connector_request_serverlog" - }, - { - "$ref": "#/components/schemas/create_connector_request_servicenow" - }, - { - "$ref": "#/components/schemas/create_connector_request_servicenow_itom" - }, - { - "$ref": "#/components/schemas/create_connector_request_servicenow_sir" - }, - { - "$ref": "#/components/schemas/create_connector_request_slack_api" - }, - { - "$ref": "#/components/schemas/create_connector_request_slack_webhook" - }, - { - "$ref": "#/components/schemas/create_connector_request_swimlane" - }, - { - "$ref": "#/components/schemas/create_connector_request_teams" - }, - { - "$ref": "#/components/schemas/create_connector_request_tines" - }, - { - "$ref": "#/components/schemas/create_connector_request_torq" - }, - { - "$ref": "#/components/schemas/create_connector_request_webhook" - }, - { - "$ref": "#/components/schemas/create_connector_request_xmatters" - } - ], - "discriminator": { - "propertyName": "connector_type_id" - } + "$ref": "#/components/schemas/create_connector_request" }, "examples": { "createIndexConnectorRequest": { @@ -448,7 +798,7 @@ }, "put": { "summary": "Updates the attributes for a connector.", - "operationId": "updateConnector", + "operationId": "updateConnectorWithSpaceId", "description": "You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", "tags": [ "connectors" @@ -469,73 +819,7 @@ "content": { "application/json": { "schema": { - "title": "Update connector request body properties", - "description": "The properties vary depending on the connector type.", - "oneOf": [ - { - "$ref": "#/components/schemas/create_connector_request_bedrock" - }, - { - "$ref": "#/components/schemas/update_connector_request_cases_webhook" - }, - { - "$ref": "#/components/schemas/update_connector_request_d3security" - }, - { - "$ref": "#/components/schemas/update_connector_request_email" - }, - { - "$ref": "#/components/schemas/create_connector_request_genai" - }, - { - "$ref": "#/components/schemas/update_connector_request_index" - }, - { - "$ref": "#/components/schemas/update_connector_request_jira" - }, - { - "$ref": "#/components/schemas/update_connector_request_opsgenie" - }, - { - "$ref": "#/components/schemas/update_connector_request_pagerduty" - }, - { - "$ref": "#/components/schemas/update_connector_request_resilient" - }, - { - "$ref": "#/components/schemas/update_connector_request_serverlog" - }, - { - "$ref": "#/components/schemas/update_connector_request_servicenow" - }, - { - "$ref": "#/components/schemas/update_connector_request_servicenow_itom" - }, - { - "$ref": "#/components/schemas/update_connector_request_slack_api" - }, - { - "$ref": "#/components/schemas/update_connector_request_slack_webhook" - }, - { - "$ref": "#/components/schemas/update_connector_request_swimlane" - }, - { - "$ref": "#/components/schemas/update_connector_request_teams" - }, - { - "$ref": "#/components/schemas/update_connector_request_tines" - }, - { - "$ref": "#/components/schemas/update_connector_request_torq" - }, - { - "$ref": "#/components/schemas/update_connector_request_webhook" - }, - { - "$ref": "#/components/schemas/update_connector_request_xmatters" - } - ] + "$ref": "#/components/schemas/update_connector_request" }, "examples": { "updateIndexConnectorRequest": { @@ -557,28 +841,7 @@ } }, "400": { - "description": "Indicates a bad request.", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "error": { - "type": "string", - "example": "Bad Request" - }, - "message": { - "type": "string", - "example": "error validating action type config: [index]: expected value of type [string] but got [undefined]" - }, - "statusCode": { - "type": "integer", - "example": 400 - } - } - } - } - } + "$ref": "#/components/responses/401" }, "401": { "$ref": "#/components/responses/401" @@ -602,7 +865,7 @@ "/s/{spaceId}/api/actions/connectors": { "get": { "summary": "Retrieves all connectors.", - "operationId": "getConnectors", + "operationId": "getConnectorsWithSpaceId", "description": "You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", "tags": [ "connectors" @@ -616,60 +879,11 @@ "200": { "description": "Indicates a successful call.", "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "title": "Get connectors response body properties", - "description": "The properties vary for each connector type.", - "type": "object", - "required": [ - "connector_type_id", - "id", - "is_deprecated", - "is_preconfigured", - "name", - "referenced_by_count" - ], - "properties": { - "connector_type_id": { - "$ref": "#/components/schemas/connector_types" - }, - "config": { - "type": "object", - "description": "The configuration for the connector. Configuration properties vary depending on the connector type.", - "additionalProperties": true, - "nullable": true - }, - "id": { - "type": "string", - "description": "The identifier for the connector.", - "example": "b0766e10-d190-11ec-b04c-776c77d14fca" - }, - "is_deprecated": { - "$ref": "#/components/schemas/is_deprecated" - }, - "is_missing_secrets": { - "$ref": "#/components/schemas/is_missing_secrets" - }, - "is_preconfigured": { - "$ref": "#/components/schemas/is_preconfigured" - }, - "is_system_action": { - "$ref": "#/components/schemas/is_system_action" - }, - "name": { - "type": "string", - "description": "The display name for the connector.", - "example": "my-connector" - }, - "referenced_by_count": { - "type": "integer", - "description": "Indicates the number of saved objects that reference the connector. If `is_preconfigured` is true, this value is not calculated.", - "example": 2, - "default": 0 - } - } + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/connector_response_properties" } }, "examples": { @@ -699,7 +913,7 @@ "/s/{spaceId}/api/actions/connector_types": { "get": { "summary": "Retrieves a list of all connector types.", - "operationId": "getConnectorTypes", + "operationId": "getConnectorTypesWithSpaceId", "description": "You do not need any Kibana feature privileges to run this API.\n", "tags": [ "connectors" @@ -799,7 +1013,7 @@ "/s/{spaceId}/api/actions/connector/{connectorId}/_execute": { "post": { "summary": "Runs a connector.", - "operationId": "runConnector", + "operationId": "runConnectorWithSpaceId", "description": "You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. If you use an index connector, you must also have `all`, `create`, `index`, or `write` indices privileges.\n", "tags": [ "connectors" @@ -820,66 +1034,7 @@ "content": { "application/json": { "schema": { - "title": "Run connector request body properties", - "description": "The properties vary depending on the connector type.", - "type": "object", - "required": [ - "params" - ], - "properties": { - "params": { - "oneOf": [ - { - "$ref": "#/components/schemas/run_connector_params_documents" - }, - { - "$ref": "#/components/schemas/run_connector_params_level_message" - }, - { - "title": "Subaction parameters", - "description": "Test an action that involves a subaction.", - "oneOf": [ - { - "$ref": "#/components/schemas/run_connector_subaction_addevent" - }, - { - "$ref": "#/components/schemas/run_connector_subaction_closealert" - }, - { - "$ref": "#/components/schemas/run_connector_subaction_createalert" - }, - { - "$ref": "#/components/schemas/run_connector_subaction_fieldsbyissuetype" - }, - { - "$ref": "#/components/schemas/run_connector_subaction_getchoices" - }, - { - "$ref": "#/components/schemas/run_connector_subaction_getfields" - }, - { - "$ref": "#/components/schemas/run_connector_subaction_getincident" - }, - { - "$ref": "#/components/schemas/run_connector_subaction_issue" - }, - { - "$ref": "#/components/schemas/run_connector_subaction_issues" - }, - { - "$ref": "#/components/schemas/run_connector_subaction_issuetypes" - }, - { - "$ref": "#/components/schemas/run_connector_subaction_pushtoservice" - } - ], - "discriminator": { - "propertyName": "subAction" - } - } - ] - } - } + "$ref": "#/components/schemas/run_connector_request" }, "examples": { "runIndexConnectorRequest": { @@ -1400,24 +1555,24 @@ "description": "Cross-site request forgery protection", "required": true }, - "space_id": { + "connector_id": { "in": "path", - "name": "spaceId", - "description": "An identifier for the space. If `/s/` and the identifier are omitted from the path, the default space is used.", + "name": "connectorId", + "description": "An identifier for the connector.", "required": true, "schema": { "type": "string", - "example": "default" + "example": "df770e30-8b8b-11ed-a780-3b746c987a81" } }, - "connector_id": { + "space_id": { "in": "path", - "name": "connectorId", - "description": "An identifier for the connector.", + "name": "spaceId", + "description": "An identifier for the space. If `/s/` and the identifier are omitted from the path, the default space is used.", "required": true, "schema": { "type": "string", - "example": "df770e30-8b8b-11ed-a780-3b746c987a81" + "example": "default" } }, "action_id": { @@ -3188,6 +3343,81 @@ } } }, + "create_connector_request": { + "title": "Create connector request body properties", + "description": "The properties vary depending on the connector type.", + "oneOf": [ + { + "$ref": "#/components/schemas/create_connector_request_bedrock" + }, + { + "$ref": "#/components/schemas/create_connector_request_cases_webhook" + }, + { + "$ref": "#/components/schemas/create_connector_request_d3security" + }, + { + "$ref": "#/components/schemas/create_connector_request_email" + }, + { + "$ref": "#/components/schemas/create_connector_request_genai" + }, + { + "$ref": "#/components/schemas/create_connector_request_index" + }, + { + "$ref": "#/components/schemas/create_connector_request_jira" + }, + { + "$ref": "#/components/schemas/create_connector_request_opsgenie" + }, + { + "$ref": "#/components/schemas/create_connector_request_pagerduty" + }, + { + "$ref": "#/components/schemas/create_connector_request_resilient" + }, + { + "$ref": "#/components/schemas/create_connector_request_serverlog" + }, + { + "$ref": "#/components/schemas/create_connector_request_servicenow" + }, + { + "$ref": "#/components/schemas/create_connector_request_servicenow_itom" + }, + { + "$ref": "#/components/schemas/create_connector_request_servicenow_sir" + }, + { + "$ref": "#/components/schemas/create_connector_request_slack_api" + }, + { + "$ref": "#/components/schemas/create_connector_request_slack_webhook" + }, + { + "$ref": "#/components/schemas/create_connector_request_swimlane" + }, + { + "$ref": "#/components/schemas/create_connector_request_teams" + }, + { + "$ref": "#/components/schemas/create_connector_request_tines" + }, + { + "$ref": "#/components/schemas/create_connector_request_torq" + }, + { + "$ref": "#/components/schemas/create_connector_request_webhook" + }, + { + "$ref": "#/components/schemas/create_connector_request_xmatters" + } + ], + "discriminator": { + "propertyName": "connector_type_id" + } + }, "is_deprecated": { "type": "boolean", "description": "Indicates whether the connector type is deprecated.", @@ -3200,7 +3430,7 @@ }, "is_preconfigured": { "type": "boolean", - "description": "Indicates whether it is a preconfigured connector. If true, the `config` and `is_missing_secrets` properties are omitted from the response.", + "description": "Indicates whether it is a preconfigured connector. If true, the `config` and `is_missing_secrets` properties are omitted from the response. \n", "example": false }, "is_system_action": { @@ -3208,11 +3438,59 @@ "description": "Indicates whether the connector is used for system actions.", "example": false }, + "connector_response_properties_bedrock": { + "title": "Connector response properties for an Amazon Bedrock connector", + "type": "object", + "required": [ + "config", + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_bedrock" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".bedrock" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + } + } + }, + "referenced_by_count": { + "type": "integer", + "description": "Indicates the number of saved objects that reference the connector. If `is_preconfigured` is true, this value is not calculated. This property is returned only by the get all connectors API.\n", + "example": 2 + }, "connector_response_properties_cases_webhook": { "title": "Connector request properties for a Webhook - Case Management connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3249,6 +3527,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3256,7 +3537,6 @@ "title": "Connector response properties for a D3 Security connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3293,6 +3573,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3300,7 +3583,6 @@ "title": "Connector response properties for an email connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3337,6 +3619,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3344,7 +3629,6 @@ "title": "Connector response properties for an index connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3381,6 +3665,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3388,7 +3675,6 @@ "title": "Connector response properties for a Jira connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3425,6 +3711,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3432,7 +3721,6 @@ "title": "Connector response properties for an Opsgenie connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3469,6 +3757,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3476,7 +3767,6 @@ "title": "Connector response properties for a PagerDuty connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3513,6 +3803,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3520,7 +3813,6 @@ "title": "Connector response properties for a IBM Resilient connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3557,6 +3849,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3564,7 +3859,6 @@ "title": "Connector response properties for a server log connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3602,6 +3896,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3609,7 +3906,6 @@ "title": "Connector response properties for a ServiceNow ITSM connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3646,6 +3942,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3653,7 +3952,6 @@ "title": "Connector response properties for a ServiceNow ITOM connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3690,6 +3988,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3697,7 +3998,6 @@ "title": "Connector response properties for a ServiceNow SecOps connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3734,6 +4034,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3774,6 +4077,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3814,6 +4120,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3821,7 +4130,6 @@ "title": "Connector response properties for a Swimlane connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3858,6 +4166,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3901,6 +4212,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3908,7 +4222,6 @@ "title": "Connector response properties for a Tines connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3945,6 +4258,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3952,7 +4268,6 @@ "title": "Connector response properties for a Torq connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -3989,6 +4304,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -3996,7 +4314,6 @@ "title": "Connector response properties for a Webhook connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -4033,6 +4350,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -4040,7 +4360,6 @@ "title": "Connector response properties for an xMatters connector", "type": "object", "required": [ - "config", "connector_type_id", "id", "is_deprecated", @@ -4077,6 +4396,9 @@ "name": { "type": "string", "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" } } }, @@ -4084,6 +4406,9 @@ "title": "Connector response properties", "description": "The properties vary depending on the connector type.", "oneOf": [ + { + "$ref": "#/components/schemas/connector_response_properties_bedrock" + }, { "$ref": "#/components/schemas/connector_response_properties_cases_webhook" }, @@ -4149,6 +4474,26 @@ "propertyName": "connector_type_id" } }, + "update_connector_request_bedrock": { + "title": "Update Amazon Bedrock connector request", + "type": "object", + "required": [ + "config", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_bedrock" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_bedrock" + } + } + }, "update_connector_request_cases_webhook": { "title": "Update Webhook - Case Managment connector request", "type": "object", @@ -4524,44 +4869,73 @@ } } }, - "connector_types": { - "title": "Connector types", - "type": "string", - "description": "The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`.", - "enum": [ - ".bedrock", - ".cases-webhook", - ".d3security", - ".email", - ".gen-ai", - ".index", - ".jira", - ".opsgenie", - ".pagerduty", - ".resilient", - ".servicenow", - ".servicenow-itom", - ".servicenow-sir", - ".server-log", - ".slack", - ".slack_api", - ".swimlane", - ".teams", - ".tines", - ".torq", - ".webhook", - ".xmatters" - ], - "example": ".server-log" - }, - "features": { - "type": "string", - "description": "The feature that uses the connector. Valid values are `alerting`, `cases`, `uptime`, and `siem`.\n", - "enum": [ - "alerting", - "cases", - "uptime", - "siem" + "update_connector_request": { + "title": "Update connector request body properties", + "description": "The properties vary depending on the connector type.", + "oneOf": [ + { + "$ref": "#/components/schemas/update_connector_request_bedrock" + }, + { + "$ref": "#/components/schemas/update_connector_request_cases_webhook" + }, + { + "$ref": "#/components/schemas/update_connector_request_d3security" + }, + { + "$ref": "#/components/schemas/update_connector_request_email" + }, + { + "$ref": "#/components/schemas/create_connector_request_genai" + }, + { + "$ref": "#/components/schemas/update_connector_request_index" + }, + { + "$ref": "#/components/schemas/update_connector_request_jira" + }, + { + "$ref": "#/components/schemas/update_connector_request_opsgenie" + }, + { + "$ref": "#/components/schemas/update_connector_request_pagerduty" + }, + { + "$ref": "#/components/schemas/update_connector_request_resilient" + }, + { + "$ref": "#/components/schemas/update_connector_request_serverlog" + }, + { + "$ref": "#/components/schemas/update_connector_request_servicenow" + }, + { + "$ref": "#/components/schemas/update_connector_request_servicenow_itom" + }, + { + "$ref": "#/components/schemas/update_connector_request_slack_api" + }, + { + "$ref": "#/components/schemas/update_connector_request_slack_webhook" + }, + { + "$ref": "#/components/schemas/update_connector_request_swimlane" + }, + { + "$ref": "#/components/schemas/update_connector_request_teams" + }, + { + "$ref": "#/components/schemas/update_connector_request_tines" + }, + { + "$ref": "#/components/schemas/update_connector_request_torq" + }, + { + "$ref": "#/components/schemas/update_connector_request_webhook" + }, + { + "$ref": "#/components/schemas/update_connector_request_xmatters" + } ] }, "run_connector_params_documents": { @@ -5246,6 +5620,109 @@ } } }, + "run_connector_request": { + "title": "Run connector request body properties", + "description": "The properties vary depending on the connector type.", + "type": "object", + "required": [ + "params" + ], + "properties": { + "params": { + "oneOf": [ + { + "$ref": "#/components/schemas/run_connector_params_documents" + }, + { + "$ref": "#/components/schemas/run_connector_params_level_message" + }, + { + "title": "Subaction parameters", + "description": "Test an action that involves a subaction.", + "oneOf": [ + { + "$ref": "#/components/schemas/run_connector_subaction_addevent" + }, + { + "$ref": "#/components/schemas/run_connector_subaction_closealert" + }, + { + "$ref": "#/components/schemas/run_connector_subaction_createalert" + }, + { + "$ref": "#/components/schemas/run_connector_subaction_fieldsbyissuetype" + }, + { + "$ref": "#/components/schemas/run_connector_subaction_getchoices" + }, + { + "$ref": "#/components/schemas/run_connector_subaction_getfields" + }, + { + "$ref": "#/components/schemas/run_connector_subaction_getincident" + }, + { + "$ref": "#/components/schemas/run_connector_subaction_issue" + }, + { + "$ref": "#/components/schemas/run_connector_subaction_issues" + }, + { + "$ref": "#/components/schemas/run_connector_subaction_issuetypes" + }, + { + "$ref": "#/components/schemas/run_connector_subaction_pushtoservice" + } + ], + "discriminator": { + "propertyName": "subAction" + } + } + ] + } + } + }, + "features": { + "type": "string", + "description": "The feature that uses the connector.\n", + "enum": [ + "alerting", + "cases", + "generativeAI", + "siem", + "uptime" + ] + }, + "connector_types": { + "title": "Connector types", + "type": "string", + "description": "The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`.", + "enum": [ + ".bedrock", + ".cases-webhook", + ".d3security", + ".email", + ".gen-ai", + ".index", + ".jira", + ".opsgenie", + ".pagerduty", + ".resilient", + ".servicenow", + ".servicenow-itom", + ".servicenow-sir", + ".server-log", + ".slack", + ".slack_api", + ".swimlane", + ".teams", + ".tines", + ".torq", + ".webhook", + ".xmatters" + ], + "example": ".server-log" + }, "action_response_properties": { "title": "Action response properties", "description": "The properties vary depending on the action type.", @@ -5417,7 +5894,7 @@ } }, "get_connector_response": { - "summary": "A list of connector types", + "summary": "Get connector details.", "value": { "id": "df770e30-8b8b-11ed-a780-3b746c987a81", "name": "my_server_log_connector", @@ -5438,78 +5915,6 @@ } } }, - "get_connectors_response": { - "summary": "A list of connectors", - "value": [ - { - "id": "preconfigured-email-connector", - "name": "my-preconfigured-email-notification", - "connector_type_id": ".email", - "is_preconfigured": true, - "is_deprecated": false, - "referenced_by_count": 0, - "is_system_action": false - }, - { - "id": "e07d0c80-8b8b-11ed-a780-3b746c987a81", - "name": "my-index-connector", - "config": { - "index": "test-index", - "refresh": false, - "executionTimeField": null - }, - "connector_type_id": ".index", - "is_preconfigured": false, - "is_deprecated": false, - "referenced_by_count": 2, - "is_missing_secrets": false, - "is_system_action": false - } - ] - }, - "get_connector_types_response": { - "summary": "A list of connector types", - "value": [ - { - "id": ".swimlane", - "name": "Swimlane", - "enabled": true, - "enabled_in_config": true, - "enabled_in_license": true, - "minimum_license_required": "gold", - "supported_feature_ids": [ - "alerting", - "cases", - "siem" - ] - }, - { - "id": ".index", - "name": "Index", - "enabled": true, - "enabled_in_config": true, - "enabled_in_license": true, - "minimum_license_required": "basic", - "supported_feature_ids": [ - "alerting", - "uptime", - "siem" - ] - }, - { - "id": ".server-log", - "name": "Server log", - "enabled": true, - "enabled_in_config": true, - "enabled_in_license": true, - "minimum_license_required": "basic", - "supported_feature_ids": [ - "alerting", - "uptime" - ] - } - ] - }, "run_index_connector_request": { "summary": "Run an index connector.", "value": { @@ -5726,6 +6131,107 @@ }, "status": "ok" } + }, + "get_connectors_response": { + "summary": "A list of connectors", + "value": [ + { + "id": "preconfigured-email-connector", + "name": "my-preconfigured-email-notification", + "connector_type_id": ".email", + "is_preconfigured": true, + "is_deprecated": false, + "referenced_by_count": 0, + "is_system_action": false + }, + { + "id": "e07d0c80-8b8b-11ed-a780-3b746c987a81", + "name": "my-index-connector", + "config": { + "index": "test-index", + "refresh": false, + "executionTimeField": null + }, + "connector_type_id": ".index", + "is_preconfigured": false, + "is_deprecated": false, + "referenced_by_count": 2, + "is_missing_secrets": false, + "is_system_action": false + } + ] + }, + "get_connector_types_generativeai_response": { + "summary": "A list of connector types for the `generativeAI` feature.", + "value": [ + { + "id": ".gen-ai", + "name": "OpenAI", + "enabled": true, + "enabled_in_config": true, + "enabled_in_license": true, + "minimum_license_required": "enterprise", + "supported_feature_ids": [ + "generativeAI" + ], + "is_system_action_type": false + }, + { + "id": ".bedrock", + "name": "AWS Bedrock", + "enabled": true, + "enabled_in_config": true, + "enabled_in_license": true, + "minimum_license_required": "enterprise", + "supported_feature_ids": [ + "generativeAI" + ], + "is_system_action_type": false + } + ] + }, + "get_connector_types_response": { + "summary": "A list of connector types", + "value": [ + { + "id": ".swimlane", + "name": "Swimlane", + "enabled": true, + "enabled_in_config": true, + "enabled_in_license": true, + "minimum_license_required": "gold", + "supported_feature_ids": [ + "alerting", + "cases", + "siem" + ] + }, + { + "id": ".index", + "name": "Index", + "enabled": true, + "enabled_in_config": true, + "enabled_in_license": true, + "minimum_license_required": "basic", + "supported_feature_ids": [ + "alerting", + "uptime", + "siem" + ] + }, + { + "id": ".server-log", + "name": "Server log", + "enabled": true, + "enabled_in_config": true, + "enabled_in_license": true, + "minimum_license_required": "basic", + "supported_feature_ids": [ + "alerting", + "uptime" + ] + } + ] } }, "responses": { diff --git a/x-pack/plugins/actions/docs/openapi/bundled.yaml b/x-pack/plugins/actions/docs/openapi/bundled.yaml index 9fb7caccd1f170..099757a354f9ec 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled.yaml +++ b/x-pack/plugins/actions/docs/openapi/bundled.yaml @@ -18,49 +18,20 @@ tags: - name: connectors description: Connector APIs enable you to create and manage connectors. paths: - /s/{spaceId}/api/actions/connector: + /api/actions/connector: post: summary: Creates a connector. operationId: createConnector - description: | - You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: - connectors parameters: - $ref: '#/components/parameters/kbn_xsrf' - - $ref: '#/components/parameters/space_id' requestBody: required: true content: application/json: schema: - title: Create connector request body properties - description: The properties vary depending on the connector type. - oneOf: - - $ref: '#/components/schemas/create_connector_request_bedrock' - - $ref: '#/components/schemas/create_connector_request_cases_webhook' - - $ref: '#/components/schemas/create_connector_request_d3security' - - $ref: '#/components/schemas/create_connector_request_email' - - $ref: '#/components/schemas/create_connector_request_genai' - - $ref: '#/components/schemas/create_connector_request_index' - - $ref: '#/components/schemas/create_connector_request_jira' - - $ref: '#/components/schemas/create_connector_request_opsgenie' - - $ref: '#/components/schemas/create_connector_request_pagerduty' - - $ref: '#/components/schemas/create_connector_request_resilient' - - $ref: '#/components/schemas/create_connector_request_serverlog' - - $ref: '#/components/schemas/create_connector_request_servicenow' - - $ref: '#/components/schemas/create_connector_request_servicenow_itom' - - $ref: '#/components/schemas/create_connector_request_servicenow_sir' - - $ref: '#/components/schemas/create_connector_request_slack_api' - - $ref: '#/components/schemas/create_connector_request_slack_webhook' - - $ref: '#/components/schemas/create_connector_request_swimlane' - - $ref: '#/components/schemas/create_connector_request_teams' - - $ref: '#/components/schemas/create_connector_request_tines' - - $ref: '#/components/schemas/create_connector_request_torq' - - $ref: '#/components/schemas/create_connector_request_webhook' - - $ref: '#/components/schemas/create_connector_request_xmatters' - discriminator: - propertyName: connector_type_id + $ref: '#/components/schemas/create_connector_request' examples: createEmailConnectorRequest: $ref: '#/components/examples/create_email_connector_request' @@ -92,17 +63,14 @@ paths: - url: https://localhost:5601 servers: - url: https://localhost:5601 - /s/{spaceId}/api/actions/connector/{connectorId}: + /api/actions/connector/{connectorId}: get: summary: Retrieves a connector by ID. operationId: getConnector - description: | - You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: - connectors parameters: - $ref: '#/components/parameters/connector_id' - - $ref: '#/components/parameters/space_id' responses: '200': description: Indicates a successful call. @@ -116,26 +84,341 @@ paths: '401': $ref: '#/components/responses/401' '404': - description: Object is not found. + $ref: '#/components/responses/404' + servers: + - url: https://localhost:5601 + delete: + summary: Deletes a connector. + operationId: deleteConnector + tags: + - connectors + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/connector_id' + responses: + '204': + description: Indicates a successful call. + '401': + $ref: '#/components/responses/401' + '404': + $ref: '#/components/responses/404' + servers: + - url: https://localhost:5601 + post: + summary: Creates a connector. + operationId: createConnectorId + tags: + - connectors + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - in: path + name: connectorId + description: | + A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated. + required: true + schema: + type: string + example: ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/create_connector_request' + examples: + createIndexConnectorRequest: + $ref: '#/components/examples/create_index_connector_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/connector_response_properties' + examples: + createIndexConnectorResponse: + $ref: '#/components/examples/create_index_connector_response' + '401': + $ref: '#/components/responses/401' + servers: + - url: https://localhost:5601 + put: + summary: Updates the attributes for a connector. + operationId: updateConnector + tags: + - connectors + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/connector_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/update_connector_request' + examples: + updateIndexConnectorRequest: + $ref: '#/components/examples/update_index_connector_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/connector_response_properties' + '400': + $ref: '#/components/responses/401' + '401': + $ref: '#/components/responses/401' + '404': + $ref: '#/components/responses/404' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/actions/connector/{connectorId}/_execute: + post: + summary: Runs a connector. + operationId: runConnector + description: | + You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. If you use an index connector, you must also have `all`, `create`, `index`, or `write` indices privileges. + tags: + - connectors + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/connector_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/run_connector_request' + examples: + runIndexConnectorRequest: + $ref: '#/components/examples/run_index_connector_request' + runJiraConnectorRequest: + $ref: '#/components/examples/run_jira_connector_request' + runServerLogConnectorRequest: + $ref: '#/components/examples/run_server_log_connector_request' + runServiceNowITOMConnectorRequest: + $ref: '#/components/examples/run_servicenow_itom_connector_request' + runSwimlaneConnectorRequest: + $ref: '#/components/examples/run_swimlane_connector_request' + responses: + '200': + description: Indicates a successful call. content: application/json: schema: type: object + required: + - connector_id + - status properties: - error: + connector_id: type: string - example: Not Found - message: + description: The identifier for the connector. + data: + oneOf: + - type: object + description: Information returned from the action. + additionalProperties: true + - type: array + description: An array of information returned from the action. + items: + type: object + status: type: string - example: Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found - statusCode: - type: integer - example: 404 + description: The status of the action. + enum: + - error + - ok + examples: + runIndexConnectorResponse: + $ref: '#/components/examples/run_index_connector_response' + runJiraConnectorResponse: + $ref: '#/components/examples/run_jira_connector_response' + runServerLogConnectorResponse: + $ref: '#/components/examples/run_server_log_connector_response' + runServiceNowITOMConnectorResponse: + $ref: '#/components/examples/run_servicenow_itom_connector_response' + runSwimlaneConnectorResponse: + $ref: '#/components/examples/run_swimlane_connector_response' + '401': + $ref: '#/components/responses/401' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/actions/connectors: + get: + summary: Retrieves all connectors. + operationId: getConnectors + tags: + - connectors + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/connector_response_properties' + examples: + getConnectorsResponse: + $ref: '#/components/examples/get_connectors_response' + '401': + $ref: '#/components/responses/401' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/actions/connector_types: + get: + summary: Retrieves a list of all connector types. + operationId: getConnectorTypes + tags: + - connectors + parameters: + - in: query + name: feature_id + description: A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases). + schema: + $ref: '#/components/schemas/features' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + title: Get connector types response body properties + description: The properties vary for each connector type. + type: array + items: + type: object + properties: + enabled: + type: boolean + description: Indicates whether the connector type is enabled in Kibana. + example: true + enabled_in_config: + type: boolean + description: Indicates whether the connector type is enabled in the Kibana configuration file. + example: true + enabled_in_license: + type: boolean + description: Indicates whether the connector is enabled in the license. + example: true + id: + $ref: '#/components/schemas/connector_types' + is_system_action_type: + type: boolean + example: false + minimum_license_required: + type: string + description: The license that is required to use the connector type. + example: basic + name: + type: string + description: The name of the connector type. + example: Index + supported_feature_ids: + type: array + description: The features that are supported by the connector type. + items: + $ref: '#/components/schemas/features' + example: + - alerting + - cases + - siem + examples: + getConnectorTypesServerlessResponse: + $ref: '#/components/examples/get_connector_types_generativeai_response' + '401': + $ref: '#/components/responses/401' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /s/{spaceId}/api/actions/connector: + post: + summary: Creates a connector. + operationId: createConnectorWithSpaceId + description: | + You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. + tags: + - connectors + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/space_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/create_connector_request' + examples: + createEmailConnectorRequest: + $ref: '#/components/examples/create_email_connector_request' + createIndexConnectorRequest: + $ref: '#/components/examples/create_index_connector_request' + createWebhookConnectorRequest: + $ref: '#/components/examples/create_webhook_connector_request' + createXmattersConnectorRequest: + $ref: '#/components/examples/create_xmatters_connector_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/connector_response_properties' + examples: + createEmailConnectorResponse: + $ref: '#/components/examples/create_email_connector_response' + createIndexConnectorResponse: + $ref: '#/components/examples/create_index_connector_response' + createWebhookConnectorResponse: + $ref: '#/components/examples/create_webhook_connector_response' + createXmattersConnectorResponse: + $ref: '#/components/examples/create_xmatters_connector_response' + '401': + $ref: '#/components/responses/401' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /s/{spaceId}/api/actions/connector/{connectorId}: + get: + summary: Retrieves a connector by ID. + operationId: getConnectorWithSpaceId + description: | + You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. + tags: + - connectors + parameters: + - $ref: '#/components/parameters/connector_id' + - $ref: '#/components/parameters/space_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/connector_response_properties' + examples: + getConnectorResponse: + $ref: '#/components/examples/get_connector_response' + '401': + $ref: '#/components/responses/401' + '404': + $ref: '#/components/responses/404' servers: - url: https://localhost:5601 delete: summary: Deletes a connector. - operationId: deleteConnector + operationId: deleteConnectorWithSpaceId description: | You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. WARNING: When you delete a connector, it cannot be recovered. tags: @@ -150,26 +433,12 @@ paths: '401': $ref: '#/components/responses/401' '404': - description: Object is not found. - content: - application/json: - schema: - type: object - properties: - error: - type: string - example: Not Found - message: - type: string - example: Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found - statusCode: - type: integer - example: 404 + $ref: '#/components/responses/404' servers: - url: https://localhost:5601 post: summary: Creates a connector. - operationId: createConnectorId + operationId: createConnectorIdWithSpaceId description: | You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: @@ -189,33 +458,7 @@ paths: content: application/json: schema: - title: Create connector request body properties - description: The properties vary depending on the connector type. - oneOf: - - $ref: '#/components/schemas/create_connector_request_bedrock' - - $ref: '#/components/schemas/create_connector_request_cases_webhook' - - $ref: '#/components/schemas/create_connector_request_d3security' - - $ref: '#/components/schemas/create_connector_request_email' - - $ref: '#/components/schemas/create_connector_request_genai' - - $ref: '#/components/schemas/create_connector_request_index' - - $ref: '#/components/schemas/create_connector_request_jira' - - $ref: '#/components/schemas/create_connector_request_opsgenie' - - $ref: '#/components/schemas/create_connector_request_pagerduty' - - $ref: '#/components/schemas/create_connector_request_resilient' - - $ref: '#/components/schemas/create_connector_request_serverlog' - - $ref: '#/components/schemas/create_connector_request_servicenow' - - $ref: '#/components/schemas/create_connector_request_servicenow_itom' - - $ref: '#/components/schemas/create_connector_request_servicenow_sir' - - $ref: '#/components/schemas/create_connector_request_slack_api' - - $ref: '#/components/schemas/create_connector_request_slack_webhook' - - $ref: '#/components/schemas/create_connector_request_swimlane' - - $ref: '#/components/schemas/create_connector_request_teams' - - $ref: '#/components/schemas/create_connector_request_tines' - - $ref: '#/components/schemas/create_connector_request_torq' - - $ref: '#/components/schemas/create_connector_request_webhook' - - $ref: '#/components/schemas/create_connector_request_xmatters' - discriminator: - propertyName: connector_type_id + $ref: '#/components/schemas/create_connector_request' examples: createIndexConnectorRequest: $ref: '#/components/examples/create_index_connector_request' @@ -235,7 +478,7 @@ paths: - url: https://localhost:5601 put: summary: Updates the attributes for a connector. - operationId: updateConnector + operationId: updateConnectorWithSpaceId description: | You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: @@ -249,30 +492,7 @@ paths: content: application/json: schema: - title: Update connector request body properties - description: The properties vary depending on the connector type. - oneOf: - - $ref: '#/components/schemas/create_connector_request_bedrock' - - $ref: '#/components/schemas/update_connector_request_cases_webhook' - - $ref: '#/components/schemas/update_connector_request_d3security' - - $ref: '#/components/schemas/update_connector_request_email' - - $ref: '#/components/schemas/create_connector_request_genai' - - $ref: '#/components/schemas/update_connector_request_index' - - $ref: '#/components/schemas/update_connector_request_jira' - - $ref: '#/components/schemas/update_connector_request_opsgenie' - - $ref: '#/components/schemas/update_connector_request_pagerduty' - - $ref: '#/components/schemas/update_connector_request_resilient' - - $ref: '#/components/schemas/update_connector_request_serverlog' - - $ref: '#/components/schemas/update_connector_request_servicenow' - - $ref: '#/components/schemas/update_connector_request_servicenow_itom' - - $ref: '#/components/schemas/update_connector_request_slack_api' - - $ref: '#/components/schemas/update_connector_request_slack_webhook' - - $ref: '#/components/schemas/update_connector_request_swimlane' - - $ref: '#/components/schemas/update_connector_request_teams' - - $ref: '#/components/schemas/update_connector_request_tines' - - $ref: '#/components/schemas/update_connector_request_torq' - - $ref: '#/components/schemas/update_connector_request_webhook' - - $ref: '#/components/schemas/update_connector_request_xmatters' + $ref: '#/components/schemas/update_connector_request' examples: updateIndexConnectorRequest: $ref: '#/components/examples/update_index_connector_request' @@ -284,21 +504,7 @@ paths: schema: $ref: '#/components/schemas/connector_response_properties' '400': - description: Indicates a bad request. - content: - application/json: - schema: - type: object - properties: - error: - type: string - example: Bad Request - message: - type: string - example: 'error validating action type config: [index]: expected value of type [string] but got [undefined]' - statusCode: - type: integer - example: 400 + $ref: '#/components/responses/401' '401': $ref: '#/components/responses/401' '404': @@ -310,7 +516,7 @@ paths: /s/{spaceId}/api/actions/connectors: get: summary: Retrieves all connectors. - operationId: getConnectors + operationId: getConnectorsWithSpaceId description: | You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: @@ -325,45 +531,7 @@ paths: schema: type: array items: - title: Get connectors response body properties - description: The properties vary for each connector type. - type: object - required: - - connector_type_id - - id - - is_deprecated - - is_preconfigured - - name - - referenced_by_count - properties: - connector_type_id: - $ref: '#/components/schemas/connector_types' - config: - type: object - description: The configuration for the connector. Configuration properties vary depending on the connector type. - additionalProperties: true - nullable: true - id: - type: string - description: The identifier for the connector. - example: b0766e10-d190-11ec-b04c-776c77d14fca - is_deprecated: - $ref: '#/components/schemas/is_deprecated' - is_missing_secrets: - $ref: '#/components/schemas/is_missing_secrets' - is_preconfigured: - $ref: '#/components/schemas/is_preconfigured' - is_system_action: - $ref: '#/components/schemas/is_system_action' - name: - type: string - description: The display name for the connector. - example: my-connector - referenced_by_count: - type: integer - description: Indicates the number of saved objects that reference the connector. If `is_preconfigured` is true, this value is not calculated. - example: 2 - default: 0 + $ref: '#/components/schemas/connector_response_properties' examples: getConnectorsResponse: $ref: '#/components/examples/get_connectors_response' @@ -376,7 +544,7 @@ paths: /s/{spaceId}/api/actions/connector_types: get: summary: Retrieves a list of all connector types. - operationId: getConnectorTypes + operationId: getConnectorTypesWithSpaceId description: | You do not need any Kibana feature privileges to run this API. tags: @@ -443,7 +611,7 @@ paths: /s/{spaceId}/api/actions/connector/{connectorId}/_execute: post: summary: Runs a connector. - operationId: runConnector + operationId: runConnectorWithSpaceId description: | You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. If you use an index connector, you must also have `all`, `create`, `index`, or `write` indices privileges. tags: @@ -457,32 +625,7 @@ paths: content: application/json: schema: - title: Run connector request body properties - description: The properties vary depending on the connector type. - type: object - required: - - params - properties: - params: - oneOf: - - $ref: '#/components/schemas/run_connector_params_documents' - - $ref: '#/components/schemas/run_connector_params_level_message' - - title: Subaction parameters - description: Test an action that involves a subaction. - oneOf: - - $ref: '#/components/schemas/run_connector_subaction_addevent' - - $ref: '#/components/schemas/run_connector_subaction_closealert' - - $ref: '#/components/schemas/run_connector_subaction_createalert' - - $ref: '#/components/schemas/run_connector_subaction_fieldsbyissuetype' - - $ref: '#/components/schemas/run_connector_subaction_getchoices' - - $ref: '#/components/schemas/run_connector_subaction_getfields' - - $ref: '#/components/schemas/run_connector_subaction_getincident' - - $ref: '#/components/schemas/run_connector_subaction_issue' - - $ref: '#/components/schemas/run_connector_subaction_issues' - - $ref: '#/components/schemas/run_connector_subaction_issuetypes' - - $ref: '#/components/schemas/run_connector_subaction_pushtoservice' - discriminator: - propertyName: subAction + $ref: '#/components/schemas/run_connector_request' examples: runIndexConnectorRequest: $ref: '#/components/examples/run_index_connector_request' @@ -796,14 +939,6 @@ components: name: kbn-xsrf description: Cross-site request forgery protection required: true - space_id: - in: path - name: spaceId - description: An identifier for the space. If `/s/` and the identifier are omitted from the path, the default space is used. - required: true - schema: - type: string - example: default connector_id: in: path name: connectorId @@ -812,6 +947,14 @@ components: schema: type: string example: df770e30-8b8b-11ed-a780-3b746c987a81 + space_id: + in: path + name: spaceId + description: An identifier for the space. If `/s/` and the identifier are omitted from the path, the default space is used. + required: true + schema: + type: string + example: default action_id: in: path name: actionId @@ -2189,30 +2332,95 @@ components: name: type: string description: The display name for the connector. - example: my-connector - secrets: - $ref: '#/components/schemas/secrets_properties_xmatters' - is_deprecated: - type: boolean - description: Indicates whether the connector type is deprecated. - example: false - is_missing_secrets: - type: boolean - description: Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type. - example: false - is_preconfigured: - type: boolean - description: Indicates whether it is a preconfigured connector. If true, the `config` and `is_missing_secrets` properties are omitted from the response. - example: false - is_system_action: - type: boolean - description: Indicates whether the connector is used for system actions. - example: false + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_xmatters' + create_connector_request: + title: Create connector request body properties + description: The properties vary depending on the connector type. + oneOf: + - $ref: '#/components/schemas/create_connector_request_bedrock' + - $ref: '#/components/schemas/create_connector_request_cases_webhook' + - $ref: '#/components/schemas/create_connector_request_d3security' + - $ref: '#/components/schemas/create_connector_request_email' + - $ref: '#/components/schemas/create_connector_request_genai' + - $ref: '#/components/schemas/create_connector_request_index' + - $ref: '#/components/schemas/create_connector_request_jira' + - $ref: '#/components/schemas/create_connector_request_opsgenie' + - $ref: '#/components/schemas/create_connector_request_pagerduty' + - $ref: '#/components/schemas/create_connector_request_resilient' + - $ref: '#/components/schemas/create_connector_request_serverlog' + - $ref: '#/components/schemas/create_connector_request_servicenow' + - $ref: '#/components/schemas/create_connector_request_servicenow_itom' + - $ref: '#/components/schemas/create_connector_request_servicenow_sir' + - $ref: '#/components/schemas/create_connector_request_slack_api' + - $ref: '#/components/schemas/create_connector_request_slack_webhook' + - $ref: '#/components/schemas/create_connector_request_swimlane' + - $ref: '#/components/schemas/create_connector_request_teams' + - $ref: '#/components/schemas/create_connector_request_tines' + - $ref: '#/components/schemas/create_connector_request_torq' + - $ref: '#/components/schemas/create_connector_request_webhook' + - $ref: '#/components/schemas/create_connector_request_xmatters' + discriminator: + propertyName: connector_type_id + is_deprecated: + type: boolean + description: Indicates whether the connector type is deprecated. + example: false + is_missing_secrets: + type: boolean + description: Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type. + example: false + is_preconfigured: + type: boolean + description: | + Indicates whether it is a preconfigured connector. If true, the `config` and `is_missing_secrets` properties are omitted from the response. + example: false + is_system_action: + type: boolean + description: Indicates whether the connector is used for system actions. + example: false + connector_response_properties_bedrock: + title: Connector response properties for an Amazon Bedrock connector + type: object + required: + - config + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_bedrock' + connector_type_id: + type: string + description: The type of connector. + enum: + - .bedrock + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + type: integer + description: | + Indicates the number of saved objects that reference the connector. If `is_preconfigured` is true, this value is not calculated. This property is returned only by the get all connectors API. + example: 2 connector_response_properties_cases_webhook: title: Connector request properties for a Webhook - Case Management connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2240,11 +2448,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_d3security: title: Connector response properties for a D3 Security connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2272,11 +2481,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_email: title: Connector response properties for an email connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2304,11 +2514,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_index: title: Connector response properties for an index connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2336,11 +2547,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_jira: title: Connector response properties for a Jira connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2368,11 +2580,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_opsgenie: title: Connector response properties for an Opsgenie connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2400,11 +2613,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_pagerduty: title: Connector response properties for a PagerDuty connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2432,11 +2646,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_resilient: title: Connector response properties for a IBM Resilient connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2464,11 +2679,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_serverlog: title: Connector response properties for a server log connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2497,11 +2713,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_servicenow: title: Connector response properties for a ServiceNow ITSM connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2529,11 +2746,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_servicenow_itom: title: Connector response properties for a ServiceNow ITOM connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2561,11 +2779,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_servicenow_sir: title: Connector response properties for a ServiceNow SecOps connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2593,6 +2812,8 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_slack_api: title: Connector response properties for a Slack connector type: object @@ -2622,6 +2843,8 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_slack_webhook: title: Connector response properties for a Slack connector type: object @@ -2651,11 +2874,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_swimlane: title: Connector response properties for a Swimlane connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2683,6 +2907,8 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_teams: title: Connector response properties for a Microsoft Teams connector type: object @@ -2714,11 +2940,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_tines: title: Connector response properties for a Tines connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2746,11 +2973,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_torq: title: Connector response properties for a Torq connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2778,11 +3006,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_webhook: title: Connector response properties for a Webhook connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2810,11 +3039,12 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties_xmatters: title: Connector response properties for an xMatters connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -2842,10 +3072,13 @@ components: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' connector_response_properties: title: Connector response properties description: The properties vary depending on the connector type. oneOf: + - $ref: '#/components/schemas/connector_response_properties_bedrock' - $ref: '#/components/schemas/connector_response_properties_cases_webhook' - $ref: '#/components/schemas/connector_response_properties_d3security' - $ref: '#/components/schemas/connector_response_properties_email' @@ -2868,6 +3101,20 @@ components: - $ref: '#/components/schemas/connector_response_properties_xmatters' discriminator: propertyName: connector_type_id + update_connector_request_bedrock: + title: Update Amazon Bedrock connector request + type: object + required: + - config + - name + properties: + config: + $ref: '#/components/schemas/config_properties_bedrock' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_bedrock' update_connector_request_cases_webhook: title: Update Webhook - Case Managment connector request type: object @@ -3135,43 +3382,31 @@ components: description: The display name for the connector. secrets: $ref: '#/components/schemas/secrets_properties_xmatters' - connector_types: - title: Connector types - type: string - description: The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`. - enum: - - .bedrock - - .cases-webhook - - .d3security - - .email - - .gen-ai - - .index - - .jira - - .opsgenie - - .pagerduty - - .resilient - - .servicenow - - .servicenow-itom - - .servicenow-sir - - .server-log - - .slack - - .slack_api - - .swimlane - - .teams - - .tines - - .torq - - .webhook - - .xmatters - example: .server-log - features: - type: string - description: | - The feature that uses the connector. Valid values are `alerting`, `cases`, `uptime`, and `siem`. - enum: - - alerting - - cases - - uptime - - siem + update_connector_request: + title: Update connector request body properties + description: The properties vary depending on the connector type. + oneOf: + - $ref: '#/components/schemas/update_connector_request_bedrock' + - $ref: '#/components/schemas/update_connector_request_cases_webhook' + - $ref: '#/components/schemas/update_connector_request_d3security' + - $ref: '#/components/schemas/update_connector_request_email' + - $ref: '#/components/schemas/create_connector_request_genai' + - $ref: '#/components/schemas/update_connector_request_index' + - $ref: '#/components/schemas/update_connector_request_jira' + - $ref: '#/components/schemas/update_connector_request_opsgenie' + - $ref: '#/components/schemas/update_connector_request_pagerduty' + - $ref: '#/components/schemas/update_connector_request_resilient' + - $ref: '#/components/schemas/update_connector_request_serverlog' + - $ref: '#/components/schemas/update_connector_request_servicenow' + - $ref: '#/components/schemas/update_connector_request_servicenow_itom' + - $ref: '#/components/schemas/update_connector_request_slack_api' + - $ref: '#/components/schemas/update_connector_request_slack_webhook' + - $ref: '#/components/schemas/update_connector_request_swimlane' + - $ref: '#/components/schemas/update_connector_request_teams' + - $ref: '#/components/schemas/update_connector_request_tines' + - $ref: '#/components/schemas/update_connector_request_torq' + - $ref: '#/components/schemas/update_connector_request_webhook' + - $ref: '#/components/schemas/update_connector_request_xmatters' run_connector_params_documents: title: Index connector parameters description: Test an action that indexes a document into Elasticsearch. @@ -3661,6 +3896,71 @@ components: urgency: type: string description: The urgency of the incident for ServiceNow ITSM connectors. + run_connector_request: + title: Run connector request body properties + description: The properties vary depending on the connector type. + type: object + required: + - params + properties: + params: + oneOf: + - $ref: '#/components/schemas/run_connector_params_documents' + - $ref: '#/components/schemas/run_connector_params_level_message' + - title: Subaction parameters + description: Test an action that involves a subaction. + oneOf: + - $ref: '#/components/schemas/run_connector_subaction_addevent' + - $ref: '#/components/schemas/run_connector_subaction_closealert' + - $ref: '#/components/schemas/run_connector_subaction_createalert' + - $ref: '#/components/schemas/run_connector_subaction_fieldsbyissuetype' + - $ref: '#/components/schemas/run_connector_subaction_getchoices' + - $ref: '#/components/schemas/run_connector_subaction_getfields' + - $ref: '#/components/schemas/run_connector_subaction_getincident' + - $ref: '#/components/schemas/run_connector_subaction_issue' + - $ref: '#/components/schemas/run_connector_subaction_issues' + - $ref: '#/components/schemas/run_connector_subaction_issuetypes' + - $ref: '#/components/schemas/run_connector_subaction_pushtoservice' + discriminator: + propertyName: subAction + features: + type: string + description: | + The feature that uses the connector. + enum: + - alerting + - cases + - generativeAI + - siem + - uptime + connector_types: + title: Connector types + type: string + description: The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`. + enum: + - .bedrock + - .cases-webhook + - .d3security + - .email + - .gen-ai + - .index + - .jira + - .opsgenie + - .pagerduty + - .resilient + - .servicenow + - .servicenow-itom + - .servicenow-sir + - .server-log + - .slack + - .slack_api + - .swimlane + - .teams + - .tines + - .torq + - .webhook + - .xmatters + example: .server-log action_response_properties: title: Action response properties description: The properties vary depending on the action type. @@ -3795,7 +4095,7 @@ components: is_missing_secrets: false is_system_action: false get_connector_response: - summary: A list of connector types + summary: Get connector details. value: id: df770e30-8b8b-11ed-a780-3b746c987a81 name: my_server_log_connector @@ -3811,60 +4111,6 @@ components: name: updated-connector config: index: updated-index - get_connectors_response: - summary: A list of connectors - value: - - id: preconfigured-email-connector - name: my-preconfigured-email-notification - connector_type_id: .email - is_preconfigured: true - is_deprecated: false - referenced_by_count: 0 - is_system_action: false - - id: e07d0c80-8b8b-11ed-a780-3b746c987a81 - name: my-index-connector - config: - index: test-index - refresh: false - executionTimeField: null - connector_type_id: .index - is_preconfigured: false - is_deprecated: false - referenced_by_count: 2 - is_missing_secrets: false - is_system_action: false - get_connector_types_response: - summary: A list of connector types - value: - - id: .swimlane - name: Swimlane - enabled: true - enabled_in_config: true - enabled_in_license: true - minimum_license_required: gold - supported_feature_ids: - - alerting - - cases - - siem - - id: .index - name: Index - enabled: true - enabled_in_config: true - enabled_in_license: true - minimum_license_required: basic - supported_feature_ids: - - alerting - - uptime - - siem - - id: .server-log - name: Server log - enabled: true - enabled_in_config: true - enabled_in_license: true - minimum_license_required: basic - supported_feature_ids: - - alerting - - uptime run_index_connector_request: summary: Run an index connector. value: @@ -4005,6 +4251,81 @@ components: - commentId: 1 pushedDate: '2022-09-08T16:52:27.865Z' status: ok + get_connectors_response: + summary: A list of connectors + value: + - id: preconfigured-email-connector + name: my-preconfigured-email-notification + connector_type_id: .email + is_preconfigured: true + is_deprecated: false + referenced_by_count: 0 + is_system_action: false + - id: e07d0c80-8b8b-11ed-a780-3b746c987a81 + name: my-index-connector + config: + index: test-index + refresh: false + executionTimeField: null + connector_type_id: .index + is_preconfigured: false + is_deprecated: false + referenced_by_count: 2 + is_missing_secrets: false + is_system_action: false + get_connector_types_generativeai_response: + summary: A list of connector types for the `generativeAI` feature. + value: + - id: .gen-ai + name: OpenAI + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: enterprise + supported_feature_ids: + - generativeAI + is_system_action_type: false + - id: .bedrock + name: AWS Bedrock + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: enterprise + supported_feature_ids: + - generativeAI + is_system_action_type: false + get_connector_types_response: + summary: A list of connector types + value: + - id: .swimlane + name: Swimlane + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: gold + supported_feature_ids: + - alerting + - cases + - siem + - id: .index + name: Index + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: basic + supported_feature_ids: + - alerting + - uptime + - siem + - id: .server-log + name: Server log + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: basic + supported_feature_ids: + - alerting + - uptime responses: '401': description: Authorization information is missing or invalid. diff --git a/x-pack/plugins/actions/docs/openapi/bundled_serverless.json b/x-pack/plugins/actions/docs/openapi/bundled_serverless.json new file mode 100644 index 00000000000000..25d7b7484ae8d5 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/bundled_serverless.json @@ -0,0 +1,4155 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Connectors", + "description": "OpenAPI schema for connectors in Serverless projects", + "version": "0.1", + "contact": { + "name": "Connectors Team" + }, + "license": { + "name": "Elastic License 2.0", + "url": "https://www.elastic.co/licensing/elastic-license" + } + }, + "servers": [ + { + "url": "http://localhost:5601", + "description": "local" + } + ], + "security": [ + { + "apiKeyAuth": [] + } + ], + "tags": [ + { + "name": "connectors", + "description": "Connector APIs enable you to create and manage connectors." + } + ], + "paths": { + "/api/actions/connector": { + "post": { + "summary": "Creates a connector.", + "operationId": "createConnector", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_connector_request" + }, + "examples": { + "createEmailConnectorRequest": { + "$ref": "#/components/examples/create_email_connector_request" + }, + "createIndexConnectorRequest": { + "$ref": "#/components/examples/create_index_connector_request" + }, + "createWebhookConnectorRequest": { + "$ref": "#/components/examples/create_webhook_connector_request" + }, + "createXmattersConnectorRequest": { + "$ref": "#/components/examples/create_xmatters_connector_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connector_response_properties" + }, + "examples": { + "createEmailConnectorResponse": { + "$ref": "#/components/examples/create_email_connector_response" + }, + "createIndexConnectorResponse": { + "$ref": "#/components/examples/create_index_connector_response" + }, + "createWebhookConnectorResponse": { + "$ref": "#/components/examples/create_webhook_connector_response" + }, + "createXmattersConnectorResponse": { + "$ref": "#/components/examples/create_xmatters_connector_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/actions/connector/{connectorId}": { + "get": { + "summary": "Retrieves a connector by ID.", + "operationId": "getConnector", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/connector_id" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connector_response_properties" + }, + "examples": { + "getConnectorResponse": { + "$ref": "#/components/examples/get_connector_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + }, + "404": { + "$ref": "#/components/responses/404" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "delete": { + "summary": "Deletes a connector.", + "operationId": "deleteConnector", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/connector_id" + } + ], + "responses": { + "204": { + "description": "Indicates a successful call." + }, + "401": { + "$ref": "#/components/responses/401" + }, + "404": { + "$ref": "#/components/responses/404" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "post": { + "summary": "Creates a connector.", + "operationId": "createConnectorId", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "in": "path", + "name": "connectorId", + "description": "A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated.\n", + "required": true, + "schema": { + "type": "string", + "example": "ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/create_connector_request" + }, + "examples": { + "createIndexConnectorRequest": { + "$ref": "#/components/examples/create_index_connector_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connector_response_properties" + }, + "examples": { + "createIndexConnectorResponse": { + "$ref": "#/components/examples/create_index_connector_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "put": { + "summary": "Updates the attributes for a connector.", + "operationId": "updateConnector", + "tags": [ + "connectors" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/connector_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/update_connector_request" + }, + "examples": { + "updateIndexConnectorRequest": { + "$ref": "#/components/examples/update_index_connector_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/connector_response_properties" + } + } + } + }, + "400": { + "$ref": "#/components/responses/401" + }, + "401": { + "$ref": "#/components/responses/401" + }, + "404": { + "$ref": "#/components/responses/404" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/actions/connectors": { + "get": { + "summary": "Retrieves all connectors.", + "operationId": "getConnectors", + "tags": [ + "connectors" + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/connector_response_properties" + } + }, + "examples": { + "getConnectorsResponse": { + "$ref": "#/components/examples/get_connectors_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/actions/connector_types": { + "get": { + "summary": "Retrieves a list of all connector types.", + "operationId": "getConnectorTypes", + "tags": [ + "connectors" + ], + "parameters": [ + { + "in": "query", + "name": "feature_id", + "description": "A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases).", + "schema": { + "$ref": "#/components/schemas/features" + } + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json": { + "schema": { + "title": "Get connector types response body properties", + "description": "The properties vary for each connector type.", + "type": "array", + "items": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Indicates whether the connector type is enabled in Kibana.", + "example": true + }, + "enabled_in_config": { + "type": "boolean", + "description": "Indicates whether the connector type is enabled in the Kibana configuration file.", + "example": true + }, + "enabled_in_license": { + "type": "boolean", + "description": "Indicates whether the connector is enabled in the license.", + "example": true + }, + "id": { + "$ref": "#/components/schemas/connector_types" + }, + "is_system_action_type": { + "type": "boolean", + "example": false + }, + "minimum_license_required": { + "type": "string", + "description": "The license that is required to use the connector type.", + "example": "basic" + }, + "name": { + "type": "string", + "description": "The name of the connector type.", + "example": "Index" + }, + "supported_feature_ids": { + "type": "array", + "description": "The features that are supported by the connector type.", + "items": { + "$ref": "#/components/schemas/features" + }, + "example": [ + "alerting", + "cases", + "siem" + ] + } + } + } + }, + "examples": { + "getConnectorTypesServerlessResponse": { + "$ref": "#/components/examples/get_connector_types_generativeai_response" + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/401" + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + } + }, + "components": { + "securitySchemes": { + "apiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "ApiKey" + } + }, + "parameters": { + "kbn_xsrf": { + "schema": { + "type": "string" + }, + "in": "header", + "name": "kbn-xsrf", + "description": "Cross-site request forgery protection", + "required": true + }, + "connector_id": { + "in": "path", + "name": "connectorId", + "description": "An identifier for the connector.", + "required": true, + "schema": { + "type": "string", + "example": "df770e30-8b8b-11ed-a780-3b746c987a81" + } + } + }, + "schemas": { + "config_properties_bedrock": { + "title": "Connector request properties for an Amazon Bedrock connector", + "description": "Defines properties for connectors when type is `.bedrock`.", + "type": "object", + "required": [ + "apiUrl" + ], + "properties": { + "apiUrl": { + "type": "string", + "description": "The Amazon Bedrock request URL." + }, + "defaultModel": { + "type": "string", + "description": "The generative artificial intelligence model for Amazon Bedrock to use. Current support is for the Anthropic Claude models.\n", + "default": "anthropic.claude-v2" + } + } + }, + "secrets_properties_bedrock": { + "title": "Connector secrets properties for an Amazon Bedrock connector", + "description": "Defines secrets for connectors when type is `.bedrock`.", + "type": "object", + "required": [ + "accessKey", + "secret" + ], + "properties": { + "accessKey": { + "type": "string", + "description": "The AWS access key for authentication." + }, + "secret": { + "type": "string", + "description": "The AWS secret for authentication." + } + } + }, + "create_connector_request_bedrock": { + "title": "Create Amazon Bedrock connector request", + "description": "The Amazon Bedrock connector uses axios to send a POST request to Amazon Bedrock.", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_bedrock" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".bedrock" + ], + "example": ".bedrock" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_bedrock" + } + } + }, + "config_properties_cases_webhook": { + "title": "Connector request properties for Webhook - Case Management connector", + "required": [ + "createIncidentJson", + "createIncidentResponseKey", + "createIncidentUrl", + "getIncidentResponseExternalTitleKey", + "getIncidentUrl", + "updateIncidentJson", + "updateIncidentUrl", + "viewIncidentUrl" + ], + "description": "Defines properties for connectors when type is `.cases-webhook`.", + "type": "object", + "properties": { + "createCommentJson": { + "type": "string", + "description": "A JSON payload sent to the create comment URL to create a case comment. You can use variables to add Kibana Cases data to the payload. The required variable is `case.comment`. Due to Mustache template variables (the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated once the Mustache variables have been placed when the REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass.\n", + "example": { + "body": { + "[object Object]": null + } + } + }, + "createCommentMethod": { + "type": "string", + "description": "The REST API HTTP request method to create a case comment in the third-party system. Valid values are `patch`, `post`, and `put`.\n", + "default": "put", + "enum": [ + "patch", + "post", + "put" + ] + }, + "createCommentUrl": { + "type": "string", + "description": "The REST API URL to create a case comment by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts setting`, add the hostname to the allowed hosts.\n", + "example": "https://testing-jira.atlassian.net/rest/api/2/issue/{{{external.system.id}}}/comment" + }, + "createIncidentJson": { + "type": "string", + "description": "A JSON payload sent to the create case URL to create a case. You can use variables to add case data to the payload. Required variables are `case.title` and `case.description`. Due to Mustache template variables (which is the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review.\n", + "example": { + "fields": { + "summary": { + "[object Object]": null + }, + "description": { + "[object Object]": null + }, + "labels": { + "[object Object]": null + } + } + } + }, + "createIncidentMethod": { + "type": "string", + "description": "The REST API HTTP request method to create a case in the third-party system. Valid values are `patch`, `post`, and `put`.\n", + "enum": [ + "patch", + "post", + "put" + ], + "default": "post" + }, + "createIncidentResponseKey": { + "type": "string", + "description": "The JSON key in the create case response that contains the external case ID." + }, + "createIncidentUrl": { + "type": "string", + "description": "The REST API URL to create a case in the third-party system. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts.\n" + }, + "getIncidentResponseExternalTitleKey": { + "type": "string", + "description": "The JSON key in get case response that contains the external case title." + }, + "getIncidentUrl": { + "type": "string", + "description": "The REST API URL to get the case by ID from the third-party system. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. You can use a variable to add the external system ID to the URL. Due to Mustache template variables (the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass.\n", + "example": "https://testing-jira.atlassian.net/rest/api/2/issue/{{{external.system.id}}}" + }, + "hasAuth": { + "type": "boolean", + "description": "If true, a username and password for login type authentication must be provided.", + "default": true + }, + "headers": { + "type": "string", + "description": "A set of key-value pairs sent as headers with the request URLs for the create case, update case, get case, and create comment methods.\n" + }, + "updateIncidentJson": { + "type": "string", + "description": "The JSON payload sent to the update case URL to update the case. You can use variables to add Kibana Cases data to the payload. Required variables are `case.title` and `case.description`. Due to Mustache template variables (which is the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review.\n", + "example": { + "fields": { + "summary": { + "[object Object]": null + }, + "description": { + "[object Object]": null + }, + "labels": { + "[object Object]": null + } + } + } + }, + "updateIncidentMethod": { + "type": "string", + "description": "The REST API HTTP request method to update the case in the third-party system. Valid values are `patch`, `post`, and `put`.\n", + "default": "put", + "enum": [ + "patch", + "post", + "put" + ] + }, + "updateIncidentUrl": { + "type": "string", + "description": "The REST API URL to update the case by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts.\n", + "example": "https://testing-jira.atlassian.net/rest/api/2/issue/{{{external.system.ID}}}" + }, + "viewIncidentUrl": { + "type": "string", + "description": "The URL to view the case in the external system. You can use variables to add the external system ID or external system title to the URL.\n", + "example": "https://testing-jira.atlassian.net/browse/{{{external.system.title}}}" + } + } + }, + "secrets_properties_cases_webhook": { + "title": "Connector secrets properties for Webhook - Case Management connector", + "type": "object", + "properties": { + "password": { + "type": "string", + "description": "The password for HTTP basic authentication. If `hasAuth` is set to `true`, this property is required." + }, + "user": { + "type": "string", + "description": "The username for HTTP basic authentication. If `hasAuth` is set to `true`, this property is required." + } + } + }, + "create_connector_request_cases_webhook": { + "title": "Create Webhook - Case Managment connector request", + "description": "The Webhook - Case Management connector uses axios to send POST, PUT, and GET requests to a case management RESTful API web service.\n", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_cases_webhook" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".cases-webhook" + ], + "example": ".cases-webhook" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_cases_webhook" + } + } + }, + "config_properties_d3security": { + "title": "Connector request properties for a D3 Security connector", + "description": "Defines properties for connectors when type is `.d3security`.", + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "type": "string", + "description": "The D3 Security API request URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts.\n" + } + } + }, + "secrets_properties_d3security": { + "title": "Connector secrets properties for a D3 Security connector", + "description": "Defines secrets for connectors when type is `.d3security`.", + "required": [ + "token" + ], + "type": "object", + "properties": { + "token": { + "type": "string", + "description": "The D3 Security token." + } + } + }, + "create_connector_request_d3security": { + "title": "Create D3 Security connector request", + "description": "The connector uses axios to send a POST request to a D3 Security endpoint.\n", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_d3security" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".d3security" + ], + "example": ".d3security" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_d3security" + } + } + }, + "config_properties_email": { + "title": "Connector request properties for an email connector", + "description": "Defines properties for connectors when type is `.email`.", + "required": [ + "from" + ], + "type": "object", + "properties": { + "clientId": { + "description": "The client identifier, which is a part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required.\n", + "type": "string", + "nullable": true + }, + "from": { + "description": "The from address for all emails sent by the connector. It must be specified in `user@host-name` format.\n", + "type": "string" + }, + "hasAuth": { + "description": "Specifies whether a user and password are required inside the secrets configuration.\n", + "default": true, + "type": "boolean" + }, + "host": { + "description": "The host name of the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. \n", + "type": "string" + }, + "oauthTokenUrl": { + "type": "string", + "nullable": true + }, + "port": { + "description": "The port to connect to on the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. \n", + "type": "integer" + }, + "secure": { + "description": "Specifies whether the connection to the service provider will use TLS. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored.\n", + "type": "boolean" + }, + "service": { + "description": "The name of the email service.\n", + "type": "string", + "enum": [ + "elastic_cloud", + "exchange_server", + "gmail", + "other", + "outlook365", + "ses" + ] + }, + "tenantId": { + "description": "The tenant identifier, which is part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required.\n", + "type": "string", + "nullable": true + } + } + }, + "secrets_properties_email": { + "title": "Connector secrets properties for an email connector", + "description": "Defines secrets for connectors when type is `.email`.", + "type": "object", + "properties": { + "clientSecret": { + "type": "string", + "description": "The Microsoft Exchange Client secret for OAuth 2.0 client credentials authentication. It must be URL-encoded. If `service` is `exchange_server`, this property is required.\n" + }, + "password": { + "type": "string", + "description": "The password for HTTP basic authentication. If `hasAuth` is set to `true`, this property is required.\n" + }, + "user": { + "type": "string", + "description": "The username for HTTP basic authentication. If `hasAuth` is set to `true`, this property is required.\n" + } + } + }, + "create_connector_request_email": { + "title": "Create email connector request", + "description": "The email connector uses the SMTP protocol to send mail messages, using an integration of Nodemailer. An exception is Microsoft Exchange, which uses HTTP protocol for sending emails, Send mail. Email message text is sent as both plain text and html text.\n", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_email" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".email" + ], + "example": ".email" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_email" + } + } + }, + "config_properties_genai": { + "title": "Connector request properties for an OpenAI connector", + "description": "Defines properties for connectors when type is `.gen-ai`.", + "oneOf": [ + { + "type": "object", + "required": [ + "apiProvider", + "apiUrl" + ], + "properties": { + "apiProvider": { + "type": "string", + "description": "The OpenAI API provider.", + "enum": [ + "Azure OpenAI" + ] + }, + "apiUrl": { + "type": "string", + "description": "The OpenAI API endpoint." + } + } + }, + { + "type": "object", + "required": [ + "apiProvider", + "apiUrl" + ], + "properties": { + "apiProvider": { + "type": "string", + "description": "The OpenAI API provider.", + "enum": [ + "OpenAI" + ] + }, + "apiUrl": { + "type": "string", + "description": "The OpenAI API endpoint." + }, + "defaultModel": { + "type": "string", + "description": "The default model to use for requests." + } + } + } + ], + "discriminator": { + "propertyName": "apiProvider" + } + }, + "secrets_properties_genai": { + "title": "Connector secrets properties for an OpenAI connector", + "description": "Defines secrets for connectors when type is `.gen-ai`.", + "type": "object", + "properties": { + "apiKey": { + "type": "string", + "description": "The OpenAI API key." + } + } + }, + "create_connector_request_genai": { + "title": "Create OpenAI connector request", + "description": "The OpenAI connector uses axios to send a POST request to either OpenAI or Azure OpenAPI.\n", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_genai" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".gen-ai" + ], + "example": ".gen-ai" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_genai" + } + } + }, + "config_properties_index": { + "title": "Connector request properties for an index connector", + "required": [ + "index" + ], + "description": "Defines properties for connectors when type is `.index`.", + "type": "object", + "properties": { + "executionTimeField": { + "description": "A field that indicates when the document was indexed.", + "default": null, + "type": "string", + "nullable": true + }, + "index": { + "description": "The Elasticsearch index to be written to.", + "type": "string" + }, + "refresh": { + "description": "The refresh policy for the write request, which affects when changes are made visible to search. Refer to the refresh setting for Elasticsearch document APIs.\n", + "default": false, + "type": "boolean" + } + } + }, + "create_connector_request_index": { + "title": "Create index connector request", + "description": "The index connector indexes a document into Elasticsearch.", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_index" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".index" + ], + "example": ".index" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + } + } + }, + "config_properties_jira": { + "title": "Connector request properties for a Jira connector", + "required": [ + "apiUrl", + "projectKey" + ], + "description": "Defines properties for connectors when type is `.jira`.", + "type": "object", + "properties": { + "apiUrl": { + "description": "The Jira instance URL.", + "type": "string" + }, + "projectKey": { + "description": "The Jira project key.", + "type": "string" + } + } + }, + "secrets_properties_jira": { + "title": "Connector secrets properties for a Jira connector", + "required": [ + "apiToken", + "email" + ], + "description": "Defines secrets for connectors when type is `.jira`.", + "type": "object", + "properties": { + "apiToken": { + "description": "The Jira API authentication token for HTTP basic authentication.", + "type": "string" + }, + "email": { + "description": "The account email for HTTP Basic authentication.", + "type": "string" + } + } + }, + "create_connector_request_jira": { + "title": "Create Jira connector request", + "description": "The Jira connector uses the REST API v2 to create Jira issues.", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_jira" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".jira" + ], + "example": ".jira" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_jira" + } + } + }, + "config_properties_opsgenie": { + "title": "Connector request properties for an Opsgenie connector", + "required": [ + "apiUrl" + ], + "description": "Defines properties for connectors when type is `.opsgenie`.", + "type": "object", + "properties": { + "apiUrl": { + "description": "The Opsgenie URL. For example, `https://api.opsgenie.com` or `https://api.eu.opsgenie.com`. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts.\n", + "type": "string" + } + } + }, + "secrets_properties_opsgenie": { + "title": "Connector secrets properties for an Opsgenie connector", + "required": [ + "apiKey" + ], + "description": "Defines secrets for connectors when type is `.opsgenie`.", + "type": "object", + "properties": { + "apiKey": { + "description": "The Opsgenie API authentication key for HTTP Basic authentication.", + "type": "string" + } + } + }, + "create_connector_request_opsgenie": { + "title": "Create Opsgenie connector request", + "description": "The Opsgenie connector uses the Opsgenie alert API.", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_opsgenie" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".opsgenie" + ], + "example": ".opsgenie" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_opsgenie" + } + } + }, + "config_properties_pagerduty": { + "title": "Connector request properties for a PagerDuty connector", + "description": "Defines properties for connectors when type is `.pagerduty`.", + "type": "object", + "properties": { + "apiUrl": { + "description": "The PagerDuty event URL.", + "type": "string", + "nullable": true, + "example": "https://events.pagerduty.com/v2/enqueue" + } + } + }, + "secrets_properties_pagerduty": { + "title": "Connector secrets properties for a PagerDuty connector", + "description": "Defines secrets for connectors when type is `.pagerduty`.", + "type": "object", + "required": [ + "routingKey" + ], + "properties": { + "routingKey": { + "description": "A 32 character PagerDuty Integration Key for an integration on a service.\n", + "type": "string" + } + } + }, + "create_connector_request_pagerduty": { + "title": "Create PagerDuty connector request", + "description": "The PagerDuty connector uses the v2 Events API to trigger, acknowledge, and resolve PagerDuty alerts.\n", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_pagerduty" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".pagerduty" + ], + "example": ".pagerduty" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_pagerduty" + } + } + }, + "config_properties_resilient": { + "title": "Connector request properties for a IBM Resilient connector", + "required": [ + "apiUrl", + "orgId" + ], + "description": "Defines properties for connectors when type is `.resilient`.", + "type": "object", + "properties": { + "apiUrl": { + "description": "The IBM Resilient instance URL.", + "type": "string" + }, + "orgId": { + "description": "The IBM Resilient organization ID.", + "type": "string" + } + } + }, + "secrets_properties_resilient": { + "title": "Connector secrets properties for IBM Resilient connector", + "required": [ + "apiKeyId", + "apiKeySecret" + ], + "description": "Defines secrets for connectors when type is `.resilient`.", + "type": "object", + "properties": { + "apiKeyId": { + "type": "string", + "description": "The authentication key ID for HTTP Basic authentication." + }, + "apiKeySecret": { + "type": "string", + "description": "The authentication key secret for HTTP Basic authentication." + } + } + }, + "create_connector_request_resilient": { + "title": "Create IBM Resilient connector request", + "description": "The IBM Resilient connector uses the RESILIENT REST v2 to create IBM Resilient incidents.", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_resilient" + }, + "connector_type_id": { + "description": "The type of connector.", + "type": "string", + "example": ".resilient", + "enum": [ + ".resilient" + ] + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_resilient" + } + } + }, + "create_connector_request_serverlog": { + "title": "Create server log connector request", + "description": "This connector writes an entry to the Kibana server log.", + "type": "object", + "required": [ + "connector_type_id", + "name" + ], + "properties": { + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".server-log" + ], + "example": ".server-log" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + } + } + }, + "config_properties_servicenow": { + "title": "Connector request properties for a ServiceNow ITSM connector", + "required": [ + "apiUrl" + ], + "description": "Defines properties for connectors when type is `.servicenow`.", + "type": "object", + "properties": { + "apiUrl": { + "type": "string", + "description": "The ServiceNow instance URL." + }, + "clientId": { + "description": "The client ID assigned to your OAuth application. This property is required when `isOAuth` is `true`.\n", + "type": "string" + }, + "isOAuth": { + "description": "The type of authentication to use. The default value is false, which means basic authentication is used instead of open authorization (OAuth).\n", + "default": false, + "type": "boolean" + }, + "jwtKeyId": { + "description": "The key identifier assigned to the JWT verifier map of your OAuth application. This property is required when `isOAuth` is `true`.\n", + "type": "string" + }, + "userIdentifierValue": { + "description": "The identifier to use for OAuth authentication. This identifier should be the user field you selected when you created an OAuth JWT API endpoint for external clients in your ServiceNow instance. For example, if the selected user field is `Email`, the user identifier should be the user's email address. This property is required when `isOAuth` is `true`.\n", + "type": "string" + }, + "usesTableApi": { + "description": "Determines whether the connector uses the Table API or the Import Set API. This property is supported only for ServiceNow ITSM and ServiceNow SecOps connectors. NOTE: If this property is set to `false`, the Elastic application should be installed in ServiceNow.\n", + "default": true, + "type": "boolean" + } + } + }, + "secrets_properties_servicenow": { + "title": "Connector secrets properties for ServiceNow ITOM, ServiceNow ITSM, and ServiceNow SecOps connectors", + "description": "Defines secrets for connectors when type is `.servicenow`, `.servicenow-sir`, or `.servicenow-itom`.", + "type": "object", + "properties": { + "clientSecret": { + "type": "string", + "description": "The client secret assigned to your OAuth application. This property is required when `isOAuth` is `true`." + }, + "password": { + "type": "string", + "description": "The password for HTTP basic authentication. This property is required when `isOAuth` is `false`." + }, + "privateKey": { + "type": "string", + "description": "The RSA private key that you created for use in ServiceNow. This property is required when `isOAuth` is `true`." + }, + "privateKeyPassword": { + "type": "string", + "description": "The password for the RSA private key. This property is required when `isOAuth` is `true` and you set a password on your private key." + }, + "username": { + "type": "string", + "description": "The username for HTTP basic authentication. This property is required when `isOAuth` is `false`." + } + } + }, + "create_connector_request_servicenow": { + "title": "Create ServiceNow ITSM connector request", + "description": "The ServiceNow ITSM connector uses the import set API to create ServiceNow incidents. You can use the connector for rule actions and cases.\n", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_servicenow" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".servicenow" + ], + "example": ".servicenow" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_servicenow" + } + } + }, + "config_properties_servicenow_itom": { + "title": "Connector request properties for a ServiceNow ITSM connector", + "required": [ + "apiUrl" + ], + "description": "Defines properties for connectors when type is `.servicenow`.", + "type": "object", + "properties": { + "apiUrl": { + "type": "string", + "description": "The ServiceNow instance URL." + }, + "clientId": { + "description": "The client ID assigned to your OAuth application. This property is required when `isOAuth` is `true`.\n", + "type": "string" + }, + "isOAuth": { + "description": "The type of authentication to use. The default value is false, which means basic authentication is used instead of open authorization (OAuth).\n", + "default": false, + "type": "boolean" + }, + "jwtKeyId": { + "description": "The key identifier assigned to the JWT verifier map of your OAuth application. This property is required when `isOAuth` is `true`.\n", + "type": "string" + }, + "userIdentifierValue": { + "description": "The identifier to use for OAuth authentication. This identifier should be the user field you selected when you created an OAuth JWT API endpoint for external clients in your ServiceNow instance. For example, if the selected user field is `Email`, the user identifier should be the user's email address. This property is required when `isOAuth` is `true`.\n", + "type": "string" + } + } + }, + "create_connector_request_servicenow_itom": { + "title": "Create ServiceNow ITOM connector request", + "description": "The ServiceNow ITOM connector uses the event API to create ServiceNow events. You can use the connector for rule actions.\n", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_servicenow_itom" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".servicenow-itom" + ], + "example": ".servicenow-itom" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_servicenow" + } + } + }, + "create_connector_request_servicenow_sir": { + "title": "Create ServiceNow SecOps connector request", + "description": "The ServiceNow SecOps connector uses the import set API to create ServiceNow security incidents. You can use the connector for rule actions and cases.\n", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_servicenow" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".servicenow-sir" + ], + "example": ".servicenow-sir" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_servicenow" + } + } + }, + "secrets_properties_slack_api": { + "title": "Connector secrets properties for a Web API Slack connector", + "description": "Defines secrets for connectors when type is `.slack`.", + "required": [ + "token" + ], + "type": "object", + "properties": { + "token": { + "type": "string", + "description": "Slack bot user OAuth token." + } + } + }, + "create_connector_request_slack_api": { + "title": "Create Slack connector request", + "description": "The Slack connector uses Slack Incoming Webhooks.", + "type": "object", + "required": [ + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".slack_api" + ], + "example": ".slack_api" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_slack_api" + } + } + }, + "secrets_properties_slack_webhook": { + "title": "Connector secrets properties for a Webhook Slack connector", + "description": "Defines secrets for connectors when type is `.slack`.", + "required": [ + "webhookUrl" + ], + "type": "object", + "properties": { + "webhookUrl": { + "type": "string", + "description": "Slack webhook url." + } + } + }, + "create_connector_request_slack_webhook": { + "title": "Create Slack connector request", + "description": "The Slack connector uses Slack Incoming Webhooks.", + "type": "object", + "required": [ + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".slack" + ], + "example": ".slack" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_slack_webhook" + } + } + }, + "config_properties_swimlane": { + "title": "Connector request properties for a Swimlane connector", + "required": [ + "apiUrl", + "appId", + "connectorType" + ], + "description": "Defines properties for connectors when type is `.swimlane`.", + "type": "object", + "properties": { + "apiUrl": { + "description": "The Swimlane instance URL.", + "type": "string" + }, + "appId": { + "description": "The Swimlane application ID.", + "type": "string" + }, + "connectorType": { + "description": "The type of connector. Valid values are `all`, `alerts`, and `cases`.", + "type": "string", + "enum": [ + "all", + "alerts", + "cases" + ] + }, + "mappings": { + "title": "Connector mappings properties for a Swimlane connector", + "description": "The field mapping.", + "type": "object", + "properties": { + "alertIdConfig": { + "title": "Alert identifier mapping", + "description": "Mapping for the alert ID.", + "type": "object", + "required": [ + "fieldType", + "id", + "key", + "name" + ], + "properties": { + "fieldType": { + "type": "string", + "description": "The type of field in Swimlane." + }, + "id": { + "type": "string", + "description": "The identifier for the field in Swimlane." + }, + "key": { + "type": "string", + "description": "The key for the field in Swimlane." + }, + "name": { + "type": "string", + "description": "The name of the field in Swimlane." + } + } + }, + "caseIdConfig": { + "title": "Case identifier mapping", + "description": "Mapping for the case ID.", + "type": "object", + "required": [ + "fieldType", + "id", + "key", + "name" + ], + "properties": { + "fieldType": { + "type": "string", + "description": "The type of field in Swimlane." + }, + "id": { + "type": "string", + "description": "The identifier for the field in Swimlane." + }, + "key": { + "type": "string", + "description": "The key for the field in Swimlane." + }, + "name": { + "type": "string", + "description": "The name of the field in Swimlane." + } + } + }, + "caseNameConfig": { + "title": "Case name mapping", + "description": "Mapping for the case name.", + "type": "object", + "required": [ + "fieldType", + "id", + "key", + "name" + ], + "properties": { + "fieldType": { + "type": "string", + "description": "The type of field in Swimlane." + }, + "id": { + "type": "string", + "description": "The identifier for the field in Swimlane." + }, + "key": { + "type": "string", + "description": "The key for the field in Swimlane." + }, + "name": { + "type": "string", + "description": "The name of the field in Swimlane." + } + } + }, + "commentsConfig": { + "title": "Case comment mapping", + "description": "Mapping for the case comments.", + "type": "object", + "required": [ + "fieldType", + "id", + "key", + "name" + ], + "properties": { + "fieldType": { + "type": "string", + "description": "The type of field in Swimlane." + }, + "id": { + "type": "string", + "description": "The identifier for the field in Swimlane." + }, + "key": { + "type": "string", + "description": "The key for the field in Swimlane." + }, + "name": { + "type": "string", + "description": "The name of the field in Swimlane." + } + } + }, + "descriptionConfig": { + "title": "Case description mapping", + "description": "Mapping for the case description.", + "type": "object", + "required": [ + "fieldType", + "id", + "key", + "name" + ], + "properties": { + "fieldType": { + "type": "string", + "description": "The type of field in Swimlane." + }, + "id": { + "type": "string", + "description": "The identifier for the field in Swimlane." + }, + "key": { + "type": "string", + "description": "The key for the field in Swimlane." + }, + "name": { + "type": "string", + "description": "The name of the field in Swimlane." + } + } + }, + "ruleNameConfig": { + "title": "Rule name mapping", + "description": "Mapping for the name of the alert's rule.", + "type": "object", + "required": [ + "fieldType", + "id", + "key", + "name" + ], + "properties": { + "fieldType": { + "type": "string", + "description": "The type of field in Swimlane." + }, + "id": { + "type": "string", + "description": "The identifier for the field in Swimlane." + }, + "key": { + "type": "string", + "description": "The key for the field in Swimlane." + }, + "name": { + "type": "string", + "description": "The name of the field in Swimlane." + } + } + }, + "severityConfig": { + "title": "Severity mapping", + "description": "Mapping for the severity.", + "type": "object", + "required": [ + "fieldType", + "id", + "key", + "name" + ], + "properties": { + "fieldType": { + "type": "string", + "description": "The type of field in Swimlane." + }, + "id": { + "type": "string", + "description": "The identifier for the field in Swimlane." + }, + "key": { + "type": "string", + "description": "The key for the field in Swimlane." + }, + "name": { + "type": "string", + "description": "The name of the field in Swimlane." + } + } + } + } + } + } + }, + "secrets_properties_swimlane": { + "title": "Connector secrets properties for a Swimlane connector", + "description": "Defines secrets for connectors when type is `.swimlane`.", + "type": "object", + "properties": { + "apiToken": { + "description": "Swimlane API authentication token.", + "type": "string" + } + } + }, + "create_connector_request_swimlane": { + "title": "Create Swimlane connector request", + "description": "The Swimlane connector uses the Swimlane REST API to create Swimlane records.", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_swimlane" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".swimlane" + ], + "example": ".swimlane" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_swimlane" + } + } + }, + "secrets_properties_teams": { + "title": "Connector secrets properties for a Microsoft Teams connector", + "description": "Defines secrets for connectors when type is `.teams`.", + "type": "object", + "required": [ + "webhookUrl" + ], + "properties": { + "webhookUrl": { + "type": "string", + "description": "The URL of the incoming webhook. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts.\n" + } + } + }, + "create_connector_request_teams": { + "title": "Create Microsoft Teams connector request", + "description": "The Microsoft Teams connector uses Incoming Webhooks.", + "type": "object", + "required": [ + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".teams" + ], + "example": ".teams" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_teams" + } + } + }, + "config_properties_tines": { + "title": "Connector request properties for a Tines connector", + "description": "Defines properties for connectors when type is `.tines`.", + "type": "object", + "required": [ + "url" + ], + "properties": { + "url": { + "description": "The Tines tenant URL. If you are using the `xpack.actions.allowedHosts` setting, make sure this hostname is added to the allowed hosts.\n", + "type": "string" + } + } + }, + "secrets_properties_tines": { + "title": "Connector secrets properties for a Tines connector", + "description": "Defines secrets for connectors when type is `.tines`.", + "type": "object", + "required": [ + "email", + "token" + ], + "properties": { + "email": { + "description": "The email used to sign in to Tines.", + "type": "string" + }, + "token": { + "description": "The Tines API token.", + "type": "string" + } + } + }, + "create_connector_request_tines": { + "title": "Create Tines connector request", + "description": "The Tines connector uses Tines Webhook actions to send events via POST request.\n", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_tines" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".tines" + ], + "example": ".tines" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_tines" + } + } + }, + "config_properties_torq": { + "title": "Connector request properties for a Torq connector", + "description": "Defines properties for connectors when type is `.torq`.", + "type": "object", + "required": [ + "webhookIntegrationUrl" + ], + "properties": { + "webhookIntegrationUrl": { + "description": "The endpoint URL of the Elastic Security integration in Torq.", + "type": "string" + } + } + }, + "secrets_properties_torq": { + "title": "Connector secrets properties for a Torq connector", + "description": "Defines secrets for connectors when type is `.torq`.", + "type": "object", + "required": [ + "token" + ], + "properties": { + "token": { + "description": "The secret of the webhook authentication header.", + "type": "string" + } + } + }, + "create_connector_request_torq": { + "title": "Create Torq connector request", + "description": "The Torq connector uses a Torq webhook to trigger workflows with Kibana actions.\n", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_torq" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".torq" + ], + "example": ".torq" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_torq" + } + } + }, + "config_properties_webhook": { + "title": "Connector request properties for a Webhook connector", + "description": "Defines properties for connectors when type is `.webhook`.", + "type": "object", + "properties": { + "authType": { + "type": "string", + "enum": [ + "webhook-authentication-basic", + "webhook-authentication-ssl", + "null" + ], + "description": "The type of authentication to use: basic, SSL, or none.\n" + }, + "ca": { + "type": "string", + "description": "A base64 encoded version of the certificate authority file that the connector can trust to sign and validate certificates. This option is available for all authentication types.\n" + }, + "certType": { + "type": "string", + "description": "If the `authType` is `webhook-authentication-ssl`, specifies whether the certificate authentication data is in a CRT and key file format or a PFX file format.\n", + "enum": [ + "ssl-crt-key", + "ssl-pfx" + ] + }, + "hasAuth": { + "type": "boolean", + "description": "If `true`, a user name and password must be provided for login type authentication.\n" + }, + "headers": { + "type": "object", + "nullable": true, + "description": "A set of key-value pairs sent as headers with the request." + }, + "method": { + "type": "string", + "default": "post", + "enum": [ + "post", + "put" + ], + "description": "The HTTP request method, either `post` or `put`.\n" + }, + "url": { + "type": "string", + "description": "The request URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts.\n" + }, + "verificationMode": { + "type": "string", + "enum": [ + "certificate", + "full", + "none" + ], + "default": "full", + "description": "Controls the verification of certificates. Use `full` to validate that the certificate has an issue date within the `not_before` and `not_after` dates, chains to a trusted certificate authority (CA), and has a hostname or IP address that matches the names within the certificate. Use `certificate` to validate the certificate and verify that it is signed by a trusted authority; this option does not check the certificate hostname. Use `none` to skip certificate validation.\n" + } + } + }, + "secrets_properties_webhook": { + "title": "Connector secrets properties for a Webhook connector", + "description": "Defines secrets for connectors when type is `.webhook`.", + "type": "object", + "properties": { + "crt": { + "type": "string", + "description": "If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-crt-key`, it is a base64 encoded version of the CRT or CERT file." + }, + "key": { + "type": "string", + "description": "If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-crt-key`, it is a base64 encoded version of the KEY file." + }, + "pfx": { + "type": "string", + "description": "If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-pfx`, it is a base64 encoded version of the PFX or P12 file." + }, + "password": { + "type": "string", + "description": "The password for HTTP basic authentication or the passphrase for the SSL certificate files. If `hasAuth` is set to `true` and `authType` is `webhook-authentication-basic`, this property is required.\n" + }, + "user": { + "type": "string", + "description": "The username for HTTP basic authentication. If `hasAuth` is set to `true` and `authType` is `webhook-authentication-basic`, this property is required.\n" + } + } + }, + "create_connector_request_webhook": { + "title": "Create Webhook connector request", + "description": "The Webhook connector uses axios to send a POST or PUT request to a web service.\n", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_webhook" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".webhook" + ], + "example": ".webhook" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_webhook" + } + } + }, + "config_properties_xmatters": { + "title": "Connector request properties for an xMatters connector", + "description": "Defines properties for connectors when type is `.xmatters`.", + "type": "object", + "properties": { + "configUrl": { + "description": "The request URL for the Elastic Alerts trigger in xMatters. It is applicable only when `usesBasic` is `true`.\n", + "type": "string", + "nullable": true + }, + "usesBasic": { + "description": "Specifies whether the connector uses HTTP basic authentication (`true`) or URL authentication (`false`).", + "type": "boolean", + "default": true + } + } + }, + "secrets_properties_xmatters": { + "title": "Connector secrets properties for an xMatters connector", + "description": "Defines secrets for connectors when type is `.xmatters`.", + "type": "object", + "properties": { + "password": { + "description": "A user name for HTTP basic authentication. It is applicable only when `usesBasic` is `true`.\n", + "type": "string" + }, + "secretsUrl": { + "description": "The request URL for the Elastic Alerts trigger in xMatters with the API key included in the URL. It is applicable only when `usesBasic` is `false`.\n", + "type": "string" + }, + "user": { + "description": "A password for HTTP basic authentication. It is applicable only when `usesBasic` is `true`.\n", + "type": "string" + } + } + }, + "create_connector_request_xmatters": { + "title": "Create xMatters connector request", + "description": "The xMatters connector uses the xMatters Workflow for Elastic to send actionable alerts to on-call xMatters resources.\n", + "type": "object", + "required": [ + "config", + "connector_type_id", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_xmatters" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".xmatters" + ], + "example": ".xmatters" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_xmatters" + } + } + }, + "create_connector_request": { + "title": "Create connector request body properties", + "description": "The properties vary depending on the connector type.", + "oneOf": [ + { + "$ref": "#/components/schemas/create_connector_request_bedrock" + }, + { + "$ref": "#/components/schemas/create_connector_request_cases_webhook" + }, + { + "$ref": "#/components/schemas/create_connector_request_d3security" + }, + { + "$ref": "#/components/schemas/create_connector_request_email" + }, + { + "$ref": "#/components/schemas/create_connector_request_genai" + }, + { + "$ref": "#/components/schemas/create_connector_request_index" + }, + { + "$ref": "#/components/schemas/create_connector_request_jira" + }, + { + "$ref": "#/components/schemas/create_connector_request_opsgenie" + }, + { + "$ref": "#/components/schemas/create_connector_request_pagerduty" + }, + { + "$ref": "#/components/schemas/create_connector_request_resilient" + }, + { + "$ref": "#/components/schemas/create_connector_request_serverlog" + }, + { + "$ref": "#/components/schemas/create_connector_request_servicenow" + }, + { + "$ref": "#/components/schemas/create_connector_request_servicenow_itom" + }, + { + "$ref": "#/components/schemas/create_connector_request_servicenow_sir" + }, + { + "$ref": "#/components/schemas/create_connector_request_slack_api" + }, + { + "$ref": "#/components/schemas/create_connector_request_slack_webhook" + }, + { + "$ref": "#/components/schemas/create_connector_request_swimlane" + }, + { + "$ref": "#/components/schemas/create_connector_request_teams" + }, + { + "$ref": "#/components/schemas/create_connector_request_tines" + }, + { + "$ref": "#/components/schemas/create_connector_request_torq" + }, + { + "$ref": "#/components/schemas/create_connector_request_webhook" + }, + { + "$ref": "#/components/schemas/create_connector_request_xmatters" + } + ], + "discriminator": { + "propertyName": "connector_type_id" + } + }, + "is_deprecated": { + "type": "boolean", + "description": "Indicates whether the connector type is deprecated.", + "example": false + }, + "is_missing_secrets": { + "type": "boolean", + "description": "Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.", + "example": false + }, + "is_preconfigured": { + "type": "boolean", + "description": "Indicates whether it is a preconfigured connector. If true, the `config` and `is_missing_secrets` properties are omitted from the response. \n", + "example": false + }, + "is_system_action": { + "type": "boolean", + "description": "Indicates whether the connector is used for system actions.", + "example": false + }, + "connector_response_properties_bedrock": { + "title": "Connector response properties for an Amazon Bedrock connector", + "type": "object", + "required": [ + "config", + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_bedrock" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".bedrock" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + } + } + }, + "referenced_by_count": { + "type": "integer", + "description": "Indicates the number of saved objects that reference the connector. If `is_preconfigured` is true, this value is not calculated. This property is returned only by the get all connectors API.\n", + "example": 2 + }, + "connector_response_properties_cases_webhook": { + "title": "Connector request properties for a Webhook - Case Management connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_cases_webhook" + }, + "connector_type_id": { + "description": "The type of connector.", + "type": "string", + "enum": [ + ".cases-webhook" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_d3security": { + "title": "Connector response properties for a D3 Security connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_d3security" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".d3security" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_email": { + "title": "Connector response properties for an email connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_email" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".email" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_index": { + "title": "Connector response properties for an index connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_index" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".index" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_jira": { + "title": "Connector response properties for a Jira connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_jira" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".jira" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_opsgenie": { + "title": "Connector response properties for an Opsgenie connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_opsgenie" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".opsgenie" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_pagerduty": { + "title": "Connector response properties for a PagerDuty connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_pagerduty" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".pagerduty" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_resilient": { + "title": "Connector response properties for a IBM Resilient connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_resilient" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".resilient" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_serverlog": { + "title": "Connector response properties for a server log connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "type": "object", + "nullable": true + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".server-log" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_servicenow": { + "title": "Connector response properties for a ServiceNow ITSM connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_servicenow" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".servicenow" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_servicenow_itom": { + "title": "Connector response properties for a ServiceNow ITOM connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_servicenow_itom" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".servicenow-itom" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_servicenow_sir": { + "title": "Connector response properties for a ServiceNow SecOps connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_servicenow" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".servicenow-sir" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_slack_api": { + "title": "Connector response properties for a Slack connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".slack_api" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_slack_webhook": { + "title": "Connector response properties for a Slack connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".slack" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_swimlane": { + "title": "Connector response properties for a Swimlane connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_swimlane" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".swimlane" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_teams": { + "title": "Connector response properties for a Microsoft Teams connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "type": "object" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".teams" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_tines": { + "title": "Connector response properties for a Tines connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_tines" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".tines" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_torq": { + "title": "Connector response properties for a Torq connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_torq" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".torq" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_webhook": { + "title": "Connector response properties for a Webhook connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_webhook" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".webhook" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties_xmatters": { + "title": "Connector response properties for an xMatters connector", + "type": "object", + "required": [ + "connector_type_id", + "id", + "is_deprecated", + "is_preconfigured", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_xmatters" + }, + "connector_type_id": { + "type": "string", + "description": "The type of connector.", + "enum": [ + ".xmatters" + ] + }, + "id": { + "type": "string", + "description": "The identifier for the connector." + }, + "is_deprecated": { + "$ref": "#/components/schemas/is_deprecated" + }, + "is_missing_secrets": { + "$ref": "#/components/schemas/is_missing_secrets" + }, + "is_preconfigured": { + "$ref": "#/components/schemas/is_preconfigured" + }, + "is_system_action": { + "$ref": "#/components/schemas/is_system_action" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "referenced_by_count": { + "$ref": "#/components/schemas/referenced_by_count" + } + } + }, + "connector_response_properties": { + "title": "Connector response properties", + "description": "The properties vary depending on the connector type.", + "oneOf": [ + { + "$ref": "#/components/schemas/connector_response_properties_bedrock" + }, + { + "$ref": "#/components/schemas/connector_response_properties_cases_webhook" + }, + { + "$ref": "#/components/schemas/connector_response_properties_d3security" + }, + { + "$ref": "#/components/schemas/connector_response_properties_email" + }, + { + "$ref": "#/components/schemas/connector_response_properties_index" + }, + { + "$ref": "#/components/schemas/connector_response_properties_jira" + }, + { + "$ref": "#/components/schemas/connector_response_properties_opsgenie" + }, + { + "$ref": "#/components/schemas/connector_response_properties_pagerduty" + }, + { + "$ref": "#/components/schemas/connector_response_properties_resilient" + }, + { + "$ref": "#/components/schemas/connector_response_properties_serverlog" + }, + { + "$ref": "#/components/schemas/connector_response_properties_servicenow" + }, + { + "$ref": "#/components/schemas/connector_response_properties_servicenow_itom" + }, + { + "$ref": "#/components/schemas/connector_response_properties_servicenow_sir" + }, + { + "$ref": "#/components/schemas/connector_response_properties_slack_api" + }, + { + "$ref": "#/components/schemas/connector_response_properties_slack_webhook" + }, + { + "$ref": "#/components/schemas/connector_response_properties_swimlane" + }, + { + "$ref": "#/components/schemas/connector_response_properties_teams" + }, + { + "$ref": "#/components/schemas/connector_response_properties_tines" + }, + { + "$ref": "#/components/schemas/connector_response_properties_torq" + }, + { + "$ref": "#/components/schemas/connector_response_properties_webhook" + }, + { + "$ref": "#/components/schemas/connector_response_properties_xmatters" + } + ], + "discriminator": { + "propertyName": "connector_type_id" + } + }, + "update_connector_request_bedrock": { + "title": "Update Amazon Bedrock connector request", + "type": "object", + "required": [ + "config", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_bedrock" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_bedrock" + } + } + }, + "update_connector_request_cases_webhook": { + "title": "Update Webhook - Case Managment connector request", + "type": "object", + "required": [ + "config", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_cases_webhook" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_cases_webhook" + } + } + }, + "update_connector_request_d3security": { + "title": "Update D3 Security connector request", + "type": "object", + "required": [ + "config", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_d3security" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_d3security" + } + } + }, + "update_connector_request_email": { + "title": "Update email connector request", + "type": "object", + "required": [ + "config", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_email" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_email" + } + } + }, + "update_connector_request_index": { + "title": "Update index connector request", + "type": "object", + "required": [ + "config", + "name" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_index" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + } + } + }, + "update_connector_request_jira": { + "title": "Update Jira connector request", + "type": "object", + "required": [ + "config", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_jira" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_jira" + } + } + }, + "update_connector_request_opsgenie": { + "title": "Update Opsgenie connector request", + "type": "object", + "required": [ + "config", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_opsgenie" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_opsgenie" + } + } + }, + "update_connector_request_pagerduty": { + "title": "Update PagerDuty connector request", + "type": "object", + "required": [ + "config", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_pagerduty" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_pagerduty" + } + } + }, + "update_connector_request_resilient": { + "title": "Update IBM Resilient connector request", + "type": "object", + "required": [ + "config", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_resilient" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_resilient" + } + } + }, + "update_connector_request_serverlog": { + "title": "Update server log connector request", + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "description": "The display name for the connector." + } + } + }, + "update_connector_request_servicenow": { + "title": "Update ServiceNow ITSM connector or ServiceNow SecOps request", + "type": "object", + "required": [ + "config", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_servicenow" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_servicenow" + } + } + }, + "update_connector_request_servicenow_itom": { + "title": "Create ServiceNow ITOM connector request", + "type": "object", + "required": [ + "config", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_servicenow_itom" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_servicenow" + } + } + }, + "update_connector_request_slack_api": { + "title": "Update Slack connector request", + "type": "object", + "required": [ + "name", + "secrets" + ], + "properties": { + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_slack_api" + } + } + }, + "update_connector_request_slack_webhook": { + "title": "Update Slack connector request", + "type": "object", + "required": [ + "name", + "secrets" + ], + "properties": { + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_slack_webhook" + } + } + }, + "update_connector_request_swimlane": { + "title": "Update Swimlane connector request", + "type": "object", + "required": [ + "config", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_swimlane" + }, + "name": { + "type": "string", + "description": "The display name for the connector.", + "example": "my-connector" + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_swimlane" + } + } + }, + "update_connector_request_teams": { + "title": "Update Microsoft Teams connector request", + "type": "object", + "required": [ + "name", + "secrets" + ], + "properties": { + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_teams" + } + } + }, + "update_connector_request_tines": { + "title": "Update Tines connector request", + "type": "object", + "required": [ + "config", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_tines" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_tines" + } + } + }, + "update_connector_request_torq": { + "title": "Update Torq connector request", + "type": "object", + "required": [ + "config", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_torq" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_torq" + } + } + }, + "update_connector_request_webhook": { + "title": "Update Webhook connector request", + "type": "object", + "required": [ + "config", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_webhook" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_webhook" + } + } + }, + "update_connector_request_xmatters": { + "title": "Update xMatters connector request", + "type": "object", + "required": [ + "config", + "name", + "secrets" + ], + "properties": { + "config": { + "$ref": "#/components/schemas/config_properties_xmatters" + }, + "name": { + "type": "string", + "description": "The display name for the connector." + }, + "secrets": { + "$ref": "#/components/schemas/secrets_properties_xmatters" + } + } + }, + "update_connector_request": { + "title": "Update connector request body properties", + "description": "The properties vary depending on the connector type.", + "oneOf": [ + { + "$ref": "#/components/schemas/update_connector_request_bedrock" + }, + { + "$ref": "#/components/schemas/update_connector_request_cases_webhook" + }, + { + "$ref": "#/components/schemas/update_connector_request_d3security" + }, + { + "$ref": "#/components/schemas/update_connector_request_email" + }, + { + "$ref": "#/components/schemas/create_connector_request_genai" + }, + { + "$ref": "#/components/schemas/update_connector_request_index" + }, + { + "$ref": "#/components/schemas/update_connector_request_jira" + }, + { + "$ref": "#/components/schemas/update_connector_request_opsgenie" + }, + { + "$ref": "#/components/schemas/update_connector_request_pagerduty" + }, + { + "$ref": "#/components/schemas/update_connector_request_resilient" + }, + { + "$ref": "#/components/schemas/update_connector_request_serverlog" + }, + { + "$ref": "#/components/schemas/update_connector_request_servicenow" + }, + { + "$ref": "#/components/schemas/update_connector_request_servicenow_itom" + }, + { + "$ref": "#/components/schemas/update_connector_request_slack_api" + }, + { + "$ref": "#/components/schemas/update_connector_request_slack_webhook" + }, + { + "$ref": "#/components/schemas/update_connector_request_swimlane" + }, + { + "$ref": "#/components/schemas/update_connector_request_teams" + }, + { + "$ref": "#/components/schemas/update_connector_request_tines" + }, + { + "$ref": "#/components/schemas/update_connector_request_torq" + }, + { + "$ref": "#/components/schemas/update_connector_request_webhook" + }, + { + "$ref": "#/components/schemas/update_connector_request_xmatters" + } + ] + }, + "features": { + "type": "string", + "description": "The feature that uses the connector.\n", + "enum": [ + "alerting", + "cases", + "generativeAI", + "siem", + "uptime" + ] + }, + "connector_types": { + "title": "Connector types", + "type": "string", + "description": "The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`.", + "enum": [ + ".bedrock", + ".cases-webhook", + ".d3security", + ".email", + ".gen-ai", + ".index", + ".jira", + ".opsgenie", + ".pagerduty", + ".resilient", + ".servicenow", + ".servicenow-itom", + ".servicenow-sir", + ".server-log", + ".slack", + ".slack_api", + ".swimlane", + ".teams", + ".tines", + ".torq", + ".webhook", + ".xmatters" + ], + "example": ".server-log" + } + }, + "examples": { + "create_email_connector_request": { + "summary": "Create an email connector.", + "value": { + "name": "email-connector-1", + "connector_type_id": ".email", + "config": { + "from": "tester@example.com", + "hasAuth": true, + "host": "https://example.com", + "port": 1025, + "secure": false, + "service": "other" + }, + "secrets": { + "user": "username", + "password": "password" + } + } + }, + "create_index_connector_request": { + "summary": "Create an index connector.", + "value": { + "name": "my-connector", + "connector_type_id": ".index", + "config": { + "index": "test-index" + } + } + }, + "create_webhook_connector_request": { + "summary": "Create a webhook connector with SSL authentication.", + "value": { + "name": "my-webhook-connector", + "connector_type_id": ".webhook", + "config": { + "method": "post", + "url": "https://example.com", + "authType": "webhook-authentication-ssl", + "certType": "ssl-crt-key" + }, + "secrets": { + "crt": "QmFnIEF0dH...", + "key": "LS0tLS1CRUdJ...", + "password": "my-passphrase" + } + } + }, + "create_xmatters_connector_request": { + "summary": "Create an xMatters connector with URL authentication.", + "value": { + "name": "my-xmatters-connector", + "connector_type_id": ".xmatters", + "config": { + "usesBasic": false + }, + "secrets": { + "secretsUrl": "https://example.com?apiKey=xxxxx" + } + } + }, + "create_email_connector_response": { + "summary": "A new email connector.", + "value": { + "id": "90a82c60-478f-11ee-a343-f98a117c727f", + "connector_type_id": ".email", + "name": "email-connector-1", + "config": { + "from": "tester@example.com", + "service": "other", + "host": "https://example.com", + "port": 1025, + "secure": false, + "hasAuth": true, + "tenantId": null, + "clientId": null, + "oauthTokenUrl": null + }, + "is_preconfigured": false, + "is_deprecated": false, + "is_missing_secrets": false, + "is_system_action": false + } + }, + "create_index_connector_response": { + "summary": "A new index connector.", + "value": { + "id": "c55b6eb0-6bad-11eb-9f3b-611eebc6c3ad", + "connector_type_id": ".index", + "name": "my-connector", + "config": { + "index": "test-index", + "refresh": false, + "executionTimeField": null + }, + "is_preconfigured": false, + "is_deprecated": false, + "is_missing_secrets": false, + "is_system_action": false + } + }, + "create_webhook_connector_response": { + "summary": "A new webhook connector.", + "value": { + "id": "900eb010-3b9d-11ee-a642-8ffbb94e38bd", + "name": "my-webhook-connector", + "config": { + "method": "post", + "url": "https://example.com", + "authType": "webhook-authentication-ssl", + "certType": "ssl-crt-key", + "verificationMode": "full", + "headers": null, + "hasAuth": true + }, + "connector_type_id": ".webhook", + "is_preconfigured": false, + "is_deprecated": false, + "is_missing_secrets": false, + "is_system_action": false + } + }, + "create_xmatters_connector_response": { + "summary": "A new xMatters connector.", + "value": { + "id": "4d2d8da0-4d1f-11ee-9367-577408be4681", + "name": "my-xmatters-connector", + "config": { + "usesBasic": false, + "configUrl": null + }, + "connector_type_id": ".xmatters", + "is_preconfigured": false, + "is_deprecated": false, + "is_missing_secrets": false, + "is_system_action": false + } + }, + "get_connector_response": { + "summary": "Get connector details.", + "value": { + "id": "df770e30-8b8b-11ed-a780-3b746c987a81", + "name": "my_server_log_connector", + "config": {}, + "connector_type_id": ".server-log", + "is_preconfigured": false, + "is_deprecated": false, + "is_missing_secrets": false, + "is_system_action": false + } + }, + "update_index_connector_request": { + "summary": "Update an index connector.", + "value": { + "name": "updated-connector", + "config": { + "index": "updated-index" + } + } + }, + "get_connectors_response": { + "summary": "A list of connectors", + "value": [ + { + "id": "preconfigured-email-connector", + "name": "my-preconfigured-email-notification", + "connector_type_id": ".email", + "is_preconfigured": true, + "is_deprecated": false, + "referenced_by_count": 0, + "is_system_action": false + }, + { + "id": "e07d0c80-8b8b-11ed-a780-3b746c987a81", + "name": "my-index-connector", + "config": { + "index": "test-index", + "refresh": false, + "executionTimeField": null + }, + "connector_type_id": ".index", + "is_preconfigured": false, + "is_deprecated": false, + "referenced_by_count": 2, + "is_missing_secrets": false, + "is_system_action": false + } + ] + }, + "get_connector_types_generativeai_response": { + "summary": "A list of connector types for the `generativeAI` feature.", + "value": [ + { + "id": ".gen-ai", + "name": "OpenAI", + "enabled": true, + "enabled_in_config": true, + "enabled_in_license": true, + "minimum_license_required": "enterprise", + "supported_feature_ids": [ + "generativeAI" + ], + "is_system_action_type": false + }, + { + "id": ".bedrock", + "name": "AWS Bedrock", + "enabled": true, + "enabled_in_config": true, + "enabled_in_license": true, + "minimum_license_required": "enterprise", + "supported_feature_ids": [ + "generativeAI" + ], + "is_system_action_type": false + } + ] + } + }, + "responses": { + "401": { + "description": "Authorization information is missing or invalid.", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Unauthorized response", + "properties": { + "error": { + "type": "string", + "example": "Unauthorized", + "enum": [ + "Unauthorized" + ] + }, + "message": { + "type": "string" + }, + "statusCode": { + "type": "integer", + "example": 401, + "enum": [ + 401 + ] + } + } + } + } + } + }, + "404": { + "description": "Object is not found.", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Not found response", + "properties": { + "error": { + "type": "string", + "example": "Not Found", + "enum": [ + "Not Found" + ] + }, + "message": { + "type": "string", + "example": "Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found" + }, + "statusCode": { + "type": "integer", + "example": 404, + "enum": [ + 404 + ] + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml b/x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml new file mode 100644 index 00000000000000..b66a820c1b77d7 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml @@ -0,0 +1,2985 @@ +openapi: 3.0.1 +info: + title: Connectors + description: OpenAPI schema for connectors in Serverless projects + version: '0.1' + contact: + name: Connectors Team + license: + name: Elastic License 2.0 + url: https://www.elastic.co/licensing/elastic-license +servers: + - url: http://localhost:5601 + description: local +security: + - apiKeyAuth: [] +tags: + - name: connectors + description: Connector APIs enable you to create and manage connectors. +paths: + /api/actions/connector: + post: + summary: Creates a connector. + operationId: createConnector + tags: + - connectors + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/create_connector_request' + examples: + createEmailConnectorRequest: + $ref: '#/components/examples/create_email_connector_request' + createIndexConnectorRequest: + $ref: '#/components/examples/create_index_connector_request' + createWebhookConnectorRequest: + $ref: '#/components/examples/create_webhook_connector_request' + createXmattersConnectorRequest: + $ref: '#/components/examples/create_xmatters_connector_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/connector_response_properties' + examples: + createEmailConnectorResponse: + $ref: '#/components/examples/create_email_connector_response' + createIndexConnectorResponse: + $ref: '#/components/examples/create_index_connector_response' + createWebhookConnectorResponse: + $ref: '#/components/examples/create_webhook_connector_response' + createXmattersConnectorResponse: + $ref: '#/components/examples/create_xmatters_connector_response' + '401': + $ref: '#/components/responses/401' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/actions/connector/{connectorId}: + get: + summary: Retrieves a connector by ID. + operationId: getConnector + tags: + - connectors + parameters: + - $ref: '#/components/parameters/connector_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/connector_response_properties' + examples: + getConnectorResponse: + $ref: '#/components/examples/get_connector_response' + '401': + $ref: '#/components/responses/401' + '404': + $ref: '#/components/responses/404' + servers: + - url: https://localhost:5601 + delete: + summary: Deletes a connector. + operationId: deleteConnector + tags: + - connectors + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/connector_id' + responses: + '204': + description: Indicates a successful call. + '401': + $ref: '#/components/responses/401' + '404': + $ref: '#/components/responses/404' + servers: + - url: https://localhost:5601 + post: + summary: Creates a connector. + operationId: createConnectorId + tags: + - connectors + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - in: path + name: connectorId + description: | + A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated. + required: true + schema: + type: string + example: ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/create_connector_request' + examples: + createIndexConnectorRequest: + $ref: '#/components/examples/create_index_connector_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/connector_response_properties' + examples: + createIndexConnectorResponse: + $ref: '#/components/examples/create_index_connector_response' + '401': + $ref: '#/components/responses/401' + servers: + - url: https://localhost:5601 + put: + summary: Updates the attributes for a connector. + operationId: updateConnector + tags: + - connectors + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/connector_id' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/update_connector_request' + examples: + updateIndexConnectorRequest: + $ref: '#/components/examples/update_index_connector_request' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '#/components/schemas/connector_response_properties' + '400': + $ref: '#/components/responses/401' + '401': + $ref: '#/components/responses/401' + '404': + $ref: '#/components/responses/404' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/actions/connectors: + get: + summary: Retrieves all connectors. + operationId: getConnectors + tags: + - connectors + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/connector_response_properties' + examples: + getConnectorsResponse: + $ref: '#/components/examples/get_connectors_response' + '401': + $ref: '#/components/responses/401' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/actions/connector_types: + get: + summary: Retrieves a list of all connector types. + operationId: getConnectorTypes + tags: + - connectors + parameters: + - in: query + name: feature_id + description: A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases). + schema: + $ref: '#/components/schemas/features' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + title: Get connector types response body properties + description: The properties vary for each connector type. + type: array + items: + type: object + properties: + enabled: + type: boolean + description: Indicates whether the connector type is enabled in Kibana. + example: true + enabled_in_config: + type: boolean + description: Indicates whether the connector type is enabled in the Kibana configuration file. + example: true + enabled_in_license: + type: boolean + description: Indicates whether the connector is enabled in the license. + example: true + id: + $ref: '#/components/schemas/connector_types' + is_system_action_type: + type: boolean + example: false + minimum_license_required: + type: string + description: The license that is required to use the connector type. + example: basic + name: + type: string + description: The name of the connector type. + example: Index + supported_feature_ids: + type: array + description: The features that are supported by the connector type. + items: + $ref: '#/components/schemas/features' + example: + - alerting + - cases + - siem + examples: + getConnectorTypesServerlessResponse: + $ref: '#/components/examples/get_connector_types_generativeai_response' + '401': + $ref: '#/components/responses/401' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 +components: + securitySchemes: + apiKeyAuth: + type: apiKey + in: header + name: ApiKey + parameters: + kbn_xsrf: + schema: + type: string + in: header + name: kbn-xsrf + description: Cross-site request forgery protection + required: true + connector_id: + in: path + name: connectorId + description: An identifier for the connector. + required: true + schema: + type: string + example: df770e30-8b8b-11ed-a780-3b746c987a81 + schemas: + config_properties_bedrock: + title: Connector request properties for an Amazon Bedrock connector + description: Defines properties for connectors when type is `.bedrock`. + type: object + required: + - apiUrl + properties: + apiUrl: + type: string + description: The Amazon Bedrock request URL. + defaultModel: + type: string + description: | + The generative artificial intelligence model for Amazon Bedrock to use. Current support is for the Anthropic Claude models. + default: anthropic.claude-v2 + secrets_properties_bedrock: + title: Connector secrets properties for an Amazon Bedrock connector + description: Defines secrets for connectors when type is `.bedrock`. + type: object + required: + - accessKey + - secret + properties: + accessKey: + type: string + description: The AWS access key for authentication. + secret: + type: string + description: The AWS secret for authentication. + create_connector_request_bedrock: + title: Create Amazon Bedrock connector request + description: The Amazon Bedrock connector uses axios to send a POST request to Amazon Bedrock. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_bedrock' + connector_type_id: + type: string + description: The type of connector. + enum: + - .bedrock + example: .bedrock + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_bedrock' + config_properties_cases_webhook: + title: Connector request properties for Webhook - Case Management connector + required: + - createIncidentJson + - createIncidentResponseKey + - createIncidentUrl + - getIncidentResponseExternalTitleKey + - getIncidentUrl + - updateIncidentJson + - updateIncidentUrl + - viewIncidentUrl + description: Defines properties for connectors when type is `.cases-webhook`. + type: object + properties: + createCommentJson: + type: string + description: | + A JSON payload sent to the create comment URL to create a case comment. You can use variables to add Kibana Cases data to the payload. The required variable is `case.comment`. Due to Mustache template variables (the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated once the Mustache variables have been placed when the REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass. + example: + body: + '[object Object]': null + createCommentMethod: + type: string + description: | + The REST API HTTP request method to create a case comment in the third-party system. Valid values are `patch`, `post`, and `put`. + default: put + enum: + - patch + - post + - put + createCommentUrl: + type: string + description: | + The REST API URL to create a case comment by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts setting`, add the hostname to the allowed hosts. + example: https://testing-jira.atlassian.net/rest/api/2/issue/{{{external.system.id}}}/comment + createIncidentJson: + type: string + description: | + A JSON payload sent to the create case URL to create a case. You can use variables to add case data to the payload. Required variables are `case.title` and `case.description`. Due to Mustache template variables (which is the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review. + example: + fields: + summary: + '[object Object]': null + description: + '[object Object]': null + labels: + '[object Object]': null + createIncidentMethod: + type: string + description: | + The REST API HTTP request method to create a case in the third-party system. Valid values are `patch`, `post`, and `put`. + enum: + - patch + - post + - put + default: post + createIncidentResponseKey: + type: string + description: The JSON key in the create case response that contains the external case ID. + createIncidentUrl: + type: string + description: | + The REST API URL to create a case in the third-party system. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. + getIncidentResponseExternalTitleKey: + type: string + description: The JSON key in get case response that contains the external case title. + getIncidentUrl: + type: string + description: | + The REST API URL to get the case by ID from the third-party system. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. You can use a variable to add the external system ID to the URL. Due to Mustache template variables (the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass. + example: https://testing-jira.atlassian.net/rest/api/2/issue/{{{external.system.id}}} + hasAuth: + type: boolean + description: If true, a username and password for login type authentication must be provided. + default: true + headers: + type: string + description: | + A set of key-value pairs sent as headers with the request URLs for the create case, update case, get case, and create comment methods. + updateIncidentJson: + type: string + description: | + The JSON payload sent to the update case URL to update the case. You can use variables to add Kibana Cases data to the payload. Required variables are `case.title` and `case.description`. Due to Mustache template variables (which is the text enclosed in triple braces, for example, `{{{case.title}}}`), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review. + example: + fields: + summary: + '[object Object]': null + description: + '[object Object]': null + labels: + '[object Object]': null + updateIncidentMethod: + type: string + description: | + The REST API HTTP request method to update the case in the third-party system. Valid values are `patch`, `post`, and `put`. + default: put + enum: + - patch + - post + - put + updateIncidentUrl: + type: string + description: | + The REST API URL to update the case by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. + example: https://testing-jira.atlassian.net/rest/api/2/issue/{{{external.system.ID}}} + viewIncidentUrl: + type: string + description: | + The URL to view the case in the external system. You can use variables to add the external system ID or external system title to the URL. + example: https://testing-jira.atlassian.net/browse/{{{external.system.title}}} + secrets_properties_cases_webhook: + title: Connector secrets properties for Webhook - Case Management connector + type: object + properties: + password: + type: string + description: The password for HTTP basic authentication. If `hasAuth` is set to `true`, this property is required. + user: + type: string + description: The username for HTTP basic authentication. If `hasAuth` is set to `true`, this property is required. + create_connector_request_cases_webhook: + title: Create Webhook - Case Managment connector request + description: | + The Webhook - Case Management connector uses axios to send POST, PUT, and GET requests to a case management RESTful API web service. + type: object + required: + - config + - connector_type_id + - name + properties: + config: + $ref: '#/components/schemas/config_properties_cases_webhook' + connector_type_id: + type: string + description: The type of connector. + enum: + - .cases-webhook + example: .cases-webhook + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_cases_webhook' + config_properties_d3security: + title: Connector request properties for a D3 Security connector + description: Defines properties for connectors when type is `.d3security`. + type: object + required: + - url + properties: + url: + type: string + description: | + The D3 Security API request URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. + secrets_properties_d3security: + title: Connector secrets properties for a D3 Security connector + description: Defines secrets for connectors when type is `.d3security`. + required: + - token + type: object + properties: + token: + type: string + description: The D3 Security token. + create_connector_request_d3security: + title: Create D3 Security connector request + description: | + The connector uses axios to send a POST request to a D3 Security endpoint. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_d3security' + connector_type_id: + type: string + description: The type of connector. + enum: + - .d3security + example: .d3security + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_d3security' + config_properties_email: + title: Connector request properties for an email connector + description: Defines properties for connectors when type is `.email`. + required: + - from + type: object + properties: + clientId: + description: | + The client identifier, which is a part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required. + type: string + nullable: true + from: + description: | + The from address for all emails sent by the connector. It must be specified in `user@host-name` format. + type: string + hasAuth: + description: | + Specifies whether a user and password are required inside the secrets configuration. + default: true + type: boolean + host: + description: | + The host name of the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. + type: string + oauthTokenUrl: + type: string + nullable: true + port: + description: | + The port to connect to on the service provider. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If `service` is `other`, this property must be defined. + type: integer + secure: + description: | + Specifies whether the connection to the service provider will use TLS. If the `service` is `elastic_cloud` (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. + type: boolean + service: + description: | + The name of the email service. + type: string + enum: + - elastic_cloud + - exchange_server + - gmail + - other + - outlook365 + - ses + tenantId: + description: | + The tenant identifier, which is part of OAuth 2.0 client credentials authentication, in GUID format. If `service` is `exchange_server`, this property is required. + type: string + nullable: true + secrets_properties_email: + title: Connector secrets properties for an email connector + description: Defines secrets for connectors when type is `.email`. + type: object + properties: + clientSecret: + type: string + description: | + The Microsoft Exchange Client secret for OAuth 2.0 client credentials authentication. It must be URL-encoded. If `service` is `exchange_server`, this property is required. + password: + type: string + description: | + The password for HTTP basic authentication. If `hasAuth` is set to `true`, this property is required. + user: + type: string + description: | + The username for HTTP basic authentication. If `hasAuth` is set to `true`, this property is required. + create_connector_request_email: + title: Create email connector request + description: | + The email connector uses the SMTP protocol to send mail messages, using an integration of Nodemailer. An exception is Microsoft Exchange, which uses HTTP protocol for sending emails, Send mail. Email message text is sent as both plain text and html text. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_email' + connector_type_id: + type: string + description: The type of connector. + enum: + - .email + example: .email + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_email' + config_properties_genai: + title: Connector request properties for an OpenAI connector + description: Defines properties for connectors when type is `.gen-ai`. + oneOf: + - type: object + required: + - apiProvider + - apiUrl + properties: + apiProvider: + type: string + description: The OpenAI API provider. + enum: + - Azure OpenAI + apiUrl: + type: string + description: The OpenAI API endpoint. + - type: object + required: + - apiProvider + - apiUrl + properties: + apiProvider: + type: string + description: The OpenAI API provider. + enum: + - OpenAI + apiUrl: + type: string + description: The OpenAI API endpoint. + defaultModel: + type: string + description: The default model to use for requests. + discriminator: + propertyName: apiProvider + secrets_properties_genai: + title: Connector secrets properties for an OpenAI connector + description: Defines secrets for connectors when type is `.gen-ai`. + type: object + properties: + apiKey: + type: string + description: The OpenAI API key. + create_connector_request_genai: + title: Create OpenAI connector request + description: | + The OpenAI connector uses axios to send a POST request to either OpenAI or Azure OpenAPI. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_genai' + connector_type_id: + type: string + description: The type of connector. + enum: + - .gen-ai + example: .gen-ai + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_genai' + config_properties_index: + title: Connector request properties for an index connector + required: + - index + description: Defines properties for connectors when type is `.index`. + type: object + properties: + executionTimeField: + description: A field that indicates when the document was indexed. + default: null + type: string + nullable: true + index: + description: The Elasticsearch index to be written to. + type: string + refresh: + description: | + The refresh policy for the write request, which affects when changes are made visible to search. Refer to the refresh setting for Elasticsearch document APIs. + default: false + type: boolean + create_connector_request_index: + title: Create index connector request + description: The index connector indexes a document into Elasticsearch. + type: object + required: + - config + - connector_type_id + - name + properties: + config: + $ref: '#/components/schemas/config_properties_index' + connector_type_id: + type: string + description: The type of connector. + enum: + - .index + example: .index + name: + type: string + description: The display name for the connector. + example: my-connector + config_properties_jira: + title: Connector request properties for a Jira connector + required: + - apiUrl + - projectKey + description: Defines properties for connectors when type is `.jira`. + type: object + properties: + apiUrl: + description: The Jira instance URL. + type: string + projectKey: + description: The Jira project key. + type: string + secrets_properties_jira: + title: Connector secrets properties for a Jira connector + required: + - apiToken + - email + description: Defines secrets for connectors when type is `.jira`. + type: object + properties: + apiToken: + description: The Jira API authentication token for HTTP basic authentication. + type: string + email: + description: The account email for HTTP Basic authentication. + type: string + create_connector_request_jira: + title: Create Jira connector request + description: The Jira connector uses the REST API v2 to create Jira issues. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_jira' + connector_type_id: + type: string + description: The type of connector. + enum: + - .jira + example: .jira + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_jira' + config_properties_opsgenie: + title: Connector request properties for an Opsgenie connector + required: + - apiUrl + description: Defines properties for connectors when type is `.opsgenie`. + type: object + properties: + apiUrl: + description: | + The Opsgenie URL. For example, `https://api.opsgenie.com` or `https://api.eu.opsgenie.com`. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. + type: string + secrets_properties_opsgenie: + title: Connector secrets properties for an Opsgenie connector + required: + - apiKey + description: Defines secrets for connectors when type is `.opsgenie`. + type: object + properties: + apiKey: + description: The Opsgenie API authentication key for HTTP Basic authentication. + type: string + create_connector_request_opsgenie: + title: Create Opsgenie connector request + description: The Opsgenie connector uses the Opsgenie alert API. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_opsgenie' + connector_type_id: + type: string + description: The type of connector. + enum: + - .opsgenie + example: .opsgenie + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_opsgenie' + config_properties_pagerduty: + title: Connector request properties for a PagerDuty connector + description: Defines properties for connectors when type is `.pagerduty`. + type: object + properties: + apiUrl: + description: The PagerDuty event URL. + type: string + nullable: true + example: https://events.pagerduty.com/v2/enqueue + secrets_properties_pagerduty: + title: Connector secrets properties for a PagerDuty connector + description: Defines secrets for connectors when type is `.pagerduty`. + type: object + required: + - routingKey + properties: + routingKey: + description: | + A 32 character PagerDuty Integration Key for an integration on a service. + type: string + create_connector_request_pagerduty: + title: Create PagerDuty connector request + description: | + The PagerDuty connector uses the v2 Events API to trigger, acknowledge, and resolve PagerDuty alerts. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_pagerduty' + connector_type_id: + type: string + description: The type of connector. + enum: + - .pagerduty + example: .pagerduty + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_pagerduty' + config_properties_resilient: + title: Connector request properties for a IBM Resilient connector + required: + - apiUrl + - orgId + description: Defines properties for connectors when type is `.resilient`. + type: object + properties: + apiUrl: + description: The IBM Resilient instance URL. + type: string + orgId: + description: The IBM Resilient organization ID. + type: string + secrets_properties_resilient: + title: Connector secrets properties for IBM Resilient connector + required: + - apiKeyId + - apiKeySecret + description: Defines secrets for connectors when type is `.resilient`. + type: object + properties: + apiKeyId: + type: string + description: The authentication key ID for HTTP Basic authentication. + apiKeySecret: + type: string + description: The authentication key secret for HTTP Basic authentication. + create_connector_request_resilient: + title: Create IBM Resilient connector request + description: The IBM Resilient connector uses the RESILIENT REST v2 to create IBM Resilient incidents. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_resilient' + connector_type_id: + description: The type of connector. + type: string + example: .resilient + enum: + - .resilient + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_resilient' + create_connector_request_serverlog: + title: Create server log connector request + description: This connector writes an entry to the Kibana server log. + type: object + required: + - connector_type_id + - name + properties: + connector_type_id: + type: string + description: The type of connector. + enum: + - .server-log + example: .server-log + name: + type: string + description: The display name for the connector. + example: my-connector + config_properties_servicenow: + title: Connector request properties for a ServiceNow ITSM connector + required: + - apiUrl + description: Defines properties for connectors when type is `.servicenow`. + type: object + properties: + apiUrl: + type: string + description: The ServiceNow instance URL. + clientId: + description: | + The client ID assigned to your OAuth application. This property is required when `isOAuth` is `true`. + type: string + isOAuth: + description: | + The type of authentication to use. The default value is false, which means basic authentication is used instead of open authorization (OAuth). + default: false + type: boolean + jwtKeyId: + description: | + The key identifier assigned to the JWT verifier map of your OAuth application. This property is required when `isOAuth` is `true`. + type: string + userIdentifierValue: + description: | + The identifier to use for OAuth authentication. This identifier should be the user field you selected when you created an OAuth JWT API endpoint for external clients in your ServiceNow instance. For example, if the selected user field is `Email`, the user identifier should be the user's email address. This property is required when `isOAuth` is `true`. + type: string + usesTableApi: + description: | + Determines whether the connector uses the Table API or the Import Set API. This property is supported only for ServiceNow ITSM and ServiceNow SecOps connectors. NOTE: If this property is set to `false`, the Elastic application should be installed in ServiceNow. + default: true + type: boolean + secrets_properties_servicenow: + title: Connector secrets properties for ServiceNow ITOM, ServiceNow ITSM, and ServiceNow SecOps connectors + description: Defines secrets for connectors when type is `.servicenow`, `.servicenow-sir`, or `.servicenow-itom`. + type: object + properties: + clientSecret: + type: string + description: The client secret assigned to your OAuth application. This property is required when `isOAuth` is `true`. + password: + type: string + description: The password for HTTP basic authentication. This property is required when `isOAuth` is `false`. + privateKey: + type: string + description: The RSA private key that you created for use in ServiceNow. This property is required when `isOAuth` is `true`. + privateKeyPassword: + type: string + description: The password for the RSA private key. This property is required when `isOAuth` is `true` and you set a password on your private key. + username: + type: string + description: The username for HTTP basic authentication. This property is required when `isOAuth` is `false`. + create_connector_request_servicenow: + title: Create ServiceNow ITSM connector request + description: | + The ServiceNow ITSM connector uses the import set API to create ServiceNow incidents. You can use the connector for rule actions and cases. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_servicenow' + connector_type_id: + type: string + description: The type of connector. + enum: + - .servicenow + example: .servicenow + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_servicenow' + config_properties_servicenow_itom: + title: Connector request properties for a ServiceNow ITSM connector + required: + - apiUrl + description: Defines properties for connectors when type is `.servicenow`. + type: object + properties: + apiUrl: + type: string + description: The ServiceNow instance URL. + clientId: + description: | + The client ID assigned to your OAuth application. This property is required when `isOAuth` is `true`. + type: string + isOAuth: + description: | + The type of authentication to use. The default value is false, which means basic authentication is used instead of open authorization (OAuth). + default: false + type: boolean + jwtKeyId: + description: | + The key identifier assigned to the JWT verifier map of your OAuth application. This property is required when `isOAuth` is `true`. + type: string + userIdentifierValue: + description: | + The identifier to use for OAuth authentication. This identifier should be the user field you selected when you created an OAuth JWT API endpoint for external clients in your ServiceNow instance. For example, if the selected user field is `Email`, the user identifier should be the user's email address. This property is required when `isOAuth` is `true`. + type: string + create_connector_request_servicenow_itom: + title: Create ServiceNow ITOM connector request + description: | + The ServiceNow ITOM connector uses the event API to create ServiceNow events. You can use the connector for rule actions. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_servicenow_itom' + connector_type_id: + type: string + description: The type of connector. + enum: + - .servicenow-itom + example: .servicenow-itom + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_servicenow' + create_connector_request_servicenow_sir: + title: Create ServiceNow SecOps connector request + description: | + The ServiceNow SecOps connector uses the import set API to create ServiceNow security incidents. You can use the connector for rule actions and cases. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_servicenow' + connector_type_id: + type: string + description: The type of connector. + enum: + - .servicenow-sir + example: .servicenow-sir + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_servicenow' + secrets_properties_slack_api: + title: Connector secrets properties for a Web API Slack connector + description: Defines secrets for connectors when type is `.slack`. + required: + - token + type: object + properties: + token: + type: string + description: Slack bot user OAuth token. + create_connector_request_slack_api: + title: Create Slack connector request + description: The Slack connector uses Slack Incoming Webhooks. + type: object + required: + - connector_type_id + - name + - secrets + properties: + connector_type_id: + type: string + description: The type of connector. + enum: + - .slack_api + example: .slack_api + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_slack_api' + secrets_properties_slack_webhook: + title: Connector secrets properties for a Webhook Slack connector + description: Defines secrets for connectors when type is `.slack`. + required: + - webhookUrl + type: object + properties: + webhookUrl: + type: string + description: Slack webhook url. + create_connector_request_slack_webhook: + title: Create Slack connector request + description: The Slack connector uses Slack Incoming Webhooks. + type: object + required: + - connector_type_id + - name + - secrets + properties: + connector_type_id: + type: string + description: The type of connector. + enum: + - .slack + example: .slack + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_slack_webhook' + config_properties_swimlane: + title: Connector request properties for a Swimlane connector + required: + - apiUrl + - appId + - connectorType + description: Defines properties for connectors when type is `.swimlane`. + type: object + properties: + apiUrl: + description: The Swimlane instance URL. + type: string + appId: + description: The Swimlane application ID. + type: string + connectorType: + description: The type of connector. Valid values are `all`, `alerts`, and `cases`. + type: string + enum: + - all + - alerts + - cases + mappings: + title: Connector mappings properties for a Swimlane connector + description: The field mapping. + type: object + properties: + alertIdConfig: + title: Alert identifier mapping + description: Mapping for the alert ID. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + caseIdConfig: + title: Case identifier mapping + description: Mapping for the case ID. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + caseNameConfig: + title: Case name mapping + description: Mapping for the case name. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + commentsConfig: + title: Case comment mapping + description: Mapping for the case comments. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + descriptionConfig: + title: Case description mapping + description: Mapping for the case description. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + ruleNameConfig: + title: Rule name mapping + description: Mapping for the name of the alert's rule. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + severityConfig: + title: Severity mapping + description: Mapping for the severity. + type: object + required: + - fieldType + - id + - key + - name + properties: + fieldType: + type: string + description: The type of field in Swimlane. + id: + type: string + description: The identifier for the field in Swimlane. + key: + type: string + description: The key for the field in Swimlane. + name: + type: string + description: The name of the field in Swimlane. + secrets_properties_swimlane: + title: Connector secrets properties for a Swimlane connector + description: Defines secrets for connectors when type is `.swimlane`. + type: object + properties: + apiToken: + description: Swimlane API authentication token. + type: string + create_connector_request_swimlane: + title: Create Swimlane connector request + description: The Swimlane connector uses the Swimlane REST API to create Swimlane records. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_swimlane' + connector_type_id: + type: string + description: The type of connector. + enum: + - .swimlane + example: .swimlane + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_swimlane' + secrets_properties_teams: + title: Connector secrets properties for a Microsoft Teams connector + description: Defines secrets for connectors when type is `.teams`. + type: object + required: + - webhookUrl + properties: + webhookUrl: + type: string + description: | + The URL of the incoming webhook. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. + create_connector_request_teams: + title: Create Microsoft Teams connector request + description: The Microsoft Teams connector uses Incoming Webhooks. + type: object + required: + - connector_type_id + - name + - secrets + properties: + connector_type_id: + type: string + description: The type of connector. + enum: + - .teams + example: .teams + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_teams' + config_properties_tines: + title: Connector request properties for a Tines connector + description: Defines properties for connectors when type is `.tines`. + type: object + required: + - url + properties: + url: + description: | + The Tines tenant URL. If you are using the `xpack.actions.allowedHosts` setting, make sure this hostname is added to the allowed hosts. + type: string + secrets_properties_tines: + title: Connector secrets properties for a Tines connector + description: Defines secrets for connectors when type is `.tines`. + type: object + required: + - email + - token + properties: + email: + description: The email used to sign in to Tines. + type: string + token: + description: The Tines API token. + type: string + create_connector_request_tines: + title: Create Tines connector request + description: | + The Tines connector uses Tines Webhook actions to send events via POST request. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_tines' + connector_type_id: + type: string + description: The type of connector. + enum: + - .tines + example: .tines + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_tines' + config_properties_torq: + title: Connector request properties for a Torq connector + description: Defines properties for connectors when type is `.torq`. + type: object + required: + - webhookIntegrationUrl + properties: + webhookIntegrationUrl: + description: The endpoint URL of the Elastic Security integration in Torq. + type: string + secrets_properties_torq: + title: Connector secrets properties for a Torq connector + description: Defines secrets for connectors when type is `.torq`. + type: object + required: + - token + properties: + token: + description: The secret of the webhook authentication header. + type: string + create_connector_request_torq: + title: Create Torq connector request + description: | + The Torq connector uses a Torq webhook to trigger workflows with Kibana actions. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_torq' + connector_type_id: + type: string + description: The type of connector. + enum: + - .torq + example: .torq + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_torq' + config_properties_webhook: + title: Connector request properties for a Webhook connector + description: Defines properties for connectors when type is `.webhook`. + type: object + properties: + authType: + type: string + enum: + - webhook-authentication-basic + - webhook-authentication-ssl + - 'null' + description: | + The type of authentication to use: basic, SSL, or none. + ca: + type: string + description: | + A base64 encoded version of the certificate authority file that the connector can trust to sign and validate certificates. This option is available for all authentication types. + certType: + type: string + description: | + If the `authType` is `webhook-authentication-ssl`, specifies whether the certificate authentication data is in a CRT and key file format or a PFX file format. + enum: + - ssl-crt-key + - ssl-pfx + hasAuth: + type: boolean + description: | + If `true`, a user name and password must be provided for login type authentication. + headers: + type: object + nullable: true + description: A set of key-value pairs sent as headers with the request. + method: + type: string + default: post + enum: + - post + - put + description: | + The HTTP request method, either `post` or `put`. + url: + type: string + description: | + The request URL. If you are using the `xpack.actions.allowedHosts` setting, add the hostname to the allowed hosts. + verificationMode: + type: string + enum: + - certificate + - full + - none + default: full + description: | + Controls the verification of certificates. Use `full` to validate that the certificate has an issue date within the `not_before` and `not_after` dates, chains to a trusted certificate authority (CA), and has a hostname or IP address that matches the names within the certificate. Use `certificate` to validate the certificate and verify that it is signed by a trusted authority; this option does not check the certificate hostname. Use `none` to skip certificate validation. + secrets_properties_webhook: + title: Connector secrets properties for a Webhook connector + description: Defines secrets for connectors when type is `.webhook`. + type: object + properties: + crt: + type: string + description: If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-crt-key`, it is a base64 encoded version of the CRT or CERT file. + key: + type: string + description: If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-crt-key`, it is a base64 encoded version of the KEY file. + pfx: + type: string + description: If `authType` is `webhook-authentication-ssl` and `certType` is `ssl-pfx`, it is a base64 encoded version of the PFX or P12 file. + password: + type: string + description: | + The password for HTTP basic authentication or the passphrase for the SSL certificate files. If `hasAuth` is set to `true` and `authType` is `webhook-authentication-basic`, this property is required. + user: + type: string + description: | + The username for HTTP basic authentication. If `hasAuth` is set to `true` and `authType` is `webhook-authentication-basic`, this property is required. + create_connector_request_webhook: + title: Create Webhook connector request + description: | + The Webhook connector uses axios to send a POST or PUT request to a web service. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_webhook' + connector_type_id: + type: string + description: The type of connector. + enum: + - .webhook + example: .webhook + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_webhook' + config_properties_xmatters: + title: Connector request properties for an xMatters connector + description: Defines properties for connectors when type is `.xmatters`. + type: object + properties: + configUrl: + description: | + The request URL for the Elastic Alerts trigger in xMatters. It is applicable only when `usesBasic` is `true`. + type: string + nullable: true + usesBasic: + description: Specifies whether the connector uses HTTP basic authentication (`true`) or URL authentication (`false`). + type: boolean + default: true + secrets_properties_xmatters: + title: Connector secrets properties for an xMatters connector + description: Defines secrets for connectors when type is `.xmatters`. + type: object + properties: + password: + description: | + A user name for HTTP basic authentication. It is applicable only when `usesBasic` is `true`. + type: string + secretsUrl: + description: | + The request URL for the Elastic Alerts trigger in xMatters with the API key included in the URL. It is applicable only when `usesBasic` is `false`. + type: string + user: + description: | + A password for HTTP basic authentication. It is applicable only when `usesBasic` is `true`. + type: string + create_connector_request_xmatters: + title: Create xMatters connector request + description: | + The xMatters connector uses the xMatters Workflow for Elastic to send actionable alerts to on-call xMatters resources. + type: object + required: + - config + - connector_type_id + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_xmatters' + connector_type_id: + type: string + description: The type of connector. + enum: + - .xmatters + example: .xmatters + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_xmatters' + create_connector_request: + title: Create connector request body properties + description: The properties vary depending on the connector type. + oneOf: + - $ref: '#/components/schemas/create_connector_request_bedrock' + - $ref: '#/components/schemas/create_connector_request_cases_webhook' + - $ref: '#/components/schemas/create_connector_request_d3security' + - $ref: '#/components/schemas/create_connector_request_email' + - $ref: '#/components/schemas/create_connector_request_genai' + - $ref: '#/components/schemas/create_connector_request_index' + - $ref: '#/components/schemas/create_connector_request_jira' + - $ref: '#/components/schemas/create_connector_request_opsgenie' + - $ref: '#/components/schemas/create_connector_request_pagerduty' + - $ref: '#/components/schemas/create_connector_request_resilient' + - $ref: '#/components/schemas/create_connector_request_serverlog' + - $ref: '#/components/schemas/create_connector_request_servicenow' + - $ref: '#/components/schemas/create_connector_request_servicenow_itom' + - $ref: '#/components/schemas/create_connector_request_servicenow_sir' + - $ref: '#/components/schemas/create_connector_request_slack_api' + - $ref: '#/components/schemas/create_connector_request_slack_webhook' + - $ref: '#/components/schemas/create_connector_request_swimlane' + - $ref: '#/components/schemas/create_connector_request_teams' + - $ref: '#/components/schemas/create_connector_request_tines' + - $ref: '#/components/schemas/create_connector_request_torq' + - $ref: '#/components/schemas/create_connector_request_webhook' + - $ref: '#/components/schemas/create_connector_request_xmatters' + discriminator: + propertyName: connector_type_id + is_deprecated: + type: boolean + description: Indicates whether the connector type is deprecated. + example: false + is_missing_secrets: + type: boolean + description: Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type. + example: false + is_preconfigured: + type: boolean + description: | + Indicates whether it is a preconfigured connector. If true, the `config` and `is_missing_secrets` properties are omitted from the response. + example: false + is_system_action: + type: boolean + description: Indicates whether the connector is used for system actions. + example: false + connector_response_properties_bedrock: + title: Connector response properties for an Amazon Bedrock connector + type: object + required: + - config + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_bedrock' + connector_type_id: + type: string + description: The type of connector. + enum: + - .bedrock + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + type: integer + description: | + Indicates the number of saved objects that reference the connector. If `is_preconfigured` is true, this value is not calculated. This property is returned only by the get all connectors API. + example: 2 + connector_response_properties_cases_webhook: + title: Connector request properties for a Webhook - Case Management connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_cases_webhook' + connector_type_id: + description: The type of connector. + type: string + enum: + - .cases-webhook + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_d3security: + title: Connector response properties for a D3 Security connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_d3security' + connector_type_id: + type: string + description: The type of connector. + enum: + - .d3security + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_email: + title: Connector response properties for an email connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_email' + connector_type_id: + type: string + description: The type of connector. + enum: + - .email + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_index: + title: Connector response properties for an index connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_index' + connector_type_id: + type: string + description: The type of connector. + enum: + - .index + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_jira: + title: Connector response properties for a Jira connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_jira' + connector_type_id: + type: string + description: The type of connector. + enum: + - .jira + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_opsgenie: + title: Connector response properties for an Opsgenie connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_opsgenie' + connector_type_id: + type: string + description: The type of connector. + enum: + - .opsgenie + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_pagerduty: + title: Connector response properties for a PagerDuty connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_pagerduty' + connector_type_id: + type: string + description: The type of connector. + enum: + - .pagerduty + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_resilient: + title: Connector response properties for a IBM Resilient connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_resilient' + connector_type_id: + type: string + description: The type of connector. + enum: + - .resilient + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_serverlog: + title: Connector response properties for a server log connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + type: object + nullable: true + connector_type_id: + type: string + description: The type of connector. + enum: + - .server-log + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_servicenow: + title: Connector response properties for a ServiceNow ITSM connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_servicenow' + connector_type_id: + type: string + description: The type of connector. + enum: + - .servicenow + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_servicenow_itom: + title: Connector response properties for a ServiceNow ITOM connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_servicenow_itom' + connector_type_id: + type: string + description: The type of connector. + enum: + - .servicenow-itom + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_servicenow_sir: + title: Connector response properties for a ServiceNow SecOps connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_servicenow' + connector_type_id: + type: string + description: The type of connector. + enum: + - .servicenow-sir + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_slack_api: + title: Connector response properties for a Slack connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + connector_type_id: + type: string + description: The type of connector. + enum: + - .slack_api + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_slack_webhook: + title: Connector response properties for a Slack connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + connector_type_id: + type: string + description: The type of connector. + enum: + - .slack + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_swimlane: + title: Connector response properties for a Swimlane connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_swimlane' + connector_type_id: + type: string + description: The type of connector. + enum: + - .swimlane + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_teams: + title: Connector response properties for a Microsoft Teams connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + type: object + connector_type_id: + type: string + description: The type of connector. + enum: + - .teams + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_tines: + title: Connector response properties for a Tines connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_tines' + connector_type_id: + type: string + description: The type of connector. + enum: + - .tines + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_torq: + title: Connector response properties for a Torq connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_torq' + connector_type_id: + type: string + description: The type of connector. + enum: + - .torq + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_webhook: + title: Connector response properties for a Webhook connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_webhook' + connector_type_id: + type: string + description: The type of connector. + enum: + - .webhook + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties_xmatters: + title: Connector response properties for an xMatters connector + type: object + required: + - connector_type_id + - id + - is_deprecated + - is_preconfigured + - name + properties: + config: + $ref: '#/components/schemas/config_properties_xmatters' + connector_type_id: + type: string + description: The type of connector. + enum: + - .xmatters + id: + type: string + description: The identifier for the connector. + is_deprecated: + $ref: '#/components/schemas/is_deprecated' + is_missing_secrets: + $ref: '#/components/schemas/is_missing_secrets' + is_preconfigured: + $ref: '#/components/schemas/is_preconfigured' + is_system_action: + $ref: '#/components/schemas/is_system_action' + name: + type: string + description: The display name for the connector. + referenced_by_count: + $ref: '#/components/schemas/referenced_by_count' + connector_response_properties: + title: Connector response properties + description: The properties vary depending on the connector type. + oneOf: + - $ref: '#/components/schemas/connector_response_properties_bedrock' + - $ref: '#/components/schemas/connector_response_properties_cases_webhook' + - $ref: '#/components/schemas/connector_response_properties_d3security' + - $ref: '#/components/schemas/connector_response_properties_email' + - $ref: '#/components/schemas/connector_response_properties_index' + - $ref: '#/components/schemas/connector_response_properties_jira' + - $ref: '#/components/schemas/connector_response_properties_opsgenie' + - $ref: '#/components/schemas/connector_response_properties_pagerduty' + - $ref: '#/components/schemas/connector_response_properties_resilient' + - $ref: '#/components/schemas/connector_response_properties_serverlog' + - $ref: '#/components/schemas/connector_response_properties_servicenow' + - $ref: '#/components/schemas/connector_response_properties_servicenow_itom' + - $ref: '#/components/schemas/connector_response_properties_servicenow_sir' + - $ref: '#/components/schemas/connector_response_properties_slack_api' + - $ref: '#/components/schemas/connector_response_properties_slack_webhook' + - $ref: '#/components/schemas/connector_response_properties_swimlane' + - $ref: '#/components/schemas/connector_response_properties_teams' + - $ref: '#/components/schemas/connector_response_properties_tines' + - $ref: '#/components/schemas/connector_response_properties_torq' + - $ref: '#/components/schemas/connector_response_properties_webhook' + - $ref: '#/components/schemas/connector_response_properties_xmatters' + discriminator: + propertyName: connector_type_id + update_connector_request_bedrock: + title: Update Amazon Bedrock connector request + type: object + required: + - config + - name + properties: + config: + $ref: '#/components/schemas/config_properties_bedrock' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_bedrock' + update_connector_request_cases_webhook: + title: Update Webhook - Case Managment connector request + type: object + required: + - config + - name + properties: + config: + $ref: '#/components/schemas/config_properties_cases_webhook' + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_cases_webhook' + update_connector_request_d3security: + title: Update D3 Security connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_d3security' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_d3security' + update_connector_request_email: + title: Update email connector request + type: object + required: + - config + - name + properties: + config: + $ref: '#/components/schemas/config_properties_email' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_email' + update_connector_request_index: + title: Update index connector request + type: object + required: + - config + - name + properties: + config: + $ref: '#/components/schemas/config_properties_index' + name: + type: string + description: The display name for the connector. + update_connector_request_jira: + title: Update Jira connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_jira' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_jira' + update_connector_request_opsgenie: + title: Update Opsgenie connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_opsgenie' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_opsgenie' + update_connector_request_pagerduty: + title: Update PagerDuty connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_pagerduty' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_pagerduty' + update_connector_request_resilient: + title: Update IBM Resilient connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_resilient' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_resilient' + update_connector_request_serverlog: + title: Update server log connector request + type: object + required: + - name + properties: + name: + type: string + description: The display name for the connector. + update_connector_request_servicenow: + title: Update ServiceNow ITSM connector or ServiceNow SecOps request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_servicenow' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_servicenow' + update_connector_request_servicenow_itom: + title: Create ServiceNow ITOM connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_servicenow_itom' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_servicenow' + update_connector_request_slack_api: + title: Update Slack connector request + type: object + required: + - name + - secrets + properties: + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_slack_api' + update_connector_request_slack_webhook: + title: Update Slack connector request + type: object + required: + - name + - secrets + properties: + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_slack_webhook' + update_connector_request_swimlane: + title: Update Swimlane connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_swimlane' + name: + type: string + description: The display name for the connector. + example: my-connector + secrets: + $ref: '#/components/schemas/secrets_properties_swimlane' + update_connector_request_teams: + title: Update Microsoft Teams connector request + type: object + required: + - name + - secrets + properties: + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_teams' + update_connector_request_tines: + title: Update Tines connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_tines' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_tines' + update_connector_request_torq: + title: Update Torq connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_torq' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_torq' + update_connector_request_webhook: + title: Update Webhook connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_webhook' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_webhook' + update_connector_request_xmatters: + title: Update xMatters connector request + type: object + required: + - config + - name + - secrets + properties: + config: + $ref: '#/components/schemas/config_properties_xmatters' + name: + type: string + description: The display name for the connector. + secrets: + $ref: '#/components/schemas/secrets_properties_xmatters' + update_connector_request: + title: Update connector request body properties + description: The properties vary depending on the connector type. + oneOf: + - $ref: '#/components/schemas/update_connector_request_bedrock' + - $ref: '#/components/schemas/update_connector_request_cases_webhook' + - $ref: '#/components/schemas/update_connector_request_d3security' + - $ref: '#/components/schemas/update_connector_request_email' + - $ref: '#/components/schemas/create_connector_request_genai' + - $ref: '#/components/schemas/update_connector_request_index' + - $ref: '#/components/schemas/update_connector_request_jira' + - $ref: '#/components/schemas/update_connector_request_opsgenie' + - $ref: '#/components/schemas/update_connector_request_pagerduty' + - $ref: '#/components/schemas/update_connector_request_resilient' + - $ref: '#/components/schemas/update_connector_request_serverlog' + - $ref: '#/components/schemas/update_connector_request_servicenow' + - $ref: '#/components/schemas/update_connector_request_servicenow_itom' + - $ref: '#/components/schemas/update_connector_request_slack_api' + - $ref: '#/components/schemas/update_connector_request_slack_webhook' + - $ref: '#/components/schemas/update_connector_request_swimlane' + - $ref: '#/components/schemas/update_connector_request_teams' + - $ref: '#/components/schemas/update_connector_request_tines' + - $ref: '#/components/schemas/update_connector_request_torq' + - $ref: '#/components/schemas/update_connector_request_webhook' + - $ref: '#/components/schemas/update_connector_request_xmatters' + features: + type: string + description: | + The feature that uses the connector. + enum: + - alerting + - cases + - generativeAI + - siem + - uptime + connector_types: + title: Connector types + type: string + description: The type of connector. For example, `.email`, `.index`, `.jira`, `.opsgenie`, or `.server-log`. + enum: + - .bedrock + - .cases-webhook + - .d3security + - .email + - .gen-ai + - .index + - .jira + - .opsgenie + - .pagerduty + - .resilient + - .servicenow + - .servicenow-itom + - .servicenow-sir + - .server-log + - .slack + - .slack_api + - .swimlane + - .teams + - .tines + - .torq + - .webhook + - .xmatters + example: .server-log + examples: + create_email_connector_request: + summary: Create an email connector. + value: + name: email-connector-1 + connector_type_id: .email + config: + from: tester@example.com + hasAuth: true + host: https://example.com + port: 1025 + secure: false + service: other + secrets: + user: username + password: password + create_index_connector_request: + summary: Create an index connector. + value: + name: my-connector + connector_type_id: .index + config: + index: test-index + create_webhook_connector_request: + summary: Create a webhook connector with SSL authentication. + value: + name: my-webhook-connector + connector_type_id: .webhook + config: + method: post + url: https://example.com + authType: webhook-authentication-ssl + certType: ssl-crt-key + secrets: + crt: QmFnIEF0dH... + key: LS0tLS1CRUdJ... + password: my-passphrase + create_xmatters_connector_request: + summary: Create an xMatters connector with URL authentication. + value: + name: my-xmatters-connector + connector_type_id: .xmatters + config: + usesBasic: false + secrets: + secretsUrl: https://example.com?apiKey=xxxxx + create_email_connector_response: + summary: A new email connector. + value: + id: 90a82c60-478f-11ee-a343-f98a117c727f + connector_type_id: .email + name: email-connector-1 + config: + from: tester@example.com + service: other + host: https://example.com + port: 1025 + secure: false + hasAuth: true + tenantId: null + clientId: null + oauthTokenUrl: null + is_preconfigured: false + is_deprecated: false + is_missing_secrets: false + is_system_action: false + create_index_connector_response: + summary: A new index connector. + value: + id: c55b6eb0-6bad-11eb-9f3b-611eebc6c3ad + connector_type_id: .index + name: my-connector + config: + index: test-index + refresh: false + executionTimeField: null + is_preconfigured: false + is_deprecated: false + is_missing_secrets: false + is_system_action: false + create_webhook_connector_response: + summary: A new webhook connector. + value: + id: 900eb010-3b9d-11ee-a642-8ffbb94e38bd + name: my-webhook-connector + config: + method: post + url: https://example.com + authType: webhook-authentication-ssl + certType: ssl-crt-key + verificationMode: full + headers: null + hasAuth: true + connector_type_id: .webhook + is_preconfigured: false + is_deprecated: false + is_missing_secrets: false + is_system_action: false + create_xmatters_connector_response: + summary: A new xMatters connector. + value: + id: 4d2d8da0-4d1f-11ee-9367-577408be4681 + name: my-xmatters-connector + config: + usesBasic: false + configUrl: null + connector_type_id: .xmatters + is_preconfigured: false + is_deprecated: false + is_missing_secrets: false + is_system_action: false + get_connector_response: + summary: Get connector details. + value: + id: df770e30-8b8b-11ed-a780-3b746c987a81 + name: my_server_log_connector + config: {} + connector_type_id: .server-log + is_preconfigured: false + is_deprecated: false + is_missing_secrets: false + is_system_action: false + update_index_connector_request: + summary: Update an index connector. + value: + name: updated-connector + config: + index: updated-index + get_connectors_response: + summary: A list of connectors + value: + - id: preconfigured-email-connector + name: my-preconfigured-email-notification + connector_type_id: .email + is_preconfigured: true + is_deprecated: false + referenced_by_count: 0 + is_system_action: false + - id: e07d0c80-8b8b-11ed-a780-3b746c987a81 + name: my-index-connector + config: + index: test-index + refresh: false + executionTimeField: null + connector_type_id: .index + is_preconfigured: false + is_deprecated: false + referenced_by_count: 2 + is_missing_secrets: false + is_system_action: false + get_connector_types_generativeai_response: + summary: A list of connector types for the `generativeAI` feature. + value: + - id: .gen-ai + name: OpenAI + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: enterprise + supported_feature_ids: + - generativeAI + is_system_action_type: false + - id: .bedrock + name: AWS Bedrock + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: enterprise + supported_feature_ids: + - generativeAI + is_system_action_type: false + responses: + '401': + description: Authorization information is missing or invalid. + content: + application/json: + schema: + type: object + title: Unauthorized response + properties: + error: + type: string + example: Unauthorized + enum: + - Unauthorized + message: + type: string + statusCode: + type: integer + example: 401 + enum: + - 401 + '404': + description: Object is not found. + content: + application/json: + schema: + type: object + title: Not found response + properties: + error: + type: string + example: Not Found + enum: + - Not Found + message: + type: string + example: Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found + statusCode: + type: integer + example: 404 + enum: + - 404 diff --git a/x-pack/plugins/actions/docs/openapi/components/examples/get_connector_response.yaml b/x-pack/plugins/actions/docs/openapi/components/examples/get_connector_response.yaml index 6de6a030140e6b..0c5ff80fe58842 100644 --- a/x-pack/plugins/actions/docs/openapi/components/examples/get_connector_response.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/examples/get_connector_response.yaml @@ -1,4 +1,4 @@ -summary: A list of connector types +summary: Get connector details. value: id: df770e30-8b8b-11ed-a780-3b746c987a81 name: my_server_log_connector diff --git a/x-pack/plugins/actions/docs/openapi/components/examples/get_connector_types_generativeai_response.yaml b/x-pack/plugins/actions/docs/openapi/components/examples/get_connector_types_generativeai_response.yaml new file mode 100644 index 00000000000000..96eff6e72f2473 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/examples/get_connector_types_generativeai_response.yaml @@ -0,0 +1,20 @@ +summary: A list of connector types for the `generativeAI` feature. +value: + - id: .gen-ai + name: OpenAI + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: enterprise + supported_feature_ids: + - generativeAI + is_system_action_type: false + - id: .bedrock + name: AWS Bedrock + enabled: true + enabled_in_config: true + enabled_in_license: true + minimum_license_required: enterprise + supported_feature_ids: + - generativeAI + is_system_action_type: false diff --git a/x-pack/plugins/actions/docs/openapi/components/responses/400.yaml b/x-pack/plugins/actions/docs/openapi/components/responses/400.yaml new file mode 100644 index 00000000000000..263623dd1fb4cb --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/responses/400.yaml @@ -0,0 +1,15 @@ +description: Indicates a bad request. +content: + application/json: + schema: + type: object + properties: + error: + type: string + example: Bad Request + message: + type: string + example: "error validating action type config: [index]: expected value of type [string] but got [undefined]" + statusCode: + type: integer + example: 400 \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties.yaml index edef270fd75ae5..4b4213b769e3b8 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties.yaml @@ -1,6 +1,7 @@ title: Connector response properties description: The properties vary depending on the connector type. oneOf: + - $ref: 'connector_response_properties_bedrock.yaml' - $ref: 'connector_response_properties_cases_webhook.yaml' - $ref: 'connector_response_properties_d3security.yaml' - $ref: 'connector_response_properties_email.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_cases_webhook.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_cases_webhook.yaml index 70e9a48910c80f..29b746e4d1f67b 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_cases_webhook.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_cases_webhook.yaml @@ -1,7 +1,6 @@ title: Connector request properties for a Webhook - Case Management connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_d3security.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_d3security.yaml index 694b7c011b84a7..e089b079b9077b 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_d3security.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_d3security.yaml @@ -1,7 +1,6 @@ title: Connector response properties for a D3 Security connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_email.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_email.yaml index b84dff4f53106b..cfe6e97fc61a91 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_email.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_email.yaml @@ -1,7 +1,6 @@ title: Connector response properties for an email connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_genai.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_genai.yaml index 928147ed87a695..0d1bbb93f854d5 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_genai.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_genai.yaml @@ -1,7 +1,6 @@ title: Connector response properties for an OpenAI connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_index.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_index.yaml index 5e76416f252108..8e5fe0ba9b8927 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_index.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_index.yaml @@ -1,7 +1,6 @@ title: Connector response properties for an index connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -28,4 +27,6 @@ properties: $ref: 'is_system_action.yaml' name: type: string - description: The display name for the connector. \ No newline at end of file + description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_jira.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_jira.yaml index f61381af963968..b822d82ba10f9b 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_jira.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_jira.yaml @@ -1,7 +1,6 @@ title: Connector response properties for a Jira connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_opsgenie.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_opsgenie.yaml index f44f79f8e7013d..9ac5d91b25c804 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_opsgenie.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_opsgenie.yaml @@ -1,7 +1,6 @@ title: Connector response properties for an Opsgenie connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_pagerduty.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_pagerduty.yaml index 0002e684c2f5ea..f8616900b01d03 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_pagerduty.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_pagerduty.yaml @@ -1,7 +1,6 @@ title: Connector response properties for a PagerDuty connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_resilient.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_resilient.yaml index fc2a239d29a4e1..489e5ab27abfcd 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_resilient.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_resilient.yaml @@ -1,7 +1,6 @@ title: Connector response properties for a IBM Resilient connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_serverlog.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_serverlog.yaml index bd41b62a114c71..a397e668102a64 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_serverlog.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_serverlog.yaml @@ -1,7 +1,6 @@ title: Connector response properties for a server log connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -30,3 +29,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_servicenow.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_servicenow.yaml index 104e7174467a4c..98ac4d3daf31d3 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_servicenow.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_servicenow.yaml @@ -1,7 +1,6 @@ title: Connector response properties for a ServiceNow ITSM connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_servicenow_itom.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_servicenow_itom.yaml index 5651629365bbdd..27cfe9d0dca6a1 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_servicenow_itom.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_servicenow_itom.yaml @@ -1,7 +1,6 @@ title: Connector response properties for a ServiceNow ITOM connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_servicenow_sir.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_servicenow_sir.yaml index 4b24b3c0e7a627..9d5a2b7ab2e2e2 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_servicenow_sir.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_servicenow_sir.yaml @@ -1,7 +1,6 @@ title: Connector response properties for a ServiceNow SecOps connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_slack_api.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_slack_api.yaml index 76510f2511dd2b..56c4f488a35af1 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_slack_api.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_slack_api.yaml @@ -26,3 +26,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_slack_webhook.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_slack_webhook.yaml index 7b0de9d2c27ca7..a9dfd3dc9e857f 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_slack_webhook.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_slack_webhook.yaml @@ -26,3 +26,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_swimlane.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_swimlane.yaml index ea645598de5b71..4c239f21a5db57 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_swimlane.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_swimlane.yaml @@ -1,7 +1,6 @@ title: Connector response properties for a Swimlane connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_teams.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_teams.yaml index 3e0dc777efa98d..939f4014763d92 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_teams.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_teams.yaml @@ -28,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_tines.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_tines.yaml index 1468becee8551d..5fcd24511580f6 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_tines.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_tines.yaml @@ -1,7 +1,6 @@ title: Connector response properties for a Tines connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_torq.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_torq.yaml index 135d5e9db6cb44..b22b6f0a872fc6 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_torq.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_torq.yaml @@ -1,7 +1,6 @@ title: Connector response properties for a Torq connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_webhook.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_webhook.yaml index 8d0dfdac5fbe6d..3469f52c5965de 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_webhook.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_webhook.yaml @@ -1,7 +1,6 @@ title: Connector response properties for a Webhook connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,6 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' + diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_xmatters.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_xmatters.yaml index 3f9e35eba8d6a3..ead2e18149522b 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_xmatters.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/connector_response_properties_xmatters.yaml @@ -1,7 +1,6 @@ title: Connector response properties for an xMatters connector type: object required: - - config - connector_type_id - id - is_deprecated @@ -29,3 +28,5 @@ properties: name: type: string description: The display name for the connector. + referenced_by_count: + $ref: 'referenced_by_count.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request.yaml new file mode 100644 index 00000000000000..3bcf6cc0c3ccb8 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/create_connector_request.yaml @@ -0,0 +1,28 @@ +title: Create connector request body properties +description: The properties vary depending on the connector type. +oneOf: + - $ref: 'create_connector_request_bedrock.yaml' + - $ref: 'create_connector_request_cases_webhook.yaml' + - $ref: 'create_connector_request_d3security.yaml' + - $ref: 'create_connector_request_email.yaml' + - $ref: 'create_connector_request_genai.yaml' + - $ref: 'create_connector_request_index.yaml' + - $ref: 'create_connector_request_jira.yaml' + - $ref: 'create_connector_request_opsgenie.yaml' + - $ref: 'create_connector_request_pagerduty.yaml' + - $ref: 'create_connector_request_resilient.yaml' + - $ref: 'create_connector_request_serverlog.yaml' + - $ref: 'create_connector_request_servicenow.yaml' + - $ref: 'create_connector_request_servicenow_itom.yaml' + - $ref: 'create_connector_request_servicenow_sir.yaml' + - $ref: 'create_connector_request_slack_api.yaml' + - $ref: 'create_connector_request_slack_webhook.yaml' + - $ref: 'create_connector_request_swimlane.yaml' + - $ref: 'create_connector_request_teams.yaml' + - $ref: 'create_connector_request_tines.yaml' + - $ref: 'create_connector_request_torq.yaml' + - $ref: 'create_connector_request_webhook.yaml' + - $ref: 'create_connector_request_xmatters.yaml' +discriminator: + propertyName: connector_type_id + \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/features.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/features.yaml index 059e91cd79c7e7..e75b745957552a 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/features.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/features.yaml @@ -1,8 +1,9 @@ type: string description: > - The feature that uses the connector. Valid values are `alerting`, `cases`, `uptime`, and `siem`. + The feature that uses the connector. enum: - alerting - cases - - uptime - - siem \ No newline at end of file + - generativeAI + - siem + - uptime \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/is_preconfigured.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/is_preconfigured.yaml index 11991d878721ad..e38741c83718eb 100644 --- a/x-pack/plugins/actions/docs/openapi/components/schemas/is_preconfigured.yaml +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/is_preconfigured.yaml @@ -1,3 +1,5 @@ type: boolean -description: Indicates whether it is a preconfigured connector. If true, the `config` and `is_missing_secrets` properties are omitted from the response. +description: > + Indicates whether it is a preconfigured connector. + If true, the `config` and `is_missing_secrets` properties are omitted from the response. example: false \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/referenced_by_count.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/referenced_by_count.yaml new file mode 100644 index 00000000000000..61579fa3dc6ce3 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/referenced_by_count.yaml @@ -0,0 +1,6 @@ +type: integer +description: > + Indicates the number of saved objects that reference the connector. + If `is_preconfigured` is true, this value is not calculated. + This property is returned only by the get all connectors API. +example: 2 \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_request.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_request.yaml new file mode 100644 index 00000000000000..a313de571b501b --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/run_connector_request.yaml @@ -0,0 +1,26 @@ +title: Run connector request body properties +description: The properties vary depending on the connector type. +type: object +required: + - params +properties: + params: + oneOf: + - $ref: 'run_connector_params_documents.yaml' + - $ref: 'run_connector_params_level_message.yaml' + - title: Subaction parameters + description: Test an action that involves a subaction. + oneOf: + - $ref: 'run_connector_subaction_addevent.yaml' + - $ref: 'run_connector_subaction_closealert.yaml' + - $ref: 'run_connector_subaction_createalert.yaml' + - $ref: 'run_connector_subaction_fieldsbyissuetype.yaml' + - $ref: 'run_connector_subaction_getchoices.yaml' + - $ref: 'run_connector_subaction_getfields.yaml' + - $ref: 'run_connector_subaction_getincident.yaml' + - $ref: 'run_connector_subaction_issue.yaml' + - $ref: 'run_connector_subaction_issues.yaml' + - $ref: 'run_connector_subaction_issuetypes.yaml' + - $ref: 'run_connector_subaction_pushtoservice.yaml' + discriminator: + propertyName: subAction \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request.yaml b/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request.yaml new file mode 100644 index 00000000000000..269cd798472772 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/components/schemas/update_connector_request.yaml @@ -0,0 +1,24 @@ +title: Update connector request body properties +description: The properties vary depending on the connector type. +oneOf: + - $ref: 'update_connector_request_bedrock.yaml' + - $ref: 'update_connector_request_cases_webhook.yaml' + - $ref: 'update_connector_request_d3security.yaml' + - $ref: 'update_connector_request_email.yaml' + - $ref: 'create_connector_request_genai.yaml' + - $ref: 'update_connector_request_index.yaml' + - $ref: 'update_connector_request_jira.yaml' + - $ref: 'update_connector_request_opsgenie.yaml' + - $ref: 'update_connector_request_pagerduty.yaml' + - $ref: 'update_connector_request_resilient.yaml' + - $ref: 'update_connector_request_serverlog.yaml' + - $ref: 'update_connector_request_servicenow.yaml' + - $ref: 'update_connector_request_servicenow_itom.yaml' + - $ref: 'update_connector_request_slack_api.yaml' + - $ref: 'update_connector_request_slack_webhook.yaml' + - $ref: 'update_connector_request_swimlane.yaml' + - $ref: 'update_connector_request_teams.yaml' + - $ref: 'update_connector_request_tines.yaml' + - $ref: 'update_connector_request_torq.yaml' + - $ref: 'update_connector_request_webhook.yaml' + - $ref: 'update_connector_request_xmatters.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/entrypoint.yaml b/x-pack/plugins/actions/docs/openapi/entrypoint.yaml index 04e844607f8272..1f85d4a44c37b6 100644 --- a/x-pack/plugins/actions/docs/openapi/entrypoint.yaml +++ b/x-pack/plugins/actions/docs/openapi/entrypoint.yaml @@ -15,24 +15,34 @@ servers: - url: 'http://localhost:5601' description: local paths: - '/s/{spaceId}/api/actions/connector': + '/api/actions/connector': + $ref: 'paths/api@actions@connector.yaml' + '/api/actions/connector/{connectorId}': + $ref: 'paths/api@actions@connector@{connectorid}.yaml' + '/api/actions/connector/{connectorId}/_execute': + $ref: paths/api@actions@connector@{connectorid}@_execute.yaml + '/api/actions/connectors': + $ref: paths/api@actions@connectors.yaml + '/api/actions/connector_types': + $ref: paths/api@actions@connector_types.yaml + '/s/{spaceId}/api/actions/connector': $ref: 'paths/s@{spaceid}@api@actions@connector.yaml' - '/s/{spaceId}/api/actions/connector/{connectorId}': + '/s/{spaceId}/api/actions/connector/{connectorId}': $ref: 'paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml' - '/s/{spaceId}/api/actions/connectors': + '/s/{spaceId}/api/actions/connectors': $ref: paths/s@{spaceid}@api@actions@connectors.yaml - '/s/{spaceId}/api/actions/connector_types': + '/s/{spaceId}/api/actions/connector_types': $ref: paths/s@{spaceid}@api@actions@connector_types.yaml - '/s/{spaceId}/api/actions/connector/{connectorId}/_execute': + '/s/{spaceId}/api/actions/connector/{connectorId}/_execute': $ref: paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml # Deprecated endpoints: - '/s/{spaceId}/api/actions/action/{actionId}': + '/s/{spaceId}/api/actions/action/{actionId}': $ref: 'paths/s@{spaceid}@api@actions@action@{actionid}.yaml' - '/s/{spaceId}/api/actions': + '/s/{spaceId}/api/actions': $ref: 'paths/s@{spaceid}@api@actions.yaml' - '/s/{spaceId}/api/actions/list_action_types': + '/s/{spaceId}/api/actions/list_action_types': $ref: 'paths/s@{spaceid}@api@actions@list_action_types.yaml' - '/s/{spaceId}/api/actions/action/{actionId}/_execute': + '/s/{spaceId}/api/actions/action/{actionId}/_execute': $ref: 'paths/s@{spaceid}@api@actions@action@{actionid}@_execute.yaml' components: securitySchemes: diff --git a/x-pack/plugins/actions/docs/openapi/entrypoint_serverless.yaml b/x-pack/plugins/actions/docs/openapi/entrypoint_serverless.yaml new file mode 100644 index 00000000000000..1cfccf790903aa --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/entrypoint_serverless.yaml @@ -0,0 +1,33 @@ +openapi: 3.0.1 +info: + title: Connectors + description: OpenAPI schema for connectors in Serverless projects + version: '0.1' + contact: + name: Connectors Team + license: + name: Elastic License 2.0 + url: https://www.elastic.co/licensing/elastic-license +tags: + - name: connectors + description: Connector APIs enable you to create and manage connectors. +servers: + - url: 'http://localhost:5601' + description: local +paths: + '/api/actions/connector': + $ref: 'paths/api@actions@connector.yaml' + '/api/actions/connector/{connectorId}': + $ref: 'paths/api@actions@connector@{connectorid}.yaml' + '/api/actions/connectors': + $ref: paths/api@actions@connectors.yaml + '/api/actions/connector_types': + $ref: paths/api@actions@connector_types.yaml +components: + securitySchemes: + apiKeyAuth: + type: apiKey + in: header + name: ApiKey +security: + - apiKeyAuth: [] diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector.yaml new file mode 100644 index 00000000000000..9c5e69a53e24f0 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector.yaml @@ -0,0 +1,44 @@ +post: + summary: Creates a connector. + operationId: createConnector + tags: + - connectors + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + requestBody: + required: true + content: + application/json: + schema: + $ref: '../components/schemas/create_connector_request.yaml' + examples: + createEmailConnectorRequest: + $ref: '../components/examples/create_email_connector_request.yaml' + createIndexConnectorRequest: + $ref: '../components/examples/create_index_connector_request.yaml' + createWebhookConnectorRequest: + $ref: '../components/examples/create_webhook_connector_request.yaml' + createXmattersConnectorRequest: + $ref: '../components/examples/create_xmatters_connector_request.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '../components/schemas/connector_response_properties.yaml' + examples: + createEmailConnectorResponse: + $ref: '../components/examples/create_email_connector_response.yaml' + createIndexConnectorResponse: + $ref: '../components/examples/create_index_connector_response.yaml' + createWebhookConnectorResponse: + $ref: '../components/examples/create_webhook_connector_response.yaml' + createXmattersConnectorResponse: + $ref: '../components/examples/create_xmatters_connector_response.yaml' + '401': + $ref: '../components/responses/401.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}.yaml new file mode 100644 index 00000000000000..f9f483f7476357 --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}.yaml @@ -0,0 +1,116 @@ +get: + summary: Retrieves a connector by ID. + operationId: getConnector + tags: + - connectors + parameters: + - $ref: '../components/parameters/connector_id.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '../components/schemas/connector_response_properties.yaml' + examples: + getConnectorResponse: + $ref: '../components/examples/get_connector_response.yaml' + '401': + $ref: '../components/responses/401.yaml' + '404': + $ref: '../components/responses/404.yaml' + servers: + - url: https://localhost:5601 + +delete: + summary: Deletes a connector. + operationId: deleteConnector + tags: + - connectors + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - $ref: '../components/parameters/connector_id.yaml' + responses: + '204': + description: Indicates a successful call. + '401': + $ref: '../components/responses/401.yaml' + '404': + $ref: '../components/responses/404.yaml' + servers: + - url: https://localhost:5601 + +post: + summary: Creates a connector. + operationId: createConnectorId + tags: + - connectors + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - in: path + name: connectorId + description: > + A UUID v1 or v4 identifier for the connector. + If you omit this parameter, an identifier is randomly generated. + required: true + schema: + type: string + example: ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 + requestBody: + required: true + content: + application/json: + schema: + $ref: '../components/schemas/create_connector_request.yaml' + examples: + createIndexConnectorRequest: + $ref: '../components/examples/create_index_connector_request.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '../components/schemas/connector_response_properties.yaml' + examples: + createIndexConnectorResponse: + $ref: '../components/examples/create_index_connector_response.yaml' + '401': + $ref: '../components/responses/401.yaml' + servers: + - url: https://localhost:5601 + +put: + summary: Updates the attributes for a connector. + operationId: updateConnector + tags: + - connectors + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - $ref: '../components/parameters/connector_id.yaml' + requestBody: + required: true + content: + application/json: + schema: + $ref: '../components/schemas/update_connector_request.yaml' + examples: + updateIndexConnectorRequest: + $ref: '../components/examples/update_index_connector_request.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + $ref: '../components/schemas/connector_response_properties.yaml' + '400': + $ref: '../components/responses/401.yaml' + '401': + $ref: '../components/responses/401.yaml' + '404': + $ref: '../components/responses/404.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}@_execute.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}@_execute.yaml new file mode 100644 index 00000000000000..a876584ca4e8ef --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}@_execute.yaml @@ -0,0 +1,75 @@ +post: + summary: Runs a connector. + operationId: runConnector + description: > + You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. + You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. + If you use an index connector, you must also have `all`, `create`, `index`, or `write` indices privileges. + tags: + - connectors + parameters: + - $ref: '../components/headers/kbn_xsrf.yaml' + - $ref: '../components/parameters/connector_id.yaml' + requestBody: + required: true + content: + application/json: + schema: + $ref: '../components/schemas/run_connector_request.yaml' + examples: + runIndexConnectorRequest: + $ref: '../components/examples/run_index_connector_request.yaml' + runJiraConnectorRequest: + $ref: '../components/examples/run_jira_connector_request.yaml' + runServerLogConnectorRequest: + $ref: '../components/examples/run_server_log_connector_request.yaml' + runServiceNowITOMConnectorRequest: + $ref: '../components/examples/run_servicenow_itom_connector_request.yaml' + runSwimlaneConnectorRequest: + $ref: '../components/examples/run_swimlane_connector_request.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: object + required: + - connector_id + - status + properties: + connector_id: + type: string + description: The identifier for the connector. + data: + oneOf: + - type: object + description: Information returned from the action. + additionalProperties: true + - type: array + description: An array of information returned from the action. + items: + type: object + status: + type: string + description: The status of the action. + enum: + - error + - ok + examples: + runIndexConnectorResponse: + $ref: '../components/examples/run_index_connector_response.yaml' + runJiraConnectorResponse: + $ref: '../components/examples/run_jira_connector_response.yaml' + runServerLogConnectorResponse: + $ref: '../components/examples/run_server_log_connector_response.yaml' + runServiceNowITOMConnectorResponse: + $ref: '../components/examples/run_servicenow_itom_connector_response.yaml' + runSwimlaneConnectorResponse: + $ref: '../components/examples/run_swimlane_connector_response.yaml' + '401': + $ref: '../components/responses/401.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector_types.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector_types.yaml new file mode 100644 index 00000000000000..30247d47b24c9b --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector_types.yaml @@ -0,0 +1,66 @@ +get: + summary: Retrieves a list of all connector types. + operationId: getConnectorTypes + tags: + - connectors + parameters: + - in: query + name: feature_id + description: A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases). + schema: + $ref: '../components/schemas/features.yaml' + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + title: Get connector types response body properties + description: The properties vary for each connector type. + type: array + items: + type: object + properties: + enabled: + type: boolean + description: Indicates whether the connector type is enabled in Kibana. + example: true + enabled_in_config: + type: boolean + description: Indicates whether the connector type is enabled in the Kibana configuration file. + example: true + enabled_in_license: + type: boolean + description: Indicates whether the connector is enabled in the license. + example: true + id: + $ref: '../components/schemas/connector_types.yaml' + is_system_action_type: + type: boolean + example: false + minimum_license_required: + type: string + description: The license that is required to use the connector type. + example: basic + name: + type: string + description: The name of the connector type. + example: Index + supported_feature_ids: + type: array + description: The features that are supported by the connector type. + items: + $ref: '../components/schemas/features.yaml' + example: + - alerting + - cases + - siem + examples: + getConnectorTypesServerlessResponse: + $ref: '../components/examples/get_connector_types_generativeai_response.yaml' + '401': + $ref: '../components/responses/401.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connectors.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connectors.yaml new file mode 100644 index 00000000000000..b350251dde206a --- /dev/null +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connectors.yaml @@ -0,0 +1,23 @@ +get: + summary: Retrieves all connectors. + operationId: getConnectors + tags: + - connectors + responses: + '200': + description: Indicates a successful call. + content: + application/json: + schema: + type: array + items: + $ref: '../components/schemas/connector_response_properties.yaml' + examples: + getConnectorsResponse: + $ref: '../components/examples/get_connectors_response.yaml' + '401': + $ref: '../components/responses/401.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml index 64712858fa8a09..86e8cc1d0bfe0f 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector.yaml @@ -1,6 +1,6 @@ post: summary: Creates a connector. - operationId: createConnector + operationId: createConnectorWithSpaceId description: > You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: @@ -13,33 +13,7 @@ post: content: application/json: schema: - title: Create connector request body properties - description: The properties vary depending on the connector type. - oneOf: - - $ref: '../components/schemas/create_connector_request_bedrock.yaml' - - $ref: '../components/schemas/create_connector_request_cases_webhook.yaml' - - $ref: '../components/schemas/create_connector_request_d3security.yaml' - - $ref: '../components/schemas/create_connector_request_email.yaml' - - $ref: '../components/schemas/create_connector_request_genai.yaml' - - $ref: '../components/schemas/create_connector_request_index.yaml' - - $ref: '../components/schemas/create_connector_request_jira.yaml' - - $ref: '../components/schemas/create_connector_request_opsgenie.yaml' - - $ref: '../components/schemas/create_connector_request_pagerduty.yaml' - - $ref: '../components/schemas/create_connector_request_resilient.yaml' - - $ref: '../components/schemas/create_connector_request_serverlog.yaml' - - $ref: '../components/schemas/create_connector_request_servicenow.yaml' - - $ref: '../components/schemas/create_connector_request_servicenow_itom.yaml' - - $ref: '../components/schemas/create_connector_request_servicenow_sir.yaml' - - $ref: '../components/schemas/create_connector_request_slack_api.yaml' - - $ref: '../components/schemas/create_connector_request_slack_webhook.yaml' - - $ref: '../components/schemas/create_connector_request_swimlane.yaml' - - $ref: '../components/schemas/create_connector_request_teams.yaml' - - $ref: '../components/schemas/create_connector_request_tines.yaml' - - $ref: '../components/schemas/create_connector_request_torq.yaml' - - $ref: '../components/schemas/create_connector_request_webhook.yaml' - - $ref: '../components/schemas/create_connector_request_xmatters.yaml' - discriminator: - propertyName: connector_type_id + $ref: '../components/schemas/create_connector_request.yaml' examples: createEmailConnectorRequest: $ref: '../components/examples/create_email_connector_request.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml index 7c1d402efaca49..0edbd0a0ed2d1a 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml @@ -1,6 +1,6 @@ get: summary: Retrieves a connector by ID. - operationId: getConnector + operationId: getConnectorWithSpaceId description: > You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: @@ -21,27 +21,13 @@ get: '401': $ref: '../components/responses/401.yaml' '404': - description: Object is not found. - content: - application/json: - schema: - type: object - properties: - error: - type: string - example: Not Found - message: - type: string - example: "Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found" - statusCode: - type: integer - example: 404 + $ref: '../components/responses/404.yaml' servers: - url: https://localhost:5601 delete: summary: Deletes a connector. - operationId: deleteConnector + operationId: deleteConnectorWithSpaceId description: > You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. WARNING: When you delete a connector, it cannot be recovered. @@ -57,27 +43,13 @@ delete: '401': $ref: '../components/responses/401.yaml' '404': - description: Object is not found. - content: - application/json: - schema: - type: object - properties: - error: - type: string - example: Not Found - message: - type: string - example: "Saved object [action/baf33fc0-920c-11ed-b36a-874bd1548a00] not found" - statusCode: - type: integer - example: 404 + $ref: '../components/responses/404.yaml' servers: - url: https://localhost:5601 post: summary: Creates a connector. - operationId: createConnectorId + operationId: createConnectorIdWithSpaceId description: > You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: @@ -97,33 +69,7 @@ post: content: application/json: schema: - title: Create connector request body properties - description: The properties vary depending on the connector type. - oneOf: - - $ref: '../components/schemas/create_connector_request_bedrock.yaml' - - $ref: '../components/schemas/create_connector_request_cases_webhook.yaml' - - $ref: '../components/schemas/create_connector_request_d3security.yaml' - - $ref: '../components/schemas/create_connector_request_email.yaml' - - $ref: '../components/schemas/create_connector_request_genai.yaml' - - $ref: '../components/schemas/create_connector_request_index.yaml' - - $ref: '../components/schemas/create_connector_request_jira.yaml' - - $ref: '../components/schemas/create_connector_request_opsgenie.yaml' - - $ref: '../components/schemas/create_connector_request_pagerduty.yaml' - - $ref: '../components/schemas/create_connector_request_resilient.yaml' - - $ref: '../components/schemas/create_connector_request_serverlog.yaml' - - $ref: '../components/schemas/create_connector_request_servicenow.yaml' - - $ref: '../components/schemas/create_connector_request_servicenow_itom.yaml' - - $ref: '../components/schemas/create_connector_request_servicenow_sir.yaml' - - $ref: '../components/schemas/create_connector_request_slack_api.yaml' - - $ref: '../components/schemas/create_connector_request_slack_webhook.yaml' - - $ref: '../components/schemas/create_connector_request_swimlane.yaml' - - $ref: '../components/schemas/create_connector_request_teams.yaml' - - $ref: '../components/schemas/create_connector_request_tines.yaml' - - $ref: '../components/schemas/create_connector_request_torq.yaml' - - $ref: '../components/schemas/create_connector_request_webhook.yaml' - - $ref: '../components/schemas/create_connector_request_xmatters.yaml' - discriminator: - propertyName: connector_type_id + $ref: '../components/schemas/create_connector_request.yaml' examples: createIndexConnectorRequest: $ref: '../components/examples/create_index_connector_request.yaml' @@ -144,7 +90,7 @@ post: put: summary: Updates the attributes for a connector. - operationId: updateConnector + operationId: updateConnectorWithSpaceId description: > You must have `all` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: @@ -158,30 +104,7 @@ put: content: application/json: schema: - title: Update connector request body properties - description: The properties vary depending on the connector type. - oneOf: - - $ref: '../components/schemas/create_connector_request_bedrock.yaml' - - $ref: '../components/schemas/update_connector_request_cases_webhook.yaml' - - $ref: '../components/schemas/update_connector_request_d3security.yaml' - - $ref: '../components/schemas/update_connector_request_email.yaml' - - $ref: '../components/schemas/create_connector_request_genai.yaml' - - $ref: '../components/schemas/update_connector_request_index.yaml' - - $ref: '../components/schemas/update_connector_request_jira.yaml' - - $ref: '../components/schemas/update_connector_request_opsgenie.yaml' - - $ref: '../components/schemas/update_connector_request_pagerduty.yaml' - - $ref: '../components/schemas/update_connector_request_resilient.yaml' - - $ref: '../components/schemas/update_connector_request_serverlog.yaml' - - $ref: '../components/schemas/update_connector_request_servicenow.yaml' - - $ref: '../components/schemas/update_connector_request_servicenow_itom.yaml' - - $ref: '../components/schemas/update_connector_request_slack_api.yaml' - - $ref: '../components/schemas/update_connector_request_slack_webhook.yaml' - - $ref: '../components/schemas/update_connector_request_swimlane.yaml' - - $ref: '../components/schemas/update_connector_request_teams.yaml' - - $ref: '../components/schemas/update_connector_request_tines.yaml' - - $ref: '../components/schemas/update_connector_request_torq.yaml' - - $ref: '../components/schemas/update_connector_request_webhook.yaml' - - $ref: '../components/schemas/update_connector_request_xmatters.yaml' + $ref: '../components/schemas/update_connector_request.yaml' examples: updateIndexConnectorRequest: $ref: '../components/examples/update_index_connector_request.yaml' @@ -193,21 +116,7 @@ put: schema: $ref: '../components/schemas/connector_response_properties.yaml' '400': - description: Indicates a bad request. - content: - application/json: - schema: - type: object - properties: - error: - type: string - example: Bad Request - message: - type: string - example: "error validating action type config: [index]: expected value of type [string] but got [undefined]" - statusCode: - type: integer - example: 400 + $ref: '../components/responses/401.yaml' '401': $ref: '../components/responses/401.yaml' '404': diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml index 9301b563bd9587..f94419bcae81d8 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml @@ -1,6 +1,6 @@ post: summary: Runs a connector. - operationId: runConnector + operationId: runConnectorWithSpaceId description: > You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. @@ -16,32 +16,7 @@ post: content: application/json: schema: - title: Run connector request body properties - description: The properties vary depending on the connector type. - type: object - required: - - params - properties: - params: - oneOf: - - $ref: '../components/schemas/run_connector_params_documents.yaml' - - $ref: '../components/schemas/run_connector_params_level_message.yaml' - - title: Subaction parameters - description: Test an action that involves a subaction. - oneOf: - - $ref: '../components/schemas/run_connector_subaction_addevent.yaml' - - $ref: '../components/schemas/run_connector_subaction_closealert.yaml' - - $ref: '../components/schemas/run_connector_subaction_createalert.yaml' - - $ref: '../components/schemas/run_connector_subaction_fieldsbyissuetype.yaml' - - $ref: '../components/schemas/run_connector_subaction_getchoices.yaml' - - $ref: '../components/schemas/run_connector_subaction_getfields.yaml' - - $ref: '../components/schemas/run_connector_subaction_getincident.yaml' - - $ref: '../components/schemas/run_connector_subaction_issue.yaml' - - $ref: '../components/schemas/run_connector_subaction_issues.yaml' - - $ref: '../components/schemas/run_connector_subaction_issuetypes.yaml' - - $ref: '../components/schemas/run_connector_subaction_pushtoservice.yaml' - discriminator: - propertyName: subAction + $ref: '../components/schemas/run_connector_request.yaml' examples: runIndexConnectorRequest: $ref: '../components/examples/run_index_connector_request.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector_types.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector_types.yaml index c1001023067478..1dfdfe775a2928 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector_types.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector_types.yaml @@ -1,6 +1,6 @@ get: summary: Retrieves a list of all connector types. - operationId: getConnectorTypes + operationId: getConnectorTypesWithSpaceId description: > You do not need any Kibana feature privileges to run this API. tags: diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connectors.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connectors.yaml index caec98d7bf5e3c..7f5d5944ba520e 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connectors.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connectors.yaml @@ -1,6 +1,6 @@ get: summary: Retrieves all connectors. - operationId: getConnectors + operationId: getConnectorsWithSpaceId description: > You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: @@ -15,45 +15,7 @@ get: schema: type: array items: - title: Get connectors response body properties - description: The properties vary for each connector type. - type: object - required: - - connector_type_id - - id - - is_deprecated - - is_preconfigured - - name - - referenced_by_count - properties: - connector_type_id: - $ref: '../components/schemas/connector_types.yaml' - config: - type: object - description: The configuration for the connector. Configuration properties vary depending on the connector type. - additionalProperties: true - nullable: true - id: - type: string - description: The identifier for the connector. - example: b0766e10-d190-11ec-b04c-776c77d14fca - is_deprecated: - $ref: '../components/schemas/is_deprecated.yaml' - is_missing_secrets: - $ref: '../components/schemas/is_missing_secrets.yaml' - is_preconfigured: - $ref: '../components/schemas/is_preconfigured.yaml' - is_system_action: - $ref: '../components/schemas/is_system_action.yaml' - name: - type: string - description: The display name for the connector. - example: my-connector - referenced_by_count: - type: integer - description: Indicates the number of saved objects that reference the connector. If `is_preconfigured` is true, this value is not calculated. - example: 2 - default: 0 + $ref: '../components/schemas/connector_response_properties.yaml' examples: getConnectorsResponse: $ref: '../components/examples/get_connectors_response.yaml' From 382e3f6ec245aec89d52b4a4be1b8c5612c011c5 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 17 Oct 2023 07:49:23 -0700 Subject: [PATCH 67/87] [DOCS] Remove OAS API previews (#168761) --- docs/api-generated/README.md | 42 - .../cases/case-apis-passthru.asciidoc | 5511 ----------------- docs/api-generated/cases/case-apis.asciidoc | 10 - .../connector-apis-passthru.asciidoc | 2823 --------- .../connectors/connector-apis.asciidoc | 10 - .../ml-apis-passthru.asciidoc | 205 - .../machine-learning/ml-apis.asciidoc | 10 - .../rules/rule-apis-passthru.asciidoc | 4905 --------------- docs/api-generated/rules/rule-apis.asciidoc | 10 - docs/api-generated/template/index.mustache | 170 - .../actions-and-connectors/create.asciidoc | 2 +- .../actions-and-connectors/delete.asciidoc | 2 +- .../actions-and-connectors/execute.asciidoc | 2 +- docs/api/actions-and-connectors/get.asciidoc | 2 +- .../actions-and-connectors/get_all.asciidoc | 2 +- docs/api/actions-and-connectors/list.asciidoc | 2 +- .../actions-and-connectors/update.asciidoc | 2 +- docs/api/alerting/create_rule.asciidoc | 2 +- docs/api/alerting/delete_rule.asciidoc | 2 +- docs/api/alerting/disable_rule.asciidoc | 2 +- docs/api/alerting/enable_rule.asciidoc | 2 +- docs/api/alerting/find_rules.asciidoc | 2 +- docs/api/alerting/get_rules.asciidoc | 2 +- docs/api/alerting/health.asciidoc | 2 +- docs/api/alerting/list_rule_types.asciidoc | 2 +- docs/api/alerting/mute_alert.asciidoc | 2 +- docs/api/alerting/mute_all_alerts.asciidoc | 2 +- docs/api/alerting/unmute_alert.asciidoc | 2 +- docs/api/alerting/unmute_all_alerts.asciidoc | 2 +- docs/api/alerting/update_rule.asciidoc | 2 +- docs/api/cases/cases-api-add-comment.asciidoc | 2 +- docs/api/cases/cases-api-create.asciidoc | 2 +- .../api/cases/cases-api-delete-cases.asciidoc | 2 +- .../cases/cases-api-delete-comments.asciidoc | 2 +- .../cases-api-find-case-activity.asciidoc | 2 +- docs/api/cases/cases-api-find-cases.asciidoc | 2 +- .../cases/cases-api-find-connectors.asciidoc | 2 +- docs/api/cases/cases-api-get-alerts.asciidoc | 2 +- .../cases-api-get-case-activity.asciidoc | 2 +- docs/api/cases/cases-api-get-case.asciidoc | 2 +- .../cases-api-get-cases-by-alert.asciidoc | 2 +- .../api/cases/cases-api-get-comments.asciidoc | 2 +- .../cases-api-get-configuration.asciidoc | 2 +- .../cases/cases-api-get-reporters.asciidoc | 2 +- docs/api/cases/cases-api-get-status.asciidoc | 2 +- docs/api/cases/cases-api-get-tags.asciidoc | 2 +- docs/api/cases/cases-api-push.asciidoc | 2 +- .../cases-api-set-configuration.asciidoc | 2 +- .../cases/cases-api-update-comment.asciidoc | 2 +- .../cases-api-update-configuration.asciidoc | 2 +- docs/api/cases/cases-api-update.asciidoc | 2 +- docs/api/machine-learning/sync.asciidoc | 2 +- docs/apis.asciidoc | 17 - docs/index.asciidoc | 2 - docs/redirects.asciidoc | 8 +- 55 files changed, 49 insertions(+), 13758 deletions(-) delete mode 100644 docs/api-generated/README.md delete mode 100644 docs/api-generated/cases/case-apis-passthru.asciidoc delete mode 100644 docs/api-generated/cases/case-apis.asciidoc delete mode 100644 docs/api-generated/connectors/connector-apis-passthru.asciidoc delete mode 100644 docs/api-generated/connectors/connector-apis.asciidoc delete mode 100644 docs/api-generated/machine-learning/ml-apis-passthru.asciidoc delete mode 100644 docs/api-generated/machine-learning/ml-apis.asciidoc delete mode 100644 docs/api-generated/rules/rule-apis-passthru.asciidoc delete mode 100644 docs/api-generated/rules/rule-apis.asciidoc delete mode 100644 docs/api-generated/template/index.mustache delete mode 100644 docs/apis.asciidoc diff --git a/docs/api-generated/README.md b/docs/api-generated/README.md deleted file mode 100644 index 97fd32119b8bc8..00000000000000 --- a/docs/api-generated/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# OpenAPI (Experimental) - -Open API specifications (OAS) exist in JSON or YAML format for some Kibana features, -though they are experimental and may be incomplete or change later. - -A preview of the API specifications can be added to the Kibana Guide by using -the following process: - -. Install [OpenAPI Generator](https://openapi-generator.tech/docs/installation), -or a similar tool that can generate HTML output from OAS. - -. Optionally validate the specifications by using the commands listed in the appropriate readmes. - -. Generate HTML output. For example: - - ``` - openapi-generator-cli generate -g html -i $GIT_HOME/kibana/x-pack/plugins/alerting/docs/openapi/bundled.yaml -o $GIT_HOME/kibana/docs/api-generated/rules -t $GIT_HOME/kibana/docs/api-generated/template - - openapi-generator-cli generate -g html -i $GIT_HOME/kibana/x-pack/plugins/cases/docs/openapi/bundled.yaml -o $GIT_HOME/kibana/docs/api-generated/cases -t $GIT_HOME/kibana/docs/api-generated/template - - openapi-generator-cli generate -g html -i $GIT_HOME/kibana/x-pack/plugins/actions/docs/openapi/bundled.yaml -o $GIT_HOME/kibana/docs/api-generated/connectors -t $GIT_HOME/kibana/docs/api-generated/template - - openapi-generator-cli generate -g html -i $GIT_HOME/kibana/x-pack/plugins/ml/common/openapi/ml_apis_v3.yaml -o $GIT_HOME/kibana/docs/api-generated/machine-learning -t $GIT_HOME/kibana/docs/api-generated/template - ``` - -. Rename the output files. For example: - ``` - mv $GIT_HOME/kibana/docs/api-generated/rules/index.html $GIT_HOME/kibana/docs/api-generated/rules/rule-apis-passthru.asciidoc - mv $GIT_HOME/kibana/docs/api-generated/cases/index.html $GIT_HOME/kibana/docs/api-generated/cases/case-apis-passthru.asciidoc - mv $GIT_HOME/kibana/docs/api-generated/connectors/index.html $GIT_HOME/kibana/docs/api-generated/connectors/connector-apis-passthru.asciidoc - mv $GIT_HOME/kibana/docs/api-generated/machine-learning/index.html $GIT_HOME/kibana/docs/api-generated/machine-learning/ml-apis-passthru.asciidoc - ``` - -. If you're creating a new set of API output, you will need to have a page that incorporates the output by using passthrough blocks. For more information, refer to [Asciidoctor docs](https://docs.asciidoctor.org/asciidoc/latest/pass/pass-block/) - -. Verify the output by building the Kibana documentation. At this time, the output is added as a technical preview in the appendix. - -## Known issues - -- Some OAS 3.0 features such as `anyOf`, `oneOf`, and `allOf` might not display properly in the preview. These are on the [Short-term roadmap](https://openapi-generator.tech/docs/roadmap/) at this time. - - diff --git a/docs/api-generated/cases/case-apis-passthru.asciidoc b/docs/api-generated/cases/case-apis-passthru.asciidoc deleted file mode 100644 index eb354b320d899c..00000000000000 --- a/docs/api-generated/cases/case-apis-passthru.asciidoc +++ /dev/null @@ -1,5511 +0,0 @@ -//// -This content is generated from the open API specification. -Any modifications made to this file will be overwritten. -//// - -++++ -
-

Access

-
    -
  1. APIKey KeyParamName:ApiKey KeyInQuery:false KeyInHeader:true
  2. -
  3. HTTP Basic Authentication
  4. -
- -

Methods

- [ Jump to Models ] - -

Table of Contents

-
-

Cases

- - -

Cases

-
-
- Up -
post /s/{spaceId}/api/cases/{caseId}/comments
-
Adds a comment or alert to a case. (addCaseComment)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're creating. NOTE: Each case can have a maximum of 1,000 alerts.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
add_case_comment_request add_case_comment_request (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
post /api/cases/{caseId}/comments
-
Adds a comment or alert to a case in the default space. (addCaseCommentDefaultSpace)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're creating. NOTE: Each case can have a maximum of 1,000 alerts.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
add_case_comment_request add_case_comment_request (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
post /s/{spaceId}/api/cases
-
Creates a case. (createCase)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're creating.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
create_case_request create_case_request (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
post /api/cases
-
Creates a case in the default space. (createCaseDefaultSpace)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're creating.
- - -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
create_case_request create_case_request (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
delete /s/{spaceId}/api/cases
-
Deletes one or more cases. (deleteCase)
-
You must have read or all privileges and the delete sub-feature privilege for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're deleting.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- -

Query parameters

-
-
ids (required)
- -
Query Parameter — The cases that you want to removed. All non-ASCII characters must be URL encoded. default: null
-
- - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
delete /s/{spaceId}/api/cases/{caseId}/comments/{commentId}
-
Deletes a comment or alert from a case. (deleteCaseComment)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're deleting.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
commentId (required)
- -
Path Parameter — The identifier for the comment. To retrieve comment IDs, use the get case or find cases APIs. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
delete /api/cases/{caseId}/comments/{commentId}
-
Deletes a comment or alert from a case in the default space. (deleteCaseCommentDefaultSpace)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're deleting.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
commentId (required)
- -
Path Parameter — The identifier for the comment. To retrieve comment IDs, use the get case or find cases APIs. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
delete /s/{spaceId}/api/cases/{caseId}/comments
-
Deletes all comments and alerts from a case. (deleteCaseComments)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're deleting.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
delete /api/cases/{caseId}/comments
-
Deletes all comments and alerts from a case in the default space. (deleteCaseCommentsDefaultSpace)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're deleting.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
delete /api/cases
-
Deletes one or more cases in the default space. (deleteCaseDefaultSpace)
-
You must have read or all privileges and the delete sub-feature privilege for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're deleting.
- - - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- -

Query parameters

-
-
ids (required)
- -
Query Parameter — The cases that you want to removed. All non-ASCII characters must be URL encoded. default: null
-
- - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/{caseId}/user_actions/_find
-
Finds user activity for a case. (findCaseActivity)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
page (optional)
- -
Query Parameter — The page number to return. default: 1
perPage (optional)
- -
Query Parameter — The number of items to return. Limited to 100 items. default: 20
sortOrder (optional)
- -
Query Parameter — Determines the sort order. default: desc
types (optional)
- -
Query Parameter — Determines the types of user actions to return. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "userActions" : [ {
-    "owner" : "cases",
-    "action" : "create",
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "id" : "22fd3e30-03b1-11ed-920c-974bfa104448",
-    "comment_id" : "578608d0-03b1-11ed-920c-974bfa104448",
-    "type" : "create_case",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzM1ODg4LDFd"
-  }, {
-    "owner" : "cases",
-    "action" : "create",
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "id" : "22fd3e30-03b1-11ed-920c-974bfa104448",
-    "comment_id" : "578608d0-03b1-11ed-920c-974bfa104448",
-    "type" : "create_case",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzM1ODg4LDFd"
-  } ],
-  "total" : 1,
-  "perPage" : 6,
-  "page" : 0
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - findCaseActivity_200_response -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/{caseId}/user_actions/_find
-
Finds user activity for a case in the default space. (findCaseActivityDefaultSpace)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
-
- - - - -

Query parameters

-
-
page (optional)
- -
Query Parameter — The page number to return. default: 1
perPage (optional)
- -
Query Parameter — The number of items to return. Limited to 100 items. default: 20
sortOrder (optional)
- -
Query Parameter — Determines the sort order. default: desc
types (optional)
- -
Query Parameter — Determines the types of user actions to return. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "userActions" : [ {
-    "owner" : "cases",
-    "action" : "create",
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "id" : "22fd3e30-03b1-11ed-920c-974bfa104448",
-    "comment_id" : "578608d0-03b1-11ed-920c-974bfa104448",
-    "type" : "create_case",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzM1ODg4LDFd"
-  }, {
-    "owner" : "cases",
-    "action" : "create",
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "id" : "22fd3e30-03b1-11ed-920c-974bfa104448",
-    "comment_id" : "578608d0-03b1-11ed-920c-974bfa104448",
-    "type" : "create_case",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzM1ODg4LDFd"
-  }, {
-    "owner" : "cases",
-    "action" : "create",
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "id" : "22fd3e30-03b1-11ed-920c-974bfa104448",
-    "comment_id" : "578608d0-03b1-11ed-920c-974bfa104448",
-    "type" : "create_case",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzM1ODg4LDFd"
-  }, {
-    "owner" : "cases",
-    "action" : "create",
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "id" : "22fd3e30-03b1-11ed-920c-974bfa104448",
-    "comment_id" : "578608d0-03b1-11ed-920c-974bfa104448",
-    "type" : "create_case",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzM1ODg4LDFd"
-  }, {
-    "owner" : "cases",
-    "action" : "create",
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "id" : "22fd3e30-03b1-11ed-920c-974bfa104448",
-    "comment_id" : "578608d0-03b1-11ed-920c-974bfa104448",
-    "type" : "create_case",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzM1ODg4LDFd"
-  } ],
-  "total" : 1,
-  "perPage" : 6,
-  "page" : 0
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - findCaseActivityDefaultSpace_200_response -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/{caseId}/comments/_find
-
Retrieves all the user comments from a case. (findCaseComments)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
page (optional)
- -
Query Parameter — The page number to return. default: 1
perPage (optional)
- -
Query Parameter — The number of items to return. Limited to 100 items. default: 20
sortOrder (optional)
- -
Query Parameter — Determines the sort order. default: desc
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/configure/connectors/_find
-
Retrieves information about connectors. (findCaseConnectors)
-
In particular, only the connectors that are supported for use in cases are returned. You must have read privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "isPreconfigured" : true,
-  "isDeprecated" : true,
-  "actionTypeId" : ".none",
-  "referencedByCount" : 0,
-  "name" : "name",
-  "id" : "id",
-  "config" : {
-    "projectKey" : "projectKey",
-    "apiUrl" : "apiUrl"
-  },
-  "isMissingSecrets" : true
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/configure/connectors/_find
-
Retrieves information about connectors in the default space. (findCaseConnectorsDefaultSpace)
-
In particular, only the connectors that are supported for use in cases are returned. You must have read privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges.
- - - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "isPreconfigured" : true,
-  "isDeprecated" : true,
-  "actionTypeId" : ".none",
-  "referencedByCount" : 0,
-  "name" : "name",
-  "id" : "id",
-  "config" : {
-    "projectKey" : "projectKey",
-    "apiUrl" : "apiUrl"
-  },
-  "isMissingSecrets" : true
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/_find
-
Retrieves a paginated subset of cases. (findCases)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
assignees (optional)
- -
Query Parameter — Filters the returned cases by assignees. Valid values are none or unique identifiers for the user profiles. These identifiers can be found by using the suggest user profile API. default: null
category (optional)
- -
Query Parameter — Filters the returned cases by category. default: null
defaultSearchOperator (optional)
- -
Query Parameter — he default operator to use for the simple_query_string. default: OR
from (optional)
- -
Query Parameter — [preview] Returns only cases that were created after a specific date. The date must be specified as a KQL data range or date match expression. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. default: null
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
page (optional)
- -
Query Parameter — The page number to return. default: 1
perPage (optional)
- -
Query Parameter — The number of items to return. Limited to 100 items. default: 20
reporters (optional)
- -
Query Parameter — Filters the returned cases by the user name of the reporter. default: null
search (optional)
- -
Query Parameter — An Elasticsearch simple_query_string query that filters the objects in the response. default: null
searchFields (optional)
- -
Query Parameter — The fields to perform the simple_query_string parsed query against. default: null
severity (optional)
- -
Query Parameter — The severity of the case. default: null
sortField (optional)
- -
Query Parameter — Determines which field is used to sort the results. default: createdAt
sortOrder (optional)
- -
Query Parameter — Determines the sort order. default: desc
status (optional)
- -
Query Parameter — Filters the returned cases by state. default: null
tags (optional)
- -
Query Parameter — Filters the returned cases by tags. default: null
to (optional)
- -
Query Parameter — [preview] Returns only cases that were created before a specific date. The date must be specified as a KQL data range or date match expression. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "count_in_progress_cases" : 6,
-  "per_page" : 5,
-  "total" : 2,
-  "cases" : [ {
-    "owner" : "cases",
-    "totalComment" : 0,
-    "settings" : {
-      "syncAlerts" : true
-    },
-    "totalAlerts" : 0,
-    "closed_at" : "2000-01-23T04:56:07.000+00:00",
-    "comments" : [ null, null, null, null, null ],
-    "assignees" : [ {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    } ],
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "description" : "A case description.",
-    "title" : "Case title 1",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzUzMiwxXQ==",
-    "closed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "tags" : [ "tag-1" ],
-    "duration" : 120,
-    "updated_at" : "2000-01-23T04:56:07.000+00:00",
-    "updated_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-    "external_service" : {
-      "external_title" : "external_title",
-      "pushed_by" : {
-        "full_name" : "full_name",
-        "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-        "email" : "email",
-        "username" : "elastic"
-      },
-      "external_url" : "external_url",
-      "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-      "connector_id" : "connector_id",
-      "external_id" : "external_id",
-      "connector_name" : "connector_name"
-    }
-  }, {
-    "owner" : "cases",
-    "totalComment" : 0,
-    "settings" : {
-      "syncAlerts" : true
-    },
-    "totalAlerts" : 0,
-    "closed_at" : "2000-01-23T04:56:07.000+00:00",
-    "comments" : [ null, null, null, null, null ],
-    "assignees" : [ {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    } ],
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "description" : "A case description.",
-    "title" : "Case title 1",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzUzMiwxXQ==",
-    "closed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "tags" : [ "tag-1" ],
-    "duration" : 120,
-    "updated_at" : "2000-01-23T04:56:07.000+00:00",
-    "updated_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-    "external_service" : {
-      "external_title" : "external_title",
-      "pushed_by" : {
-        "full_name" : "full_name",
-        "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-        "email" : "email",
-        "username" : "elastic"
-      },
-      "external_url" : "external_url",
-      "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-      "connector_id" : "connector_id",
-      "external_id" : "external_id",
-      "connector_name" : "connector_name"
-    }
-  } ],
-  "count_open_cases" : 1,
-  "count_closed_cases" : 0,
-  "page" : 5
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - findCases_200_response -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/_find
-
Retrieves a paginated subset of cases in the default space. (findCasesDefaultSpace)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
- - - - - -

Query parameters

-
-
assignees (optional)
- -
Query Parameter — Filters the returned cases by assignees. Valid values are none or unique identifiers for the user profiles. These identifiers can be found by using the suggest user profile API. default: null
category (optional)
- -
Query Parameter — Filters the returned cases by category. default: null
defaultSearchOperator (optional)
- -
Query Parameter — he default operator to use for the simple_query_string. default: OR
from (optional)
- -
Query Parameter — [preview] Returns only cases that were created after a specific date. The date must be specified as a KQL data range or date match expression. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. default: null
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
page (optional)
- -
Query Parameter — The page number to return. default: 1
perPage (optional)
- -
Query Parameter — The number of items to return. Limited to 100 items. default: 20
reporters (optional)
- -
Query Parameter — Filters the returned cases by the user name of the reporter. default: null
search (optional)
- -
Query Parameter — An Elasticsearch simple_query_string query that filters the objects in the response. default: null
searchFields (optional)
- -
Query Parameter — The fields to perform the simple_query_string parsed query against. default: null
severity (optional)
- -
Query Parameter — The severity of the case. default: null
sortField (optional)
- -
Query Parameter — Determines which field is used to sort the results. default: createdAt
sortOrder (optional)
- -
Query Parameter — Determines the sort order. default: desc
status (optional)
- -
Query Parameter — Filters the returned cases by state. default: null
tags (optional)
- -
Query Parameter — Filters the returned cases by tags. default: null
to (optional)
- -
Query Parameter — [preview] Returns only cases that were created before a specific date. The date must be specified as a KQL data range or date match expression. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "count_in_progress_cases" : 6,
-  "per_page" : 5,
-  "total" : 2,
-  "cases" : [ {
-    "owner" : "cases",
-    "totalComment" : 0,
-    "settings" : {
-      "syncAlerts" : true
-    },
-    "totalAlerts" : 0,
-    "closed_at" : "2000-01-23T04:56:07.000+00:00",
-    "comments" : [ null, null, null, null, null ],
-    "assignees" : [ {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    } ],
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "description" : "A case description.",
-    "title" : "Case title 1",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzUzMiwxXQ==",
-    "closed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "tags" : [ "tag-1" ],
-    "duration" : 120,
-    "updated_at" : "2000-01-23T04:56:07.000+00:00",
-    "updated_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-    "external_service" : {
-      "external_title" : "external_title",
-      "pushed_by" : {
-        "full_name" : "full_name",
-        "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-        "email" : "email",
-        "username" : "elastic"
-      },
-      "external_url" : "external_url",
-      "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-      "connector_id" : "connector_id",
-      "external_id" : "external_id",
-      "connector_name" : "connector_name"
-    }
-  }, {
-    "owner" : "cases",
-    "totalComment" : 0,
-    "settings" : {
-      "syncAlerts" : true
-    },
-    "totalAlerts" : 0,
-    "closed_at" : "2000-01-23T04:56:07.000+00:00",
-    "comments" : [ null, null, null, null, null ],
-    "assignees" : [ {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    } ],
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "description" : "A case description.",
-    "title" : "Case title 1",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzUzMiwxXQ==",
-    "closed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "tags" : [ "tag-1" ],
-    "duration" : 120,
-    "updated_at" : "2000-01-23T04:56:07.000+00:00",
-    "updated_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-    "external_service" : {
-      "external_title" : "external_title",
-      "pushed_by" : {
-        "full_name" : "full_name",
-        "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-        "email" : "email",
-        "username" : "elastic"
-      },
-      "external_url" : "external_url",
-      "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-      "connector_id" : "connector_id",
-      "external_id" : "external_id",
-      "connector_name" : "connector_name"
-    }
-  }, {
-    "owner" : "cases",
-    "totalComment" : 0,
-    "settings" : {
-      "syncAlerts" : true
-    },
-    "totalAlerts" : 0,
-    "closed_at" : "2000-01-23T04:56:07.000+00:00",
-    "comments" : [ null, null, null, null, null ],
-    "assignees" : [ {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    } ],
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "description" : "A case description.",
-    "title" : "Case title 1",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzUzMiwxXQ==",
-    "closed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "tags" : [ "tag-1" ],
-    "duration" : 120,
-    "updated_at" : "2000-01-23T04:56:07.000+00:00",
-    "updated_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-    "external_service" : {
-      "external_title" : "external_title",
-      "pushed_by" : {
-        "full_name" : "full_name",
-        "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-        "email" : "email",
-        "username" : "elastic"
-      },
-      "external_url" : "external_url",
-      "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-      "connector_id" : "connector_id",
-      "external_id" : "external_id",
-      "connector_name" : "connector_name"
-    }
-  }, {
-    "owner" : "cases",
-    "totalComment" : 0,
-    "settings" : {
-      "syncAlerts" : true
-    },
-    "totalAlerts" : 0,
-    "closed_at" : "2000-01-23T04:56:07.000+00:00",
-    "comments" : [ null, null, null, null, null ],
-    "assignees" : [ {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    } ],
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "description" : "A case description.",
-    "title" : "Case title 1",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzUzMiwxXQ==",
-    "closed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "tags" : [ "tag-1" ],
-    "duration" : 120,
-    "updated_at" : "2000-01-23T04:56:07.000+00:00",
-    "updated_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-    "external_service" : {
-      "external_title" : "external_title",
-      "pushed_by" : {
-        "full_name" : "full_name",
-        "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-        "email" : "email",
-        "username" : "elastic"
-      },
-      "external_url" : "external_url",
-      "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-      "connector_id" : "connector_id",
-      "external_id" : "external_id",
-      "connector_name" : "connector_name"
-    }
-  }, {
-    "owner" : "cases",
-    "totalComment" : 0,
-    "settings" : {
-      "syncAlerts" : true
-    },
-    "totalAlerts" : 0,
-    "closed_at" : "2000-01-23T04:56:07.000+00:00",
-    "comments" : [ null, null, null, null, null ],
-    "assignees" : [ {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    } ],
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "description" : "A case description.",
-    "title" : "Case title 1",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzUzMiwxXQ==",
-    "closed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "tags" : [ "tag-1" ],
-    "duration" : 120,
-    "updated_at" : "2000-01-23T04:56:07.000+00:00",
-    "updated_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-    "external_service" : {
-      "external_title" : "external_title",
-      "pushed_by" : {
-        "full_name" : "full_name",
-        "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-        "email" : "email",
-        "username" : "elastic"
-      },
-      "external_url" : "external_url",
-      "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-      "connector_id" : "connector_id",
-      "external_id" : "external_id",
-      "connector_name" : "connector_name"
-    }
-  } ],
-  "count_open_cases" : 1,
-  "count_closed_cases" : 0,
-  "page" : 5
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - findCasesDefaultSpace_200_response -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/{caseId}/comments
-
Retrieves all the comments from a case. (getAllCaseComments)
-
Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; instead, use the get case comment API, which requires a comment identifier in the path. You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/{caseId}/comments
-
Retrieves all the comments from a case in the default space. (getAllCaseCommentsDefaultSpace)
-
Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; instead, use the get case comment API, which requires a comment identifier in the path. You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/{caseId}
-
Retrieves information about a case. (getCase)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
includeComments (optional)
- -
Query Parameter — Deprecated in 8.1.0. This parameter is deprecated and will be removed in a future release. It determines whether case comments are returned. default: true
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/{caseId}/user_actions
-
Returns all user activity for a case. (getCaseActivity)
-
Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find user actions API instead. You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "action_id" : "22fd3e30-03b1-11ed-920c-974bfa104448",
-  "case_id" : "22df07d0-03b1-11ed-920c-974bfa104448",
-  "action" : "create",
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "comment_id" : "578608d0-03b1-11ed-920c-974bfa104448",
-  "type" : "create_case",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/{caseId}/user_actions
-
Returns all user activity for a case in the default space. (getCaseActivityDefaultSpace)
-
Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find user actions API instead. You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "action_id" : "22fd3e30-03b1-11ed-920c-974bfa104448",
-  "case_id" : "22df07d0-03b1-11ed-920c-974bfa104448",
-  "action" : "create",
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "comment_id" : "578608d0-03b1-11ed-920c-974bfa104448",
-  "type" : "create_case",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/{caseId}/alerts
-
Gets all alerts attached to a case. (getCaseAlerts)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "index" : "index",
-  "id" : "id",
-  "attached_at" : "2000-01-23T04:56:07.000+00:00"
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/{caseId}/alerts
-
Gets all alerts attached to a case in the default space. (getCaseAlertsDefaultSpace)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "index" : "index",
-  "id" : "id",
-  "attached_at" : "2000-01-23T04:56:07.000+00:00"
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/{caseId}/comments/{commentId}
-
Retrieves a comment from a case. (getCaseComment)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
commentId (required)
- -
Path Parameter — The identifier for the comment. To retrieve comment IDs, use the get case or find cases APIs. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
null
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - getCaseCommentDefaultSpace_200_response -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/{caseId}/comments/{commentId}
-
Retrieves a comment from a case in the default space. (getCaseCommentDefaultSpace)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
commentId (required)
- -
Path Parameter — The identifier for the comment. To retrieve comment IDs, use the get case or find cases APIs. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
null
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - getCaseCommentDefaultSpace_200_response -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/configure
-
Retrieves external connection details, such as the closure type and default connector for cases. (getCaseConfiguration)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case configuration.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "closure_type" : "close-by-user",
-  "owner" : "cases",
-  "mappings" : [ {
-    "action_type" : "overwrite",
-    "source" : "title",
-    "target" : "summary"
-  }, {
-    "action_type" : "overwrite",
-    "source" : "title",
-    "target" : "summary"
-  } ],
-  "connector" : {
-    "name" : "none",
-    "id" : "none",
-    "fields" : "{}",
-    "type" : ".none"
-  },
-  "updated_at" : "2022-06-01T19:58:48.169Z",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "created_at" : "2022-06-01T17:07:17.767Z",
-  "id" : "4a97a440-e1cd-11ec-be9b-9b1838238ee6",
-  "error" : "error",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzIwNzMsMV0="
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/configure
-
Retrieves external connection details, such as the closure type and default connector for cases in the default space. (getCaseConfigurationDefaultSpace)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case configuration.
- - - - - -

Query parameters

-
-
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "closure_type" : "close-by-user",
-  "owner" : "cases",
-  "mappings" : [ {
-    "action_type" : "overwrite",
-    "source" : "title",
-    "target" : "summary"
-  }, {
-    "action_type" : "overwrite",
-    "source" : "title",
-    "target" : "summary"
-  } ],
-  "connector" : {
-    "name" : "none",
-    "id" : "none",
-    "fields" : "{}",
-    "type" : ".none"
-  },
-  "updated_at" : "2022-06-01T19:58:48.169Z",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "created_at" : "2022-06-01T17:07:17.767Z",
-  "id" : "4a97a440-e1cd-11ec-be9b-9b1838238ee6",
-  "error" : "error",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzIwNzMsMV0="
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/{caseId}
-
Retrieves information about a case in the default space. (getCaseDefaultSpace)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're seeking.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
-
- - - - -

Query parameters

-
-
includeComments (optional)
- -
Query Parameter — Deprecated in 8.1.0. This parameter is deprecated and will be removed in a future release. It determines whether case comments are returned. default: true
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/reporters
-
Returns information about the users who opened cases. (getCaseReporters)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases. The API returns information about the users as they existed at the time of the case creation, including their name, full name, and email address. If any of those details change thereafter or if a user is deleted, the information returned by this API is unchanged.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "full_name" : "full_name",
-  "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-  "email" : "email",
-  "username" : "elastic"
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/reporters
-
Returns information about the users who opened cases in the default space. (getCaseReportersDefaultSpace)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases. The API returns information about the users as they existed at the time of the case creation, including their name, full name, and email address. If any of those details change thereafter or if a user is deleted, the information returned by this API is unchanged.
- - - - - -

Query parameters

-
-
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "full_name" : "full_name",
-  "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-  "email" : "email",
-  "username" : "elastic"
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/status
-
Returns the number of cases that are open, closed, and in progress. (getCaseStatus)
-
Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find cases API instead. You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "count_in_progress_cases" : 6,
-  "count_open_cases" : 1,
-  "count_closed_cases" : 0
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - getCaseStatusDefaultSpace_200_response -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/status
-
Returns the number of cases that are open, closed, and in progress in the default space. (getCaseStatusDefaultSpace)
-
Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find cases API instead. You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
- - - - - -

Query parameters

-
-
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "count_in_progress_cases" : 6,
-  "count_open_cases" : 1,
-  "count_closed_cases" : 0
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - getCaseStatusDefaultSpace_200_response -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/tags
-
Aggregates and returns a list of case tags. (getCaseTags)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
-
- - -

Return type

-
- - array[String] -
- - - -

Example data

-
Content-Type: application/json
-
""
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/tags
-
Aggregates and returns a list of case tags in the default space. (getCaseTagsDefaultSpace)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
- - - - - -

Query parameters

-
-
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
-
- - -

Return type

-
- - array[String] -
- - - -

Example data

-
Content-Type: application/json
-
""
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/alerts/{alertId}
-
Returns the cases associated with a specific alert. (getCasesByAlert)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
- -

Path parameters

-
-
alertId (required)
- -
Path Parameter — An identifier for the alert. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
[ {
-  "id" : "06116b80-e1c3-11ec-be9b-9b1838238ee6",
-  "title" : "security_case"
-} ]
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /api/cases/alerts/{alertId}
-
Returns the cases associated with a specific alert in the default space. (getCasesByAlertDefaultSpace)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
- -

Path parameters

-
-
alertId (required)
- -
Path Parameter — An identifier for the alert. default: null
-
- - - - -

Query parameters

-
-
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
[ {
-  "id" : "06116b80-e1c3-11ec-be9b-9b1838238ee6",
-  "title" : "security_case"
-} ]
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
post /s/{spaceId}/api/cases/{caseId}/connector/{connectorId}/_push
-
Pushes a case to an external service. (pushCase)
-
You must have all privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges. You must also have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're pushing.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
connectorId (required)
- -
Path Parameter — An identifier for the connector. To retrieve connector IDs, use the find connectors API. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
body object (optional)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
post /api/cases/{caseId}/connector/{connectorId}/_push
-
Pushes a case in the default space to an external service. (pushCaseDefaultSpace)
-
You must have all privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges. You must also have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're pushing.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
connectorId (required)
- -
Path Parameter — An identifier for the connector. To retrieve connector IDs, use the find connectors API. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
body object (optional)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
post /s/{spaceId}/api/cases/configure
-
Sets external connection details, such as the closure type and default connector for cases. (setCaseConfiguration)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case configuration. Connectors are used to interface with external systems. You must create a connector before you can use it in your cases. Refer to the add connectors API. If you set a default connector, it is automatically selected when you create cases in Kibana. If you use the create case API, however, you must still specify all of the connector details.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
set_case_configuration_request set_case_configuration_request (optional)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "closure_type" : "close-by-user",
-  "owner" : "cases",
-  "mappings" : [ {
-    "action_type" : "overwrite",
-    "source" : "title",
-    "target" : "summary"
-  }, {
-    "action_type" : "overwrite",
-    "source" : "title",
-    "target" : "summary"
-  } ],
-  "connector" : {
-    "name" : "none",
-    "id" : "none",
-    "fields" : "{}",
-    "type" : ".none"
-  },
-  "updated_at" : "2022-06-01T19:58:48.169Z",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "created_at" : "2022-06-01T17:07:17.767Z",
-  "id" : "4a97a440-e1cd-11ec-be9b-9b1838238ee6",
-  "error" : "error",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzIwNzMsMV0="
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - getCaseConfigurationDefaultSpace_200_response_inner -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
post /api/cases/configure
-
Sets external connection details, such as the closure type and default connector for cases in the default space. (setCaseConfigurationDefaultSpace)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case configuration. Connectors are used to interface with external systems. You must create a connector before you can use it in your cases. Refer to the add connectors API. If you set a default connector, it is automatically selected when you create cases in Kibana. If you use the create case API, however, you must still specify all of the connector details.
- - -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
set_case_configuration_request set_case_configuration_request (optional)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "closure_type" : "close-by-user",
-  "owner" : "cases",
-  "mappings" : [ {
-    "action_type" : "overwrite",
-    "source" : "title",
-    "target" : "summary"
-  }, {
-    "action_type" : "overwrite",
-    "source" : "title",
-    "target" : "summary"
-  } ],
-  "connector" : {
-    "name" : "none",
-    "id" : "none",
-    "fields" : "{}",
-    "type" : ".none"
-  },
-  "updated_at" : "2022-06-01T19:58:48.169Z",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "created_at" : "2022-06-01T17:07:17.767Z",
-  "id" : "4a97a440-e1cd-11ec-be9b-9b1838238ee6",
-  "error" : "error",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzIwNzMsMV0="
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - getCaseConfigurationDefaultSpace_200_response_inner -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
patch /s/{spaceId}/api/cases
-
Updates one or more cases. (updateCase)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're updating.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
update_case_request update_case_request (optional)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
patch /s/{spaceId}/api/cases/{caseId}/comments
-
Updates a comment or alert in a case. (updateCaseComment)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're updating. NOTE: You cannot change the comment type or the owner of a comment.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
update_case_comment_request update_case_comment_request (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
patch /api/cases/{caseId}/comments
-
Updates a comment or alert in a case in the default space. (updateCaseCommentDefaultSpace)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're updating. NOTE: You cannot change the comment type or the owner of a comment.
- -

Path parameters

-
-
caseId (required)
- -
Path Parameter — The identifier for the case. To retrieve case IDs, use the find cases API. All non-ASCII characters must be URL encoded. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
update_case_comment_request update_case_comment_request (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - case_response_properties -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
patch /s/{spaceId}/api/cases/configure/{configurationId}
-
Updates external connection details, such as the closure type and default connector for cases. (updateCaseConfiguration)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case configuration. Connectors are used to interface with external systems. You must create a connector before you can use it in your cases. Refer to the add connectors API.
- -

Path parameters

-
-
configurationId (required)
- -
Path Parameter — An identifier for the configuration. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
update_case_configuration_request update_case_configuration_request (optional)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "closure_type" : "close-by-user",
-  "owner" : "cases",
-  "mappings" : [ {
-    "action_type" : "overwrite",
-    "source" : "title",
-    "target" : "summary"
-  }, {
-    "action_type" : "overwrite",
-    "source" : "title",
-    "target" : "summary"
-  } ],
-  "connector" : {
-    "name" : "none",
-    "id" : "none",
-    "fields" : "{}",
-    "type" : ".none"
-  },
-  "updated_at" : "2022-06-01T19:58:48.169Z",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "created_at" : "2022-06-01T17:07:17.767Z",
-  "id" : "4a97a440-e1cd-11ec-be9b-9b1838238ee6",
-  "error" : "error",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzIwNzMsMV0="
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
patch /api/cases/configure/{configurationId}
-
Updates external connection details, such as the closure type and default connector for cases in the default space. (updateCaseConfigurationDefaultSpace)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case configuration. Connectors are used to interface with external systems. You must create a connector before you can use it in your cases. Refer to the add connectors API.
- -

Path parameters

-
-
configurationId (required)
- -
Path Parameter — An identifier for the configuration. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
update_case_configuration_request update_case_configuration_request (optional)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "closure_type" : "close-by-user",
-  "owner" : "cases",
-  "mappings" : [ {
-    "action_type" : "overwrite",
-    "source" : "title",
-    "target" : "summary"
-  }, {
-    "action_type" : "overwrite",
-    "source" : "title",
-    "target" : "summary"
-  } ],
-  "connector" : {
-    "name" : "none",
-    "id" : "none",
-    "fields" : "{}",
-    "type" : ".none"
-  },
-  "updated_at" : "2022-06-01T19:58:48.169Z",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "created_at" : "2022-06-01T17:07:17.767Z",
-  "id" : "4a97a440-e1cd-11ec-be9b-9b1838238ee6",
-  "error" : "error",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzIwNzMsMV0="
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
patch /api/cases
-
Updates one or more cases in the default space. (updateCaseDefaultSpace)
-
You must have all privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're updating.
- - -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
update_case_request update_case_request (optional)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "owner" : "cases",
-  "totalComment" : 0,
-  "settings" : {
-    "syncAlerts" : true
-  },
-  "totalAlerts" : 0,
-  "closed_at" : "2000-01-23T04:56:07.000+00:00",
-  "comments" : [ null, null, null, null, null ],
-  "assignees" : [ {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  }, {
-    "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-  } ],
-  "created_at" : "2022-05-13T09:16:17.416Z",
-  "description" : "A case description.",
-  "title" : "Case title 1",
-  "created_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "version" : "WzUzMiwxXQ==",
-  "closed_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "tags" : [ "tag-1" ],
-  "duration" : 120,
-  "updated_at" : "2000-01-23T04:56:07.000+00:00",
-  "updated_by" : {
-    "full_name" : "full_name",
-    "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-    "email" : "email",
-    "username" : "elastic"
-  },
-  "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-  "external_service" : {
-    "external_title" : "external_title",
-    "pushed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "external_url" : "external_url",
-    "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-    "connector_id" : "connector_id",
-    "external_id" : "external_id",
-    "connector_name" : "connector_name"
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
- -

Models

- [ Jump to Methods ] - -

Table of Contents

-
    -
  1. 4xx_response - Unsuccessful cases API response
  2. -
  3. Case_response_properties_for_comments_inner -
  4. -
  5. Case_response_properties_for_connectors - Case response properties for connectors
  6. -
  7. action_types -
  8. -
  9. actions -
  10. -
  11. add_alert_comment_request_properties - Add case comment request properties for alerts
  12. -
  13. add_case_comment_request - Add case comment request
  14. -
  15. add_user_comment_request_properties - Add case comment request properties for user comments
  16. -
  17. alert_comment_response_properties - Add case comment response properties for alerts
  18. -
  19. alert_comment_response_properties_rule -
  20. -
  21. alert_identifiers - Alert identifiers
  22. -
  23. alert_indices - Alert indices
  24. -
  25. alert_response_properties -
  26. -
  27. assignees_inner -
  28. -
  29. case_response_closed_by_properties - Case response properties for closed_by
  30. -
  31. case_response_created_by_properties - Case response properties for created_by
  32. -
  33. case_response_properties - Case response properties
  34. -
  35. case_response_pushed_by_properties - Case response properties for pushed_by
  36. -
  37. case_response_updated_by_properties - Case response properties for updated_by
  38. -
  39. closure_types -
  40. -
  41. connector_properties_cases_webhook - Create or upate case request properties for Cases Webhook connector
  42. -
  43. connector_properties_jira - Create or update case request properties for a Jira connector
  44. -
  45. connector_properties_jira_fields -
  46. -
  47. connector_properties_none - Create or update case request properties for no connector
  48. -
  49. connector_properties_resilient - Create case request properties for a IBM Resilient connector
  50. -
  51. connector_properties_resilient_fields -
  52. -
  53. connector_properties_servicenow - Create case request properties for a ServiceNow ITSM connector
  54. -
  55. connector_properties_servicenow_fields -
  56. -
  57. connector_properties_servicenow_sir - Create case request properties for a ServiceNow SecOps connector
  58. -
  59. connector_properties_servicenow_sir_fields -
  60. -
  61. connector_properties_swimlane - Create case request properties for a Swimlane connector
  62. -
  63. connector_properties_swimlane_fields -
  64. -
  65. connector_types -
  66. -
  67. create_case_request - Create case request
  68. -
  69. create_case_request_connector -
  70. -
  71. external_service -
  72. -
  73. findCaseActivityDefaultSpace_200_response -
  74. -
  75. findCaseActivity_200_response -
  76. -
  77. findCaseConnectorsDefaultSpace_200_response_inner -
  78. -
  79. findCaseConnectorsDefaultSpace_200_response_inner_config -
  80. -
  81. findCasesDefaultSpace_200_response -
  82. -
  83. findCasesDefaultSpace_assignees_parameter -
  84. -
  85. findCasesDefaultSpace_owner_parameter -
  86. -
  87. findCasesDefaultSpace_searchFields_parameter -
  88. -
  89. findCases_200_response -
  90. -
  91. getCaseCommentDefaultSpace_200_response -
  92. -
  93. getCaseConfigurationDefaultSpace_200_response_inner -
  94. -
  95. getCaseConfigurationDefaultSpace_200_response_inner_connector -
  96. -
  97. getCaseConfigurationDefaultSpace_200_response_inner_created_by -
  98. -
  99. getCaseConfigurationDefaultSpace_200_response_inner_mappings_inner -
  100. -
  101. getCaseConfigurationDefaultSpace_200_response_inner_updated_by -
  102. -
  103. getCaseStatusDefaultSpace_200_response -
  104. -
  105. getCasesByAlertDefaultSpace_200_response_inner -
  106. -
  107. owners -
  108. -
  109. payload_alert_comment -
  110. -
  111. payload_alert_comment_comment -
  112. -
  113. payload_alert_comment_comment_alertId -
  114. -
  115. payload_alert_comment_comment_index -
  116. -
  117. payload_assignees -
  118. -
  119. payload_connector -
  120. -
  121. payload_connector_connector -
  122. -
  123. payload_connector_connector_fields -
  124. -
  125. payload_create_case -
  126. -
  127. payload_description -
  128. -
  129. payload_pushed -
  130. -
  131. payload_settings -
  132. -
  133. payload_severity -
  134. -
  135. payload_status -
  136. -
  137. payload_tags -
  138. -
  139. payload_title -
  140. -
  141. payload_user_comment -
  142. -
  143. payload_user_comment_comment -
  144. -
  145. rule - Alerting rule
  146. -
  147. searchFieldsType -
  148. -
  149. set_case_configuration_request - Set case configuration request
  150. -
  151. set_case_configuration_request_connector -
  152. -
  153. set_case_configuration_request_settings -
  154. -
  155. settings -
  156. -
  157. severity_property -
  158. -
  159. status -
  160. -
  161. update_alert_comment_request_properties - Update case comment request properties for alerts
  162. -
  163. update_case_comment_request - Update case comment request
  164. -
  165. update_case_configuration_request - Update case configuration request
  166. -
  167. update_case_request - Update case request
  168. -
  169. update_case_request_cases_inner -
  170. -
  171. update_user_comment_request_properties - Update case comment request properties for user comments
  172. -
  173. user_actions_find_response_properties -
  174. -
  175. user_actions_response_properties -
  176. -
  177. user_actions_response_properties_created_by -
  178. -
  179. user_actions_response_properties_payload -
  180. -
  181. user_comment_response_properties - Case response properties for user comments
  182. -
- -
-

4xx_response - Unsuccessful cases API response Up

-
-
-
error (optional)
-
message (optional)
-
statusCode (optional)
-
-
-
-

Case_response_properties_for_comments_inner - Up

-
-
-
alertId (optional)
-
created_at (optional)
Date format: date-time
-
created_by (optional)
-
id (optional)
-
index (optional)
-
owner (optional)
-
pushed_at (optional)
Date format: date-time
-
pushed_by (optional)
-
rule (optional)
-
type
-
Enum:
-
user
-
updated_at (optional)
Date format: date-time
-
updated_by (optional)
-
version (optional)
-
comment (optional)
-
-
-
-

Case_response_properties_for_connectors - Case response properties for connectors Up

-
-
-
fields
-
id
String The identifier for the connector. To retrieve connector IDs, use the find connectors API.
-
name
String The name of the connector.
-
type
String The type of connector.
-
Enum:
-
.swimlane
-
-
-
-

action_types - Up

-
The type of action.
-
-
-
-
-

actions - Up

-
-
-
-
-
-

add_alert_comment_request_properties - Add case comment request properties for alerts Up

-
Defines properties for case comment requests when type is alert.
-
-
alertId
-
index
-
owner
-
rule
-
type
String The type of comment.
-
Enum:
-
alert
-
-
-
-

add_case_comment_request - Add case comment request Up

-
The add comment to case API request body varies depending on whether you are adding an alert or a comment.
-
-
alertId
-
index
-
owner
-
rule
-
type
String The type of comment.
-
Enum:
-
user
-
comment
String The new comment. It is required only when type is user.
-
-
-
-

add_user_comment_request_properties - Add case comment request properties for user comments Up

-
Defines properties for case comment requests when type is user.
-
-
comment
String The new comment. It is required only when type is user.
-
owner
-
type
String The type of comment.
-
Enum:
-
user
-
-
-
-

alert_comment_response_properties - Add case comment response properties for alerts Up

-
-
-
alertId (optional)
-
created_at (optional)
Date format: date-time
-
created_by (optional)
-
id (optional)
-
index (optional)
-
owner (optional)
-
pushed_at (optional)
Date format: date-time
-
pushed_by (optional)
-
rule (optional)
-
type
-
Enum:
-
alert
-
updated_at (optional)
Date format: date-time
-
updated_by (optional)
-
version (optional)
-
-
-
-

alert_comment_response_properties_rule - Up

-
-
-
id (optional)
String The rule identifier.
-
name (optional)
String The rule name.
-
-
-
-

alert_identifiers - Alert identifiers Up

-
The alert identifiers. It is required only when type is alert. You can use an array of strings to add multiple alerts to a case, provided that they all relate to the same rule; index must also be an array with the same length or number of elements. Adding multiple alerts in this manner is recommended rather than calling the API multiple times. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.
-
-
-
-
-

alert_indices - Alert indices Up

-
The alert indices. It is required only when type is alert. If you are adding multiple alerts to a case, use an array of strings; the position of each index name in the array must match the position of the corresponding alert identifier in the alertId array. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.
-
-
-
-
-

alert_response_properties - Up

-
-
-
attached_at (optional)
Date format: date-time
-
id (optional)
String The alert identifier.
-
index (optional)
String The alert index.
-
-
-
-

assignees_inner - Up

-
-
-
uid
String A unique identifier for the user profile. These identifiers can be found by using the suggest user profile API.
-
-
-
-

case_response_closed_by_properties - Case response properties for closed_by Up

-
-
-
email
-
full_name
-
username
-
profile_uid (optional)
-
-
-
-

case_response_created_by_properties - Case response properties for created_by Up

-
-
-
email
-
full_name
-
username
-
profile_uid (optional)
-
-
-
-

case_response_properties - Case response properties Up

-
-
-
assignees (optional)
array[assignees_inner] An array containing users that are assigned to the case.
-
closed_at
Date format: date-time
-
closed_by
-
comments
array[Case_response_properties_for_comments_inner] An array of comment objects for the case.
-
connector
-
created_at
Date format: date-time
-
created_by
-
description
-
duration
Integer The elapsed time from the creation of the case to its closure (in seconds). If the case has not been closed, the duration is set to null. If the case was closed after less than half a second, the duration is rounded down to zero.
-
external_service
-
id
-
owner
-
settings
-
severity
-
status
-
tags
-
title
-
totalAlerts
-
totalComment
-
updated_at
Date format: date-time
-
updated_by
-
version
-
-
-
-

case_response_pushed_by_properties - Case response properties for pushed_by Up

-
-
-
email
-
full_name
-
username
-
profile_uid (optional)
-
-
-
-

case_response_updated_by_properties - Case response properties for updated_by Up

-
-
-
email
-
full_name
-
username
-
profile_uid (optional)
-
-
-
-

closure_types - Up

-
Indicates whether a case is automatically closed when it is pushed to external systems (close-by-pushing) or not automatically closed (close-by-user).
-
-
-
-
-

connector_properties_cases_webhook - Create or upate case request properties for Cases Webhook connector Up

-
Defines properties for connectors when type is .cases-webhook.
-
-
fields
-
id
String The identifier for the connector. To retrieve connector IDs, use the find connectors API.
-
name
String The name of the connector.
-
type
String The type of connector.
-
Enum:
-
.cases-webhook
-
-
-
-

connector_properties_jira - Create or update case request properties for a Jira connector Up

-
Defines properties for connectors when type is .jira.
-
-
fields
-
id
String The identifier for the connector. To retrieve connector IDs, use the find connectors API.
-
name
String The name of the connector.
-
type
String The type of connector.
-
Enum:
-
.jira
-
-
-
-

connector_properties_jira_fields - Up

-
An object containing the connector fields. If you want to omit any individual field, specify null as its value.
-
-
issueType
String The type of issue.
-
parent
String The key of the parent issue, when the issue type is sub-task.
-
priority
String The priority of the issue.
-
-
-
-

connector_properties_none - Create or update case request properties for no connector Up

-
Defines properties for connectors when type is .none.
-
-
fields
String An object containing the connector fields. To create a case without a connector, specify null. To update a case to remove the connector, specify null.
-
id
String The identifier for the connector. To create a case without a connector, use none. To update a case to remove the connector, specify none.
-
name
String The name of the connector. To create a case without a connector, use none. To update a case to remove the connector, specify none.
-
type
String The type of connector. To create a case without a connector, use .none. To update a case to remove the connector, specify .none.
-
Enum:
-
.none
-
-
-
-

connector_properties_resilient - Create case request properties for a IBM Resilient connector Up

-
Defines properties for connectors when type is .resilient.
-
-
fields
-
id
String The identifier for the connector.
-
name
String The name of the connector.
-
type
String The type of connector.
-
Enum:
-
.resilient
-
-
-
-

connector_properties_resilient_fields - Up

-
An object containing the connector fields. If you want to omit any individual field, specify null as its value.
-
-
issueTypes
array[String] The type of incident.
-
severityCode
String The severity code of the incident.
-
-
-
-

connector_properties_servicenow - Create case request properties for a ServiceNow ITSM connector Up

-
Defines properties for connectors when type is .servicenow.
-
-
fields
-
id
String The identifier for the connector. To retrieve connector IDs, use the find connectors API.
-
name
String The name of the connector.
-
type
String The type of connector.
-
Enum:
-
.servicenow
-
-
-
-

connector_properties_servicenow_fields - Up

-
An object containing the connector fields. If you want to omit any individual field, specify null as its value.
-
-
category
String The category of the incident.
-
impact
String The effect an incident had on business.
-
severity
String The severity of the incident.
-
subcategory
String The subcategory of the incident.
-
urgency
String The extent to which the incident resolution can be delayed.
-
-
-
-

connector_properties_servicenow_sir - Create case request properties for a ServiceNow SecOps connector Up

-
Defines properties for connectors when type is .servicenow-sir.
-
-
fields
-
id
String The identifier for the connector. To retrieve connector IDs, use the find connectors API.
-
name
String The name of the connector.
-
type
String The type of connector.
-
Enum:
-
.servicenow-sir
-
-
-
-

connector_properties_servicenow_sir_fields - Up

-
An object containing the connector fields. If you want to omit any individual field, specify null as its value.
-
-
category
String The category of the incident.
-
destIp
Boolean Indicates whether cases will send a comma-separated list of destination IPs.
-
malwareHash
Boolean Indicates whether cases will send a comma-separated list of malware hashes.
-
malwareUrl
Boolean Indicates whether cases will send a comma-separated list of malware URLs.
-
priority
String The priority of the issue.
-
sourceIp
Boolean Indicates whether cases will send a comma-separated list of source IPs.
-
subcategory
String The subcategory of the incident.
-
-
-
-

connector_properties_swimlane - Create case request properties for a Swimlane connector Up

-
Defines properties for connectors when type is .swimlane.
-
-
fields
-
id
String The identifier for the connector. To retrieve connector IDs, use the find connectors API.
-
name
String The name of the connector.
-
type
String The type of connector.
-
Enum:
-
.swimlane
-
-
-
-

connector_properties_swimlane_fields - Up

-
An object containing the connector fields. If you want to omit any individual field, specify null as its value.
-
-
caseId
String The case identifier for Swimlane connectors.
-
-
-
-

connector_types - Up

-
The type of connector.
-
-
-
-
-

create_case_request - Create case request Up

-
The create case API request body varies depending on the type of connector.
-
-
assignees (optional)
array[assignees_inner] An array containing users that are assigned to the case.
-
connector
-
description
String The description for the case.
-
owner
-
settings
-
severity (optional)
-
tags
array[String] The words and phrases that help categorize cases. It can be an empty array.
-
category (optional)
String Category for the case. It could be a word or a phrase to categorize the case.
-
title
String A title for the case.
-
-
-
-

create_case_request_connector - Up

-
-
-
fields
-
id
String The identifier for the connector. To retrieve connector IDs, use the find connectors API.
-
name
String The name of the connector.
-
type
String The type of connector.
-
Enum:
-
.swimlane
-
-
-
-

external_service - Up

-
-
-
connector_id (optional)
-
connector_name (optional)
-
external_id (optional)
-
external_title (optional)
-
external_url (optional)
-
pushed_at (optional)
Date format: date-time
-
pushed_by (optional)
-
-
-
-

findCaseActivityDefaultSpace_200_response - Up

-
-
-
page (optional)
-
perPage (optional)
-
total (optional)
-
userActions (optional)
-
-
-
-

findCaseActivity_200_response - Up

-
-
-
page (optional)
-
perPage (optional)
-
total (optional)
-
userActions (optional)
-
-
-
-

findCaseConnectorsDefaultSpace_200_response_inner - Up

-
-
-
actionTypeId (optional)
-
config (optional)
-
id (optional)
-
isDeprecated (optional)
-
isMissingSecrets (optional)
-
isPreconfigured (optional)
-
name (optional)
-
referencedByCount (optional)
-
-
-
-

findCaseConnectorsDefaultSpace_200_response_inner_config - Up

-
-
-
apiUrl (optional)
-
projectKey (optional)
-
-
-
-

findCasesDefaultSpace_200_response - Up

-
-
-
cases (optional)
-
count_closed_cases (optional)
-
count_in_progress_cases (optional)
-
count_open_cases (optional)
-
page (optional)
-
per_page (optional)
-
total (optional)
-
-
- - - -
-

findCases_200_response - Up

-
-
-
cases (optional)
-
count_closed_cases (optional)
-
count_in_progress_cases (optional)
-
count_open_cases (optional)
-
page (optional)
-
per_page (optional)
-
total (optional)
-
-
-
-

getCaseCommentDefaultSpace_200_response - Up

-
-
-
alertId (optional)
-
created_at (optional)
Date format: date-time
-
created_by (optional)
-
id (optional)
-
index (optional)
-
owner (optional)
-
pushed_at (optional)
Date format: date-time
-
pushed_by (optional)
-
rule (optional)
-
type
-
Enum:
-
user
-
updated_at (optional)
Date format: date-time
-
updated_by (optional)
-
version (optional)
-
comment (optional)
-
-
-
-

getCaseConfigurationDefaultSpace_200_response_inner - Up

-
-
-
closure_type (optional)
-
connector (optional)
-
created_at (optional)
Date format: date-time
-
created_by (optional)
-
error (optional)
-
id (optional)
-
mappings (optional)
-
owner (optional)
-
updated_at (optional)
Date format: date-time
-
updated_by (optional)
-
version (optional)
-
-
-
-

getCaseConfigurationDefaultSpace_200_response_inner_connector - Up

-
-
-
fields (optional)
Object The fields specified in the case configuration are not used and are not propagated to individual cases, therefore it is recommended to set it to null.
-
id (optional)
String The identifier for the connector. If you do not want a default connector, use none. To retrieve connector IDs, use the find connectors API.
-
name (optional)
String The name of the connector. If you do not want a default connector, use none. To retrieve connector names, use the find connectors API.
-
type (optional)
-
-
-
-

getCaseConfigurationDefaultSpace_200_response_inner_created_by - Up

-
-
-
email (optional)
-
full_name (optional)
-
username (optional)
-
profile_uid (optional)
-
-
-
-

getCaseConfigurationDefaultSpace_200_response_inner_mappings_inner - Up

-
-
-
action_type (optional)
-
source (optional)
-
target (optional)
-
-
-
-

getCaseConfigurationDefaultSpace_200_response_inner_updated_by - Up

-
-
-
email (optional)
-
full_name (optional)
-
username (optional)
-
profile_uid (optional)
-
-
-
-

getCaseStatusDefaultSpace_200_response - Up

-
-
-
count_closed_cases (optional)
-
count_in_progress_cases (optional)
-
count_open_cases (optional)
-
-
-
-

getCasesByAlertDefaultSpace_200_response_inner - Up

-
-
-
id (optional)
String The case identifier.
-
title (optional)
String The case title.
-
-
-
-

owners - Up

-
The application that owns the cases: Stack Management, Observability, or Elastic Security.
-
-
-
- -
-

payload_alert_comment_comment - Up

-
-
-
alertId (optional)
-
index (optional)
-
owner (optional)
-
rule (optional)
-
type (optional)
-
Enum:
-
alert
-
-
- - -
-

payload_assignees - Up

-
-
-
assignees (optional)
array[assignees_inner] An array containing users that are assigned to the case.
-
-
-
-

payload_connector - Up

-
-
-
connector (optional)
-
-
-
-

payload_connector_connector - Up

-
-
-
fields (optional)
-
id (optional)
String The identifier for the connector. To create a case without a connector, use none.
-
name (optional)
String The name of the connector. To create a case without a connector, use none.
-
type (optional)
-
-
-
-

payload_connector_connector_fields - Up

-
An object containing the connector fields. To create a case without a connector, specify null. If you want to omit any individual field, specify null as its value.
-
-
caseId (optional)
String The case identifier for Swimlane connectors.
-
category (optional)
String The category of the incident for ServiceNow ITSM and ServiceNow SecOps connectors.
-
destIp (optional)
Boolean Indicates whether cases will send a comma-separated list of destination IPs for ServiceNow SecOps connectors.
-
impact (optional)
String The effect an incident had on business for ServiceNow ITSM connectors.
-
issueType (optional)
String The type of issue for Jira connectors.
-
issueTypes (optional)
array[String] The type of incident for IBM Resilient connectors.
-
malwareHash (optional)
Boolean Indicates whether cases will send a comma-separated list of malware hashes for ServiceNow SecOps connectors.
-
malwareUrl (optional)
Boolean Indicates whether cases will send a comma-separated list of malware URLs for ServiceNow SecOps connectors.
-
parent (optional)
String The key of the parent issue, when the issue type is sub-task for Jira connectors.
-
priority (optional)
String The priority of the issue for Jira and ServiceNow SecOps connectors.
-
severity (optional)
String The severity of the incident for ServiceNow ITSM connectors.
-
severityCode (optional)
String The severity code of the incident for IBM Resilient connectors.
-
sourceIp (optional)
Boolean Indicates whether cases will send a comma-separated list of source IPs for ServiceNow SecOps connectors.
-
subcategory (optional)
String The subcategory of the incident for ServiceNow ITSM connectors.
-
urgency (optional)
String The extent to which the incident resolution can be delayed for ServiceNow ITSM connectors.
-
-
-
-

payload_create_case - Up

-
-
-
assignees (optional)
array[assignees_inner] An array containing users that are assigned to the case.
-
connector (optional)
-
description (optional)
-
owner (optional)
-
settings (optional)
-
severity (optional)
-
status (optional)
-
tags (optional)
-
title (optional)
-
-
-
-

payload_description - Up

-
-
-
description (optional)
-
-
-
-

payload_pushed - Up

-
-
-
externalService (optional)
-
-
-
-

payload_settings - Up

-
-
-
settings (optional)
-
-
-
-

payload_severity - Up

-
-
-
severity (optional)
-
-
-
-

payload_status - Up

-
-
-
status (optional)
-
-
-
-

payload_tags - Up

-
-
-
tags (optional)
-
-
-
-

payload_title - Up

-
-
-
title (optional)
-
-
- -
-

payload_user_comment_comment - Up

-
-
-
comment (optional)
-
owner (optional)
-
type (optional)
-
Enum:
-
user
-
-
-
-

rule - Alerting rule Up

-
The rule that is associated with the alerts. It is required only when type is alert. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.
-
-
id (optional)
String The rule identifier.
-
name (optional)
String The rule name.
-
-
-
-

searchFieldsType - Up

-
The fields to perform the simple_query_string parsed query against.
-
-
-
-
-

set_case_configuration_request - Set case configuration request Up

-
External connection details, such as the closure type and default connector for cases.
- -
-
-

set_case_configuration_request_connector - Up

-
An object that contains the connector configuration.
-
-
fields
Object The fields specified in the case configuration are not used and are not propagated to individual cases, therefore it is recommended to set it to null.
-
id
String The identifier for the connector. If you do not want a default connector, use none. To retrieve connector IDs, use the find connectors API.
-
name
String The name of the connector. If you do not want a default connector, use none. To retrieve connector names, use the find connectors API.
-
type
-
-
-
-

set_case_configuration_request_settings - Up

-
An object that contains the case settings.
-
-
syncAlerts
Boolean Turns alert syncing on or off.
-
-
-
-

settings - Up

-
An object that contains the case settings.
-
-
syncAlerts
Boolean Turns alert syncing on or off.
-
-
-
-

severity_property - Up

-
The severity of the case.
-
-
-
-
-

status - Up

-
The status of the case.
-
-
-
-
-

update_alert_comment_request_properties - Update case comment request properties for alerts Up

-
Defines properties for case comment requests when type is alert.
-
-
alertId
-
id
String The identifier for the comment. To retrieve comment IDs, use the get comments API.
-
index
-
owner
-
rule
-
type
String The type of comment.
-
Enum:
-
alert
-
version
String The current comment version. To retrieve version values, use the get comments API.
-
-
-
-

update_case_comment_request - Update case comment request Up

-
The update case comment API request body varies depending on whether you are updating an alert or a comment.
-
-
alertId
-
id
String The identifier for the comment. To retrieve comment IDs, use the get comments API.
-
index
-
owner
-
rule
-
type
String The type of comment.
-
Enum:
-
user
-
version
String The current comment version. To retrieve version values, use the get comments API.
-
comment
String The new comment. It is required only when type is user.
-
-
-
-

update_case_configuration_request - Update case configuration request Up

-
External connection details, such as the closure type and default connector for cases.
-
-
closure_type (optional)
-
connector (optional)
-
version
String The version of the connector. To retrieve the version value, use the get configuration API.
-
-
-
-

update_case_request - Update case request Up

-
The update case API request body varies depending on the type of connector.
-
-
cases
array[update_case_request_cases_inner] An array containing one or more case objects.
-
-
-
-

update_case_request_cases_inner - Up

-
-
-
assignees (optional)
array[assignees_inner] An array containing users that are assigned to the case.
-
connector (optional)
-
description (optional)
String An updated description for the case.
-
id
String The identifier for the case.
-
settings (optional)
-
severity (optional)
-
status (optional)
-
tags (optional)
array[String] The words and phrases that help categorize cases.
-
category (optional)
String Category for the case. It could be a word or a phrase to categorize the case.
-
title (optional)
String A title for the case.
-
version
String The current version of the case. To determine this value, use the get case or find cases APIs.
-
-
-
-

update_user_comment_request_properties - Update case comment request properties for user comments Up

-
Defines properties for case comment requests when type is user.
-
-
comment
String The new comment. It is required only when type is user.
-
id
String The identifier for the comment. To retrieve comment IDs, use the get comments API.
-
owner
-
type
String The type of comment.
-
Enum:
-
user
-
version
String The current comment version. To retrieve version values, use the get comments API.
-
-
-
-

user_actions_find_response_properties - Up

-
-
-
action
-
comment_id
-
created_at
Date format: date-time
-
created_by
-
id
-
owner
-
payload
-
version
-
type
String The type of action.
-
Enum:
-
assignees
create_case
comment
connector
description
pushed
tags
title
status
settings
severity
-
-
-
-

user_actions_response_properties - Up

-
-
-
action
-
action_id
-
case_id
-
comment_id
-
created_at
Date format: date-time
-
created_by
-
owner
-
payload
-
type
-
-
-
-

user_actions_response_properties_created_by - Up

-
-
-
email
-
full_name
-
username
-
profile_uid (optional)
-
-
-
-

user_actions_response_properties_payload - Up

-
-
-
comment (optional)
-
assignees (optional)
array[assignees_inner] An array containing users that are assigned to the case.
-
connector (optional)
-
description (optional)
-
owner (optional)
-
settings (optional)
-
severity (optional)
-
status (optional)
-
tags (optional)
-
title (optional)
-
externalService (optional)
-
-
-
-

user_comment_response_properties - Case response properties for user comments Up

-
-
-
comment (optional)
-
created_at (optional)
Date format: date-time
-
created_by (optional)
-
id (optional)
-
owner (optional)
-
pushed_at (optional)
Date format: date-time
-
pushed_by (optional)
-
type
-
Enum:
-
user
-
updated_at (optional)
Date format: date-time
-
updated_by (optional)
-
version (optional)
-
-
-
-++++ diff --git a/docs/api-generated/cases/case-apis.asciidoc b/docs/api-generated/cases/case-apis.asciidoc deleted file mode 100644 index fdd9a941a58e6f..00000000000000 --- a/docs/api-generated/cases/case-apis.asciidoc +++ /dev/null @@ -1,10 +0,0 @@ -[[case-apis]] -== Case APIs - -preview::[] - -//// -This file includes content that has been generated from https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/docs/openapi. Any modifications required must be done in that open API specification. -//// - -include::case-apis-passthru.asciidoc[] \ No newline at end of file diff --git a/docs/api-generated/connectors/connector-apis-passthru.asciidoc b/docs/api-generated/connectors/connector-apis-passthru.asciidoc deleted file mode 100644 index d3495cecf9edf1..00000000000000 --- a/docs/api-generated/connectors/connector-apis-passthru.asciidoc +++ /dev/null @@ -1,2823 +0,0 @@ -//// -This content is generated from the open API specification. -Any modifications made to this file will be overwritten. -//// - -++++ -
-

Access

-
    -
  1. APIKey KeyParamName:ApiKey KeyInQuery:false KeyInHeader:true
  2. -
  3. HTTP Basic Authentication
  4. -
- -

Methods

- [ Jump to Models ] - -

Table of Contents

-
-

Connectors

- - -

Connectors

-
-
- Up -
post /s/{spaceId}/api/actions/connector
-
Creates a connector. (createConnector)
-
You must have all privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
Create_connector_request_body_properties Create_connector_request_body_properties (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
null
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - connector_response_properties -

401

- Authorization information is missing or invalid. - Unauthorized_response -
-
-
-
- Up -
post /s/{spaceId}/api/actions/connector/{connectorId}
-
Creates a connector. (createConnectorId)
-
You must have all privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
connectorId (required)
- -
Path Parameter — A UUID v1 or v4 identifier for the connector. If you omit this parameter, an identifier is randomly generated. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
Create_connector_request_body_properties Create_connector_request_body_properties (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
null
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - connector_response_properties -

401

- Authorization information is missing or invalid. - Unauthorized_response -
-
-
-
- Up -
delete /s/{spaceId}/api/actions/connector/{connectorId}
-
Deletes a connector. (deleteConnector)
-
You must have all privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges. WARNING: When you delete a connector, it cannot be recovered.
- -

Path parameters

-
-
connectorId (required)
- -
Path Parameter — An identifier for the connector. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - Unauthorized_response -

404

- Object is not found. - getConnector_404_response -
-
-
-
- Up -
get /s/{spaceId}/api/actions/connector/{connectorId}
-
Retrieves a connector by ID. (getConnector)
-
You must have read privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges.
- -

Path parameters

-
-
connectorId (required)
- -
Path Parameter — An identifier for the connector. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
null
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - connector_response_properties -

401

- Authorization information is missing or invalid. - Unauthorized_response -

404

- Object is not found. - getConnector_404_response -
-
-
-
- Up -
get /s/{spaceId}/api/actions/connector_types
-
Retrieves a list of all connector types. (getConnectorTypes)
-
You do not need any Kibana feature privileges to run this API.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
feature_id (optional)
- -
Query Parameter — A filter to limit the retrieved connector types to those that support a specific feature (such as alerting or cases). default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "supported_feature_ids" : [ "alerting", "uptime", "siem" ],
-  "name" : "Index",
-  "enabled_in_license" : true,
-  "id" : ".server-log",
-  "enabled_in_config" : true,
-  "minimum_license_required" : "basic",
-  "enabled" : true
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - Unauthorized_response -
-
-
-
- Up -
get /s/{spaceId}/api/actions/connectors
-
Retrieves all connectors. (getConnectors)
-
You must have read privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "is_missing_secrets" : false,
-  "is_deprecated" : false,
-  "is_preconfigured" : false,
-  "name" : "my-connector",
-  "is_system_action" : false,
-  "referenced_by_count" : 2,
-  "id" : "b0766e10-d190-11ec-b04c-776c77d14fca",
-  "config" : {
-    "key" : ""
-  },
-  "connector_type_id" : ".server-log"
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - Unauthorized_response -
-
-
-
- Up -
post /s/{spaceId}/api/actions
-
Creates a connector. (legacyCreateConnector)
-
Deprecated in 7.13.0. Use the create connector API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
Legacy_create_connector_request_properties Legacy_create_connector_request_properties (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "isPreconfigured" : true,
-  "isDeprecated" : true,
-  "actionTypeId" : "actionTypeId",
-  "name" : "name",
-  "id" : "id",
-  "config" : "{}",
-  "isMissingSecrets" : true
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - action_response_properties -

401

- Authorization information is missing or invalid. - Unauthorized_response -
-
-
-
- Up -
delete /s/{spaceId}/api/actions/action/{actionId}
-
Deletes a connector. (legacyDeleteConnector)
-
Deprecated in 7.13.0. Use the delete connector API instead. WARNING: When you delete a connector, it cannot be recovered.
- -

Path parameters

-
-
actionId (required)
- -
Path Parameter — An identifier for the action. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - Unauthorized_response -
-
-
-
- Up -
get /s/{spaceId}/api/actions/action/{actionId}
-
Retrieves a connector by ID. (legacyGetConnector)
-
Deprecated in 7.13.0. Use the get connector API instead.
- -

Path parameters

-
-
actionId (required)
- -
Path Parameter — An identifier for the action. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "isPreconfigured" : true,
-  "isDeprecated" : true,
-  "actionTypeId" : "actionTypeId",
-  "name" : "name",
-  "id" : "id",
-  "config" : "{}",
-  "isMissingSecrets" : true
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - action_response_properties -

401

- Authorization information is missing or invalid. - Unauthorized_response -
-
-
-
- Up -
get /s/{spaceId}/api/actions/list_action_types
-
Retrieves a list of all connector types. (legacyGetConnectorTypes)
-
Deprecated in 7.13.0. Use the get all connector types API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "enabledInConfig" : true,
-  "name" : "name",
-  "enabledInLicense" : true,
-  "id" : "id",
-  "minimumLicenseRequired" : "minimumLicenseRequired",
-  "enabled" : true
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - Unauthorized_response -
-
-
-
- Up -
get /s/{spaceId}/api/actions
-
Retrieves all connectors. (legacyGetConnectors)
-
Deprecated in 7.13.0. Use the get all connectors API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "isPreconfigured" : true,
-  "isDeprecated" : true,
-  "actionTypeId" : "actionTypeId",
-  "name" : "name",
-  "id" : "id",
-  "config" : "{}",
-  "isMissingSecrets" : true
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - Unauthorized_response -
-
-
-
- Up -
post /s/{spaceId}/api/actions/action/{actionId}/_execute
-
Runs a connector. (legacyRunConnector)
-
Deprecated in 7.13.0. Use the run connector API instead.
- -

Path parameters

-
-
actionId (required)
- -
Path Parameter — An identifier for the action. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
Legacy_run_connector_request_body_properties Legacy_run_connector_request_body_properties (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "actionId" : "actionId",
-  "status" : "status"
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - legacyRunConnector_200_response -

401

- Authorization information is missing or invalid. - Unauthorized_response -
-
-
-
- Up -
put /s/{spaceId}/api/actions/action/{actionId}
-
Updates the attributes for a connector. (legacyUpdateConnector)
-
Deprecated in 7.13.0. Use the update connector API instead.
- -

Path parameters

-
-
actionId (required)
- -
Path Parameter — An identifier for the action. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
Legacy_update_connector_request_body_properties Legacy_update_connector_request_body_properties (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "isPreconfigured" : true,
-  "isDeprecated" : true,
-  "actionTypeId" : "actionTypeId",
-  "name" : "name",
-  "id" : "id",
-  "config" : "{}",
-  "isMissingSecrets" : true
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - action_response_properties -

404

- Object is not found. - Not_found_response -
-
-
-
- Up -
post /s/{spaceId}/api/actions/connector/{connectorId}/_execute
-
Runs a connector. (runConnector)
-
You can use this API to test an action that involves interaction with Kibana services or integrations with third-party systems. You must have read privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges. If you use an index connector, you must also have all, create, index, or write indices privileges.
- -

Path parameters

-
-
connectorId (required)
- -
Path Parameter — An identifier for the connector. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
Run_connector_request_body_properties Run_connector_request_body_properties (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "connector_id" : "connector_id",
-  "status" : "error"
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - runConnector_200_response -

401

- Authorization information is missing or invalid. - Unauthorized_response -
-
-
-
- Up -
put /s/{spaceId}/api/actions/connector/{connectorId}
-
Updates the attributes for a connector. (updateConnector)
-
You must have all privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges.
- -

Path parameters

-
-
connectorId (required)
- -
Path Parameter — An identifier for the connector. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
Update_connector_request_body_properties Update_connector_request_body_properties (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
null
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - connector_response_properties -

400

- Indicates a bad request. - updateConnector_400_response -

401

- Authorization information is missing or invalid. - Unauthorized_response -

404

- Object is not found. - Not_found_response -
-
- -

Models

- [ Jump to Methods ] - -

Table of Contents

-
    -
  1. Alert_identifier_mapping - Alert identifier mapping
  2. -
  3. Case_comment_mapping - Case comment mapping
  4. -
  5. Case_description_mapping - Case description mapping
  6. -
  7. Case_identifier_mapping - Case identifier mapping
  8. -
  9. Case_name_mapping - Case name mapping
  10. -
  11. Connector_mappings_properties_for_a_Swimlane_connector - Connector mappings properties for a Swimlane connector
  12. -
  13. Create_connector_request_body_properties - Create connector request body properties
  14. -
  15. Get_connector_types_response_body_properties_inner -
  16. -
  17. Get_connectors_response_body_properties - Get connectors response body properties
  18. -
  19. Legacy_create_connector_request_properties - Legacy create connector request properties
  20. -
  21. Legacy_get_connector_types_response_body_properties_inner -
  22. -
  23. Legacy_run_connector_request_body_properties - Legacy run connector request body properties
  24. -
  25. Legacy_update_connector_request_body_properties - Legacy update connector request body properties
  26. -
  27. Not_found_response - Not found response
  28. -
  29. Rule_name_mapping - Rule name mapping
  30. -
  31. Run_connector_request_body_properties - Run connector request body properties
  32. -
  33. Run_connector_request_body_properties_params -
  34. -
  35. Severity_mapping - Severity mapping
  36. -
  37. Subaction_parameters - Subaction parameters
  38. -
  39. Unauthorized_response - Unauthorized response
  40. -
  41. Update_connector_request_body_properties - Update connector request body properties
  42. -
  43. action_response_properties - Action response properties
  44. -
  45. config_properties_cases_webhook - Connector request properties for Webhook - Case Management connector
  46. -
  47. config_properties_d3security - Connector request properties for a D3 Security connector
  48. -
  49. config_properties_email - Connector request properties for an email connector
  50. -
  51. config_properties_genai - Connector request properties for an OpenAI connector
  52. -
  53. config_properties_genai_oneOf -
  54. -
  55. config_properties_genai_oneOf_1 -
  56. -
  57. config_properties_index - Connector request properties for an index connector
  58. -
  59. config_properties_jira - Connector request properties for a Jira connector
  60. -
  61. config_properties_opsgenie - Connector request properties for an Opsgenie connector
  62. -
  63. config_properties_pagerduty - Connector request properties for a PagerDuty connector
  64. -
  65. config_properties_resilient - Connector request properties for a IBM Resilient connector
  66. -
  67. config_properties_servicenow - Connector request properties for a ServiceNow ITSM connector
  68. -
  69. config_properties_servicenow_itom - Connector request properties for a ServiceNow ITSM connector
  70. -
  71. config_properties_swimlane - Connector request properties for a Swimlane connector
  72. -
  73. config_properties_tines - Connector request properties for a Tines connector
  74. -
  75. config_properties_torq - Connector request properties for a Torq connector
  76. -
  77. config_properties_webhook - Connector request properties for a Webhook connector
  78. -
  79. config_properties_xmatters - Connector request properties for an xMatters connector
  80. -
  81. connector_response_properties - Connector response properties
  82. -
  83. connector_response_properties_cases_webhook - Connector request properties for a Webhook - Case Management connector
  84. -
  85. connector_response_properties_d3security - Connector response properties for a D3 Security connector
  86. -
  87. connector_response_properties_email - Connector response properties for an email connector
  88. -
  89. connector_response_properties_index - Connector response properties for an index connector
  90. -
  91. connector_response_properties_jira - Connector response properties for a Jira connector
  92. -
  93. connector_response_properties_opsgenie - Connector response properties for an Opsgenie connector
  94. -
  95. connector_response_properties_pagerduty - Connector response properties for a PagerDuty connector
  96. -
  97. connector_response_properties_resilient - Connector response properties for a IBM Resilient connector
  98. -
  99. connector_response_properties_serverlog - Connector response properties for a server log connector
  100. -
  101. connector_response_properties_servicenow - Connector response properties for a ServiceNow ITSM connector
  102. -
  103. connector_response_properties_servicenow_itom - Connector response properties for a ServiceNow ITOM connector
  104. -
  105. connector_response_properties_servicenow_sir - Connector response properties for a ServiceNow SecOps connector
  106. -
  107. connector_response_properties_slack_api - Connector response properties for a Slack connector
  108. -
  109. connector_response_properties_slack_webhook - Connector response properties for a Slack connector
  110. -
  111. connector_response_properties_swimlane - Connector response properties for a Swimlane connector
  112. -
  113. connector_response_properties_teams - Connector response properties for a Microsoft Teams connector
  114. -
  115. connector_response_properties_tines - Connector response properties for a Tines connector
  116. -
  117. connector_response_properties_torq - Connector response properties for a Torq connector
  118. -
  119. connector_response_properties_webhook - Connector response properties for a Webhook connector
  120. -
  121. connector_response_properties_xmatters - Connector response properties for an xMatters connector
  122. -
  123. connector_types - Connector types
  124. -
  125. create_connector_request_cases_webhook - Create Webhook - Case Managment connector request
  126. -
  127. create_connector_request_d3security - Create D3 Security connector request
  128. -
  129. create_connector_request_email - Create email connector request
  130. -
  131. create_connector_request_genai - Create OpenAI connector request
  132. -
  133. create_connector_request_index - Create index connector request
  134. -
  135. create_connector_request_jira - Create Jira connector request
  136. -
  137. create_connector_request_opsgenie - Create Opsgenie connector request
  138. -
  139. create_connector_request_pagerduty - Create PagerDuty connector request
  140. -
  141. create_connector_request_resilient - Create IBM Resilient connector request
  142. -
  143. create_connector_request_serverlog - Create server log connector request
  144. -
  145. create_connector_request_servicenow - Create ServiceNow ITSM connector request
  146. -
  147. create_connector_request_servicenow_itom - Create ServiceNow ITOM connector request
  148. -
  149. create_connector_request_servicenow_sir - Create ServiceNow SecOps connector request
  150. -
  151. create_connector_request_slack_api - Create Slack connector request
  152. -
  153. create_connector_request_slack_webhook - Create Slack connector request
  154. -
  155. create_connector_request_swimlane - Create Swimlane connector request
  156. -
  157. create_connector_request_teams - Create Microsoft Teams connector request
  158. -
  159. create_connector_request_tines - Create Tines connector request
  160. -
  161. create_connector_request_torq - Create Torq connector request
  162. -
  163. create_connector_request_webhook - Create Webhook connector request
  164. -
  165. create_connector_request_xmatters - Create xMatters connector request
  166. -
  167. features -
  168. -
  169. getConnector_404_response -
  170. -
  171. legacyRunConnector_200_response -
  172. -
  173. runConnector_200_response -
  174. -
  175. runConnector_200_response_data -
  176. -
  177. run_connector_params_documents - Index connector parameters
  178. -
  179. run_connector_params_level_message - Server log connector parameters
  180. -
  181. run_connector_subaction_addevent - The addEvent subaction
  182. -
  183. run_connector_subaction_addevent_subActionParams -
  184. -
  185. run_connector_subaction_closealert - The closeAlert subaction
  186. -
  187. run_connector_subaction_closealert_subActionParams -
  188. -
  189. run_connector_subaction_createalert - The createAlert subaction
  190. -
  191. run_connector_subaction_createalert_subActionParams -
  192. -
  193. run_connector_subaction_createalert_subActionParams_responders_inner -
  194. -
  195. run_connector_subaction_createalert_subActionParams_visibleTo_inner -
  196. -
  197. run_connector_subaction_fieldsbyissuetype - The fieldsByIssueType subaction
  198. -
  199. run_connector_subaction_fieldsbyissuetype_subActionParams -
  200. -
  201. run_connector_subaction_getchoices - The getChoices subaction
  202. -
  203. run_connector_subaction_getchoices_subActionParams -
  204. -
  205. run_connector_subaction_getfields - The getFields subaction
  206. -
  207. run_connector_subaction_getincident - The getIncident subaction
  208. -
  209. run_connector_subaction_getincident_subActionParams -
  210. -
  211. run_connector_subaction_issue - The issue subaction
  212. -
  213. run_connector_subaction_issue_subActionParams -
  214. -
  215. run_connector_subaction_issues - The issues subaction
  216. -
  217. run_connector_subaction_issues_subActionParams -
  218. -
  219. run_connector_subaction_issuetypes - The issueTypes subaction
  220. -
  221. run_connector_subaction_pushtoservice - The pushToService subaction
  222. -
  223. run_connector_subaction_pushtoservice_subActionParams -
  224. -
  225. run_connector_subaction_pushtoservice_subActionParams_comments_inner -
  226. -
  227. run_connector_subaction_pushtoservice_subActionParams_incident -
  228. -
  229. run_connector_subaction_pushtoservice_subActionParams_incident_dest_ip -
  230. -
  231. run_connector_subaction_pushtoservice_subActionParams_incident_malware_hash -
  232. -
  233. run_connector_subaction_pushtoservice_subActionParams_incident_malware_url -
  234. -
  235. run_connector_subaction_pushtoservice_subActionParams_incident_source_ip -
  236. -
  237. secrets_properties_cases_webhook - Connector secrets properties for Webhook - Case Management connector
  238. -
  239. secrets_properties_d3security - Connector secrets properties for a D3 Security connector
  240. -
  241. secrets_properties_email - Connector secrets properties for an email connector
  242. -
  243. secrets_properties_genai - Connector secrets properties for an OpenAI connector
  244. -
  245. secrets_properties_jira - Connector secrets properties for a Jira connector
  246. -
  247. secrets_properties_opsgenie - Connector secrets properties for an Opsgenie connector
  248. -
  249. secrets_properties_pagerduty - Connector secrets properties for a PagerDuty connector
  250. -
  251. secrets_properties_resilient - Connector secrets properties for IBM Resilient connector
  252. -
  253. secrets_properties_servicenow - Connector secrets properties for ServiceNow ITOM, ServiceNow ITSM, and ServiceNow SecOps connectors
  254. -
  255. secrets_properties_slack_api - Connector secrets properties for a Web API Slack connector
  256. -
  257. secrets_properties_slack_webhook - Connector secrets properties for a Webhook Slack connector
  258. -
  259. secrets_properties_swimlane - Connector secrets properties for a Swimlane connector
  260. -
  261. secrets_properties_teams - Connector secrets properties for a Microsoft Teams connector
  262. -
  263. secrets_properties_tines - Connector secrets properties for a Tines connector
  264. -
  265. secrets_properties_torq - Connector secrets properties for a Torq connector
  266. -
  267. secrets_properties_webhook - Connector secrets properties for a Webhook connector
  268. -
  269. secrets_properties_xmatters - Connector secrets properties for an xMatters connector
  270. -
  271. updateConnector_400_response -
  272. -
  273. update_connector_request_cases_webhook - Update Webhook - Case Managment connector request
  274. -
  275. update_connector_request_d3security - Update D3 Security connector request
  276. -
  277. update_connector_request_email - Update email connector request
  278. -
  279. update_connector_request_index - Update index connector request
  280. -
  281. update_connector_request_jira - Update Jira connector request
  282. -
  283. update_connector_request_opsgenie - Update Opsgenie connector request
  284. -
  285. update_connector_request_pagerduty - Update PagerDuty connector request
  286. -
  287. update_connector_request_resilient - Update IBM Resilient connector request
  288. -
  289. update_connector_request_serverlog - Update server log connector request
  290. -
  291. update_connector_request_servicenow - Update ServiceNow ITSM connector or ServiceNow SecOps request
  292. -
  293. update_connector_request_servicenow_itom - Create ServiceNow ITOM connector request
  294. -
  295. update_connector_request_slack_api - Update Slack connector request
  296. -
  297. update_connector_request_slack_webhook - Update Slack connector request
  298. -
  299. update_connector_request_swimlane - Update Swimlane connector request
  300. -
  301. update_connector_request_teams - Update Microsoft Teams connector request
  302. -
  303. update_connector_request_tines - Update Tines connector request
  304. -
  305. update_connector_request_torq - Update Torq connector request
  306. -
  307. update_connector_request_webhook - Update Webhook connector request
  308. -
  309. update_connector_request_xmatters - Update xMatters connector request
  310. -
- -
-

Alert_identifier_mapping - Alert identifier mapping Up

-
Mapping for the alert ID.
-
-
fieldType
String The type of field in Swimlane.
-
id
String The identifier for the field in Swimlane.
-
key
String The key for the field in Swimlane.
-
name
String The name of the field in Swimlane.
-
-
-
-

Case_comment_mapping - Case comment mapping Up

-
Mapping for the case comments.
-
-
fieldType
String The type of field in Swimlane.
-
id
String The identifier for the field in Swimlane.
-
key
String The key for the field in Swimlane.
-
name
String The name of the field in Swimlane.
-
-
-
-

Case_description_mapping - Case description mapping Up

-
Mapping for the case description.
-
-
fieldType
String The type of field in Swimlane.
-
id
String The identifier for the field in Swimlane.
-
key
String The key for the field in Swimlane.
-
name
String The name of the field in Swimlane.
-
-
-
-

Case_identifier_mapping - Case identifier mapping Up

-
Mapping for the case ID.
-
-
fieldType
String The type of field in Swimlane.
-
id
String The identifier for the field in Swimlane.
-
key
String The key for the field in Swimlane.
-
name
String The name of the field in Swimlane.
-
-
-
-

Case_name_mapping - Case name mapping Up

-
Mapping for the case name.
-
-
fieldType
String The type of field in Swimlane.
-
id
String The identifier for the field in Swimlane.
-
key
String The key for the field in Swimlane.
-
name
String The name of the field in Swimlane.
-
-
-
-

Connector_mappings_properties_for_a_Swimlane_connector - Connector mappings properties for a Swimlane connector Up

-
The field mapping.
-
-
alertIdConfig (optional)
-
caseIdConfig (optional)
-
caseNameConfig (optional)
-
commentsConfig (optional)
-
descriptionConfig (optional)
-
ruleNameConfig (optional)
-
severityConfig (optional)
-
-
-
-

Create_connector_request_body_properties - Create connector request body properties Up

-
The properties vary depending on the connector type.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.xmatters
-
name
String The display name for the connector.
-
secrets
-
-
-
-

Get_connector_types_response_body_properties_inner - Up

-
-
-
enabled (optional)
Boolean Indicates whether the connector type is enabled in Kibana.
-
enabled_in_config (optional)
Boolean Indicates whether the connector type is enabled in the Kibana .yml file.
-
enabled_in_license (optional)
Boolean Indicates whether the connector is enabled in the license.
-
id (optional)
-
minimum_license_required (optional)
String The license that is required to use the connector type.
-
name (optional)
String The name of the connector type.
-
supported_feature_ids (optional)
array[features] The Kibana features that are supported by the connector type.
-
-
-
-

Get_connectors_response_body_properties - Get connectors response body properties Up

-
The properties vary for each connector type.
-
-
connector_type_id
-
config (optional)
map[String, oas_any_type_not_mapped] The configuration for the connector. Configuration properties vary depending on the connector type.
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
referenced_by_count
Integer Indicates the number of saved objects that reference the connector. If is_preconfigured is true, this value is not calculated.
-
-
-
-

Legacy_create_connector_request_properties - Legacy create connector request properties Up

-
-
-
actionTypeId (optional)
String The connector type identifier.
-
config (optional)
Object The configuration for the connector. Configuration properties vary depending on the connector type.
-
name (optional)
String The display name for the connector.
-
secrets (optional)
Object The secrets configuration for the connector. Secrets configuration properties vary depending on the connector type. NOTE: Remember these values. You must provide them each time you update the connector.
-
-
-
-

Legacy_get_connector_types_response_body_properties_inner - Up

-
-
-
enabled (optional)
Boolean Indicates whether the connector type is enabled in Kibana.
-
enabledInConfig (optional)
Boolean Indicates whether the connector type is enabled in the Kibana .yml file.
-
enabledInLicense (optional)
Boolean Indicates whether the connector is enabled in the license.
-
id (optional)
String The unique identifier for the connector type.
-
minimumLicenseRequired (optional)
String The license that is required to use the connector type.
-
name (optional)
String The name of the connector type.
-
-
-
-

Legacy_run_connector_request_body_properties - Legacy run connector request body properties Up

-
The properties vary depending on the connector type.
-
-
params
Object The parameters of the connector. Parameter properties vary depending on the connector type.
-
-
-
-

Legacy_update_connector_request_body_properties - Legacy update connector request body properties Up

-
The properties vary depending on the connector type.
-
-
config (optional)
Object The new connector configuration. Configuration properties vary depending on the connector type.
-
name (optional)
String The new name for the connector.
-
secrets (optional)
Object The updated secrets configuration for the connector. Secrets properties vary depending on the connector type.
-
-
-
-

Not_found_response - Not found response Up

-
-
-
error (optional)
-
Enum:
-
Not Found
-
message (optional)
-
statusCode (optional)
-
Enum:
-
404
-
-
-
-

Rule_name_mapping - Rule name mapping Up

-
Mapping for the name of the alert's rule.
-
-
fieldType
String The type of field in Swimlane.
-
id
String The identifier for the field in Swimlane.
-
key
String The key for the field in Swimlane.
-
name
String The name of the field in Swimlane.
-
-
- -
-

Run_connector_request_body_properties_params - Up

-
-
-
documents
array[map[String, oas_any_type_not_mapped]] The documents in JSON format for index connectors.
-
level (optional)
String The log level of the message for server log connectors.
-
Enum:
-
debug
error
fatal
info
trace
warn
-
message
String The message for server log connectors.
-
subAction
String The action to test.
-
Enum:
-
pushToService
-
subActionParams
-
-
-
-

Severity_mapping - Severity mapping Up

-
Mapping for the severity.
-
-
fieldType
String The type of field in Swimlane.
-
id
String The identifier for the field in Swimlane.
-
key
String The key for the field in Swimlane.
-
name
String The name of the field in Swimlane.
-
-
-
-

Subaction_parameters - Subaction parameters Up

-
Test an action that involves a subaction.
-
-
subAction
String The action to test.
-
Enum:
-
pushToService
-
subActionParams
-
-
-
-

Unauthorized_response - Unauthorized response Up

-
-
-
error (optional)
-
Enum:
-
Unauthorized
-
message (optional)
-
statusCode (optional)
-
Enum:
-
401
-
-
-
-

Update_connector_request_body_properties - Update connector request body properties Up

-
The properties vary depending on the connector type.
-
-
config
-
name
String The display name for the connector.
-
secrets
-
connector_type_id
String The type of connector.
-
Enum:
-
.gen-ai
-
-
-
-

action_response_properties - Action response properties Up

-
The properties vary depending on the action type.
-
-
actionTypeId (optional)
-
config (optional)
-
id (optional)
-
isDeprecated (optional)
Boolean Indicates whether the action type is deprecated.
-
isMissingSecrets (optional)
Boolean Indicates whether secrets are missing for the action.
-
isPreconfigured (optional)
Boolean Indicates whether it is a preconfigured action.
-
name (optional)
-
-
-
-

config_properties_cases_webhook - Connector request properties for Webhook - Case Management connector Up

-
Defines properties for connectors when type is .cases-webhook.
-
-
createCommentJson (optional)
String A JSON payload sent to the create comment URL to create a case comment. You can use variables to add Kibana Cases data to the payload. The required variable is case.comment. Due to Mustache template variables (the text enclosed in triple braces, for example, {{{case.title}}}), the JSON is not validated when you create the connector. The JSON is validated once the Mustache variables have been placed when the REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass.
-
createCommentMethod (optional)
String The REST API HTTP request method to create a case comment in the third-party system. Valid values are patch, post, and put.
-
Enum:
-
patch
post
put
-
createCommentUrl (optional)
String The REST API URL to create a case comment by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the xpack.actions.allowedHosts setting, add the hostname to the allowed hosts.
-
createIncidentJson
String A JSON payload sent to the create case URL to create a case. You can use variables to add case data to the payload. Required variables are case.title and case.description. Due to Mustache template variables (which is the text enclosed in triple braces, for example, {{{case.title}}}), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review.
-
createIncidentMethod (optional)
String The REST API HTTP request method to create a case in the third-party system. Valid values are patch, post, and put.
-
Enum:
-
patch
post
put
-
createIncidentResponseKey
String The JSON key in the create case response that contains the external case ID.
-
createIncidentUrl
String The REST API URL to create a case in the third-party system. If you are using the xpack.actions.allowedHosts setting, add the hostname to the allowed hosts.
-
getIncidentResponseExternalTitleKey
String The JSON key in get case response that contains the external case title.
-
getIncidentUrl
String The REST API URL to get the case by ID from the third-party system. If you are using the xpack.actions.allowedHosts setting, add the hostname to the allowed hosts. You can use a variable to add the external system ID to the URL. Due to Mustache template variables (the text enclosed in triple braces, for example, {{{case.title}}}), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid, disregarding the Mustache variables, so the later validation will pass.
-
hasAuth (optional)
Boolean If true, a username and password for login type authentication must be provided.
-
headers (optional)
String A set of key-value pairs sent as headers with the request URLs for the create case, update case, get case, and create comment methods.
-
updateIncidentJson
String The JSON payload sent to the update case URL to update the case. You can use variables to add Kibana Cases data to the payload. Required variables are case.title and case.description. Due to Mustache template variables (which is the text enclosed in triple braces, for example, {{{case.title}}}), the JSON is not validated when you create the connector. The JSON is validated after the Mustache variables have been placed when REST method runs. Manually ensure that the JSON is valid to avoid future validation errors; disregard Mustache variables during your review.
-
updateIncidentMethod (optional)
String The REST API HTTP request method to update the case in the third-party system. Valid values are patch, post, and put.
-
Enum:
-
patch
post
put
-
updateIncidentUrl
String The REST API URL to update the case by ID in the third-party system. You can use a variable to add the external system ID to the URL. If you are using the xpack.actions.allowedHosts setting, add the hostname to the allowed hosts.
-
viewIncidentUrl
String The URL to view the case in the external system. You can use variables to add the external system ID or external system title to the URL.
-
-
-
-

config_properties_d3security - Connector request properties for a D3 Security connector Up

-
Defines properties for connectors when type is .d3security.
-
-
url
String The D3 Security API request URL. If you are using the xpack.actions.allowedHosts setting, add the hostname to the allowed hosts.
-
-
-
-

config_properties_email - Connector request properties for an email connector Up

-
Defines properties for connectors when type is .email.
-
-
clientId (optional)
String The client identifier, which is a part of OAuth 2.0 client credentials authentication, in GUID format. If service is exchange_server, this property is required.
-
from
String The from address for all emails sent by the connector. It must be specified in user@host-name format.
-
hasAuth (optional)
Boolean Specifies whether a user and password are required inside the secrets configuration.
-
host (optional)
String The host name of the service provider. If the service is elastic_cloud (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If service is other, this property must be defined.
-
oauthTokenUrl (optional)
-
port (optional)
Integer The port to connect to on the service provider. If the service is elastic_cloud (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored. If service is other, this property must be defined.
-
secure (optional)
Boolean Specifies whether the connection to the service provider will use TLS. If the service is elastic_cloud (for Elastic Cloud notifications) or one of Nodemailer's well-known email service providers, this property is ignored.
-
service (optional)
String The name of the email service.
-
Enum:
-
elastic_cloud
exchange_server
gmail
other
outlook365
ses
-
tenantId (optional)
String The tenant identifier, which is part of OAuth 2.0 client credentials authentication, in GUID format. If service is exchange_server, this property is required.
-
-
-
-

config_properties_genai - Connector request properties for an OpenAI connector Up

-
Defines properties for connectors when type is .gen-ai.
-
-
apiProvider
String The OpenAI API provider.
-
Enum:
-
OpenAI
-
apiUrl
String The OpenAI API endpoint.
-
defaultModel (optional)
String The default model to use for requests.
-
-
-
-

config_properties_genai_oneOf - Up

-
-
-
apiProvider
String The OpenAI API provider.
-
Enum:
-
Azure OpenAI
-
apiUrl
String The OpenAI API endpoint.
-
-
-
-

config_properties_genai_oneOf_1 - Up

-
-
-
apiProvider
String The OpenAI API provider.
-
Enum:
-
OpenAI
-
apiUrl
String The OpenAI API endpoint.
-
defaultModel (optional)
String The default model to use for requests.
-
-
-
-

config_properties_index - Connector request properties for an index connector Up

-
Defines properties for connectors when type is .index.
-
-
executionTimeField (optional)
String A field that indicates when the document was indexed.
-
index
String The Elasticsearch index to be written to.
-
refresh (optional)
Boolean The refresh policy for the write request, which affects when changes are made visible to search. Refer to the refresh setting for Elasticsearch document APIs.
-
-
-
-

config_properties_jira - Connector request properties for a Jira connector Up

-
Defines properties for connectors when type is .jira.
-
-
apiUrl
String The Jira instance URL.
-
projectKey
String The Jira project key.
-
-
-
-

config_properties_opsgenie - Connector request properties for an Opsgenie connector Up

-
Defines properties for connectors when type is .opsgenie.
-
-
apiUrl
String The Opsgenie URL. For example, https://api.opsgenie.com or https://api.eu.opsgenie.com. If you are using the xpack.actions.allowedHosts setting, add the hostname to the allowed hosts.
-
-
-
-

config_properties_pagerduty - Connector request properties for a PagerDuty connector Up

-
Defines properties for connectors when type is .pagerduty.
-
-
apiUrl (optional)
String The PagerDuty event URL.
-
-
-
-

config_properties_resilient - Connector request properties for a IBM Resilient connector Up

-
Defines properties for connectors when type is .resilient.
-
-
apiUrl
String The IBM Resilient instance URL.
-
orgId
String The IBM Resilient organization ID.
-
-
-
-

config_properties_servicenow - Connector request properties for a ServiceNow ITSM connector Up

-
Defines properties for connectors when type is .servicenow.
-
-
apiUrl
String The ServiceNow instance URL.
-
clientId (optional)
String The client ID assigned to your OAuth application. This property is required when isOAuth is true.
-
isOAuth (optional)
Boolean The type of authentication to use. The default value is false, which means basic authentication is used instead of open authorization (OAuth).
-
jwtKeyId (optional)
String The key identifier assigned to the JWT verifier map of your OAuth application. This property is required when isOAuth is true.
-
userIdentifierValue (optional)
String The identifier to use for OAuth authentication. This identifier should be the user field you selected when you created an OAuth JWT API endpoint for external clients in your ServiceNow instance. For example, if the selected user field is Email, the user identifier should be the user's email address. This property is required when isOAuth is true.
-
usesTableApi (optional)
Boolean Determines whether the connector uses the Table API or the Import Set API. This property is supported only for ServiceNow ITSM and ServiceNow SecOps connectors. NOTE: If this property is set to false, the Elastic application should be installed in ServiceNow.
-
-
-
-

config_properties_servicenow_itom - Connector request properties for a ServiceNow ITSM connector Up

-
Defines properties for connectors when type is .servicenow.
-
-
apiUrl
String The ServiceNow instance URL.
-
clientId (optional)
String The client ID assigned to your OAuth application. This property is required when isOAuth is true.
-
isOAuth (optional)
Boolean The type of authentication to use. The default value is false, which means basic authentication is used instead of open authorization (OAuth).
-
jwtKeyId (optional)
String The key identifier assigned to the JWT verifier map of your OAuth application. This property is required when isOAuth is true.
-
userIdentifierValue (optional)
String The identifier to use for OAuth authentication. This identifier should be the user field you selected when you created an OAuth JWT API endpoint for external clients in your ServiceNow instance. For example, if the selected user field is Email, the user identifier should be the user's email address. This property is required when isOAuth is true.
-
-
-
-

config_properties_swimlane - Connector request properties for a Swimlane connector Up

-
Defines properties for connectors when type is .swimlane.
-
-
apiUrl
String The Swimlane instance URL.
-
appId
String The Swimlane application ID.
-
connectorType
String The type of connector. Valid values are all, alerts, and cases.
-
Enum:
-
all
alerts
cases
-
mappings (optional)
-
-
-
-

config_properties_tines - Connector request properties for a Tines connector Up

-
Defines properties for connectors when type is .tines.
-
-
url
String The Tines tenant URL. If you are using the xpack.actions.allowedHosts setting, make sure this hostname is added to the allowed hosts.
-
-
-
-

config_properties_torq - Connector request properties for a Torq connector Up

-
Defines properties for connectors when type is .torq.
-
-
webhookIntegrationUrl
String The endpoint URL of the Elastic Security integration in Torq.
-
-
-
-

config_properties_webhook - Connector request properties for a Webhook connector Up

-
Defines properties for connectors when type is .webhook.
-
-
authType (optional)
String The type of authentication to use: basic, SSL, or none.
-
Enum:
-
webhook-authentication-basic
webhook-authentication-ssl
null
-
ca (optional)
String A base64 encoded version of the certificate authority file that the connector can trust to sign and validate certificates. This option is available for all authentication types.
-
certType (optional)
String If the authType is webhook-authentication-ssl, specifies whether the certificate authentication data is in a CRT and key file format or a PFX file format.
-
Enum:
-
ssl-crt-key
ssl-pfx
-
hasAuth (optional)
Boolean If true, a user name and password must be provided for login type authentication.
-
headers (optional)
Object A set of key-value pairs sent as headers with the request.
-
method (optional)
String The HTTP request method, either post or put.
-
Enum:
-
post
put
-
url (optional)
String The request URL. If you are using the xpack.actions.allowedHosts setting, add the hostname to the allowed hosts.
-
verificationMode (optional)
String Controls the verification of certificates. Use full to validate that the certificate has an issue date within the not_before and not_after dates, chains to a trusted certificate authority (CA), and has a hostname or IP address that matches the names within the certificate. Use certificate to validate the certificate and verify that it is signed by a trusted authority; this option does not check the certificate hostname. Use none to skip certificate validation.
-
Enum:
-
certificate
full
none
-
-
-
-

config_properties_xmatters - Connector request properties for an xMatters connector Up

-
Defines properties for connectors when type is .xmatters.
-
-
configUrl (optional)
String The request URL for the Elastic Alerts trigger in xMatters. It is applicable only when usesBasic is true.
-
usesBasic (optional)
Boolean Specifies whether the connector uses HTTP basic authentication (true) or URL authentication (false).
-
-
-
-

connector_response_properties - Connector response properties Up

-
The properties vary depending on the connector type.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.xmatters
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_cases_webhook - Connector request properties for a Webhook - Case Management connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.cases-webhook
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_d3security - Connector response properties for a D3 Security connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.d3security
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_email - Connector response properties for an email connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.email
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_index - Connector response properties for an index connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.index
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_jira - Connector response properties for a Jira connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.jira
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_opsgenie - Connector response properties for an Opsgenie connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.opsgenie
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_pagerduty - Connector response properties for a PagerDuty connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.pagerduty
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_resilient - Connector response properties for a IBM Resilient connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.resilient
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_serverlog - Connector response properties for a server log connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.server-log
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_servicenow - Connector response properties for a ServiceNow ITSM connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.servicenow
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_servicenow_itom - Connector response properties for a ServiceNow ITOM connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.servicenow-itom
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_servicenow_sir - Connector response properties for a ServiceNow SecOps connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.servicenow-sir
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_slack_api - Connector response properties for a Slack connector Up

-
-
-
connector_type_id
String The type of connector.
-
Enum:
-
.slack_api
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_slack_webhook - Connector response properties for a Slack connector Up

-
-
-
connector_type_id
String The type of connector.
-
Enum:
-
.slack
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_swimlane - Connector response properties for a Swimlane connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.swimlane
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_teams - Connector response properties for a Microsoft Teams connector Up

-
-
-
config (optional)
-
connector_type_id
String The type of connector.
-
Enum:
-
.teams
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_tines - Connector response properties for a Tines connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.tines
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_torq - Connector response properties for a Torq connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.torq
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_webhook - Connector response properties for a Webhook connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.webhook
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_response_properties_xmatters - Connector response properties for an xMatters connector Up

-
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.xmatters
-
id
String The identifier for the connector.
-
is_deprecated
Boolean Indicates whether the connector type is deprecated.
-
is_missing_secrets (optional)
Boolean Indicates whether secrets are missing for the connector. Secrets configuration properties vary depending on the connector type.
-
is_preconfigured
Boolean Indicates whether it is a preconfigured connector. If true, the config and is_missing_secrets properties are omitted from the response.
-
is_system_action (optional)
Boolean Indicates whether the connector is used for system actions.
-
name
String The display name for the connector.
-
-
-
-

connector_types - Connector types Up

-
The type of connector. For example, .email, .index, .jira, .opsgenie, or .server-log.
-
-
-
-
-

create_connector_request_cases_webhook - Create Webhook - Case Managment connector request Up

-
The Webhook - Case Management connector uses axios to send POST, PUT, and GET requests to a case management RESTful API web service.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.cases-webhook
-
name
String The display name for the connector.
-
secrets (optional)
-
-
-
-

create_connector_request_d3security - Create D3 Security connector request Up

-
The connector uses axios to send a POST request to a D3 Security endpoint.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.d3security
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_email - Create email connector request Up

-
The email connector uses the SMTP protocol to send mail messages, using an integration of Nodemailer. An exception is Microsoft Exchange, which uses HTTP protocol for sending emails, Send mail. Email message text is sent as both plain text and html text.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.email
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_genai - Create OpenAI connector request Up

-
The OpenAI connector uses axios to send a POST request to either OpenAI or Azure OpenAPI.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.gen-ai
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_index - Create index connector request Up

-
The index connector indexes a document into Elasticsearch.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.index
-
name
String The display name for the connector.
-
-
-
-

create_connector_request_jira - Create Jira connector request Up

-
The Jira connector uses the REST API v2 to create Jira issues.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.jira
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_opsgenie - Create Opsgenie connector request Up

-
The Opsgenie connector uses the Opsgenie alert API.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.opsgenie
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_pagerduty - Create PagerDuty connector request Up

-
The PagerDuty connector uses the v2 Events API to trigger, acknowledge, and resolve PagerDuty alerts.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.pagerduty
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_resilient - Create IBM Resilient connector request Up

-
The IBM Resilient connector uses the RESILIENT REST v2 to create IBM Resilient incidents.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.resilient
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_serverlog - Create server log connector request Up

-
This connector writes an entry to the Kibana server log.
-
-
connector_type_id
String The type of connector.
-
Enum:
-
.server-log
-
name
String The display name for the connector.
-
-
-
-

create_connector_request_servicenow - Create ServiceNow ITSM connector request Up

-
The ServiceNow ITSM connector uses the import set API to create ServiceNow incidents. You can use the connector for rule actions and cases.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.servicenow
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_servicenow_itom - Create ServiceNow ITOM connector request Up

-
The ServiceNow ITOM connector uses the event API to create ServiceNow events. You can use the connector for rule actions.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.servicenow-itom
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_servicenow_sir - Create ServiceNow SecOps connector request Up

-
The ServiceNow SecOps connector uses the import set API to create ServiceNow security incidents. You can use the connector for rule actions and cases.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.servicenow-sir
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_slack_api - Create Slack connector request Up

-
The Slack connector uses Slack Incoming Webhooks.
-
-
connector_type_id
String The type of connector.
-
Enum:
-
.slack_api
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_slack_webhook - Create Slack connector request Up

-
The Slack connector uses Slack Incoming Webhooks.
-
-
connector_type_id
String The type of connector.
-
Enum:
-
.slack
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_swimlane - Create Swimlane connector request Up

-
The Swimlane connector uses the Swimlane REST API to create Swimlane records.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.swimlane
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_teams - Create Microsoft Teams connector request Up

-
The Microsoft Teams connector uses Incoming Webhooks.
-
-
connector_type_id
String The type of connector.
-
Enum:
-
.teams
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_tines - Create Tines connector request Up

-
The Tines connector uses Tines Webhook actions to send events via POST request.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.tines
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_torq - Create Torq connector request Up

-
The Torq connector uses a Torq webhook to trigger workflows with Kibana actions.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.torq
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_webhook - Create Webhook connector request Up

-
The Webhook connector uses axios to send a POST or PUT request to a web service.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.webhook
-
name
String The display name for the connector.
-
secrets
-
-
-
-

create_connector_request_xmatters - Create xMatters connector request Up

-
The xMatters connector uses the xMatters Workflow for Elastic to send actionable alerts to on-call xMatters resources.
-
-
config
-
connector_type_id
String The type of connector.
-
Enum:
-
.xmatters
-
name
String The display name for the connector.
-
secrets
-
-
-
-

features - Up

-
The feature that uses the connector. Valid values are alerting, cases, uptime, and siem.
-
-
-
-
-

getConnector_404_response - Up

-
-
-
error (optional)
-
message (optional)
-
statusCode (optional)
-
-
-
-

legacyRunConnector_200_response - Up

-
-
-
actionId (optional)
-
data (optional)
-
status (optional)
String The status of the action.
-
-
-
-

runConnector_200_response - Up

-
-
-
connector_id
String The identifier for the connector.
-
data (optional)
-
status
String The status of the action.
-
Enum:
-
error
ok
-
-
- -
-

run_connector_params_documents - Index connector parameters Up

-
Test an action that indexes a document into Elasticsearch.
-
-
documents
array[map[String, oas_any_type_not_mapped]] The documents in JSON format for index connectors.
-
-
-
-

run_connector_params_level_message - Server log connector parameters Up

-
Test an action that writes an entry to the Kibana server log.
-
-
level (optional)
String The log level of the message for server log connectors.
-
Enum:
-
debug
error
fatal
info
trace
warn
-
message
String The message for server log connectors.
-
-
-
-

run_connector_subaction_addevent - The addEvent subaction Up

-
The addEvent subaction for ServiceNow ITOM connectors.
-
-
subAction
String The action to test.
-
Enum:
-
addEvent
-
subActionParams (optional)
-
-
-
-

run_connector_subaction_addevent_subActionParams - Up

-
The set of configuration properties for the action.
-
-
additional_info (optional)
String Additional information about the event.
-
description (optional)
String The details about the event.
-
event_class (optional)
String A specific instance of the source.
-
message_key (optional)
String All actions sharing this key are associated with the same ServiceNow alert. The default value is <rule ID>:<alert instance ID>.
-
metric_name (optional)
String The name of the metric.
-
node (optional)
String The host that the event was triggered for.
-
resource (optional)
String The name of the resource.
-
severity (optional)
String The severity of the event.
-
source (optional)
String The name of the event source type.
-
time_of_event (optional)
String The time of the event.
-
type (optional)
String The type of event.
-
-
-
-

run_connector_subaction_closealert - The closeAlert subaction Up

-
The closeAlert subaction for Opsgenie connectors.
-
-
subAction
String The action to test.
-
Enum:
-
closeAlert
-
subActionParams
-
-
-
-

run_connector_subaction_closealert_subActionParams - Up

-
-
-
alias
String The unique identifier used for alert deduplication in Opsgenie. The alias must match the value used when creating the alert.
-
note (optional)
String Additional information for the alert.
-
source (optional)
String The display name for the source of the alert.
-
user (optional)
String The display name for the owner.
-
-
-
-

run_connector_subaction_createalert - The createAlert subaction Up

-
The createAlert subaction for Opsgenie connectors.
-
-
subAction
String The action to test.
-
Enum:
-
createAlert
-
subActionParams
-
-
-
-

run_connector_subaction_createalert_subActionParams - Up

-
-
-
actions (optional)
array[String] The custom actions available to the alert.
-
alias (optional)
String The unique identifier used for alert deduplication in Opsgenie.
-
description (optional)
String A description that provides detailed information about the alert.
-
details (optional)
map[String, oas_any_type_not_mapped] The custom properties of the alert.
-
entity (optional)
String The domain of the alert. For example, the application or server name.
-
message
String The alert message.
-
note (optional)
String Additional information for the alert.
-
priority (optional)
String The priority level for the alert.
-
Enum:
-
P1
P2
P3
P4
P5
-
responders (optional)
array[run_connector_subaction_createalert_subActionParams_responders_inner] The entities to receive notifications about the alert. If type is user, either id or username is required. If type is team, either id or name is required.
-
source (optional)
String The display name for the source of the alert.
-
tags (optional)
array[String] The tags for the alert.
-
user (optional)
String The display name for the owner.
-
visibleTo (optional)
array[run_connector_subaction_createalert_subActionParams_visibleTo_inner] The teams and users that the alert will be visible to without sending a notification. Only one of id, name, or username is required.
-
-
-
-

run_connector_subaction_createalert_subActionParams_responders_inner - Up

-
-
-
id (optional)
String The identifier for the entity.
-
name (optional)
String The name of the entity.
-
type (optional)
String The type of responders, in this case escalation.
-
Enum:
-
escalation
schedule
team
user
-
username (optional)
String A valid email address for the user.
-
-
-
-

run_connector_subaction_createalert_subActionParams_visibleTo_inner - Up

-
-
-
id (optional)
String The identifier for the entity.
-
name (optional)
String The name of the entity.
-
type
String Valid values are team and user.
-
Enum:
-
team
user
-
username (optional)
String The user name. This property is required only when the type is user.
-
-
-
-

run_connector_subaction_fieldsbyissuetype - The fieldsByIssueType subaction Up

-
The fieldsByIssueType subaction for Jira connectors.
-
-
subAction
String The action to test.
-
Enum:
-
fieldsByIssueType
-
subActionParams
-
-
-
-

run_connector_subaction_fieldsbyissuetype_subActionParams - Up

-
-
-
id
String The Jira issue type identifier.
-
-
-
-

run_connector_subaction_getchoices - The getChoices subaction Up

-
The getChoices subaction for ServiceNow ITOM, ServiceNow ITSM, and ServiceNow SecOps connectors.
-
-
subAction
String The action to test.
-
Enum:
-
getChoices
-
subActionParams
-
-
-
-

run_connector_subaction_getchoices_subActionParams - Up

-
The set of configuration properties for the action.
-
-
fields
array[String] An array of fields.
-
-
-
-

run_connector_subaction_getfields - The getFields subaction Up

-
The getFields subaction for Jira, ServiceNow ITSM, and ServiceNow SecOps connectors.
-
-
subAction
String The action to test.
-
Enum:
-
getFields
-
-
-
-

run_connector_subaction_getincident - The getIncident subaction Up

-
The getIncident subaction for Jira, ServiceNow ITSM, and ServiceNow SecOps connectors.
-
-
subAction
String The action to test.
-
Enum:
-
getIncident
-
subActionParams
-
-
-
-

run_connector_subaction_getincident_subActionParams - Up

-
-
-
externalId
String The Jira, ServiceNow ITSM, or ServiceNow SecOps issue identifier.
-
-
-
-

run_connector_subaction_issue - The issue subaction Up

-
The issue subaction for Jira connectors.
-
-
subAction
String The action to test.
-
Enum:
-
issue
-
subActionParams (optional)
-
-
-
-

run_connector_subaction_issue_subActionParams - Up

-
-
-
id
String The Jira issue identifier.
-
-
-
-

run_connector_subaction_issues - The issues subaction Up

-
The issues subaction for Jira connectors.
-
-
subAction
String The action to test.
-
Enum:
-
issues
-
subActionParams
-
-
-
-

run_connector_subaction_issues_subActionParams - Up

-
-
-
title
String The title of the Jira issue.
-
-
-
-

run_connector_subaction_issuetypes - The issueTypes subaction Up

-
The issueTypes subaction for Jira connectors.
-
-
subAction
String The action to test.
-
Enum:
-
issueTypes
-
-
-
-

run_connector_subaction_pushtoservice - The pushToService subaction Up

-
The pushToService subaction for Jira, ServiceNow ITSM, ServiceNow SecOps, and Swimlane connectors.
-
-
subAction
String The action to test.
-
Enum:
-
pushToService
-
subActionParams
-
-
-
-

run_connector_subaction_pushtoservice_subActionParams - Up

-
The set of configuration properties for the action.
-
-
comments (optional)
array[run_connector_subaction_pushtoservice_subActionParams_comments_inner] Additional information that is sent to Jira, ServiceNow ITSM, ServiceNow SecOps, or Swimlane.
-
incident (optional)
-
-
-
-

run_connector_subaction_pushtoservice_subActionParams_comments_inner - Up

-
-
-
comment (optional)
String A comment related to the incident. For example, describe how to troubleshoot the issue.
-
commentId (optional)
Integer A unique identifier for the comment.
-
-
-
-

run_connector_subaction_pushtoservice_subActionParams_incident - Up

-
Information necessary to create or update a Jira, ServiceNow ITSM, ServiveNow SecOps, or Swimlane incident.
-
-
alertId (optional)
String The alert identifier for Swimlane connectors.
-
caseId (optional)
String The case identifier for the incident for Swimlane connectors.
-
caseName (optional)
String The case name for the incident for Swimlane connectors.
-
category (optional)
String The category of the incident for ServiceNow ITSM and ServiceNow SecOps connectors.
-
correlation_display (optional)
String A descriptive label of the alert for correlation purposes for ServiceNow ITSM and ServiceNow SecOps connectors.
-
correlation_id (optional)
String The correlation identifier for the security incident for ServiceNow ITSM and ServiveNow SecOps connectors. Connectors using the same correlation ID are associated with the same ServiceNow incident. This value determines whether a new ServiceNow incident is created or an existing one is updated. Modifying this value is optional; if not modified, the rule ID and alert ID are combined as {{ruleID}}:{{alert ID}} to form the correlation ID value in ServiceNow. The maximum character length for this value is 100 characters. NOTE: Using the default configuration of {{ruleID}}:{{alert ID}} ensures that ServiceNow creates a separate incident record for every generated alert that uses a unique alert ID. If the rule generates multiple alerts that use the same alert IDs, ServiceNow creates and continually updates a single incident record for the alert.
-
description (optional)
String The description of the incident for Jira, ServiceNow ITSM, ServiceNow SecOps, and Swimlane connectors.
-
dest_ip (optional)
-
externalId (optional)
String The Jira, ServiceNow ITSM, or ServiceNow SecOps issue identifier. If present, the incident is updated. Otherwise, a new incident is created.
-
impact (optional)
String The impact of the incident for ServiceNow ITSM connectors.
-
issueType (optional)
Integer The type of incident for Jira connectors. For example, 10006. To obtain the list of valid values, set subAction to issueTypes.
-
labels (optional)
array[String] The labels for the incident for Jira connectors. NOTE: Labels cannot contain spaces.
-
malware_hash (optional)
-
malware_url (optional)
-
parent (optional)
String The ID or key of the parent issue for Jira connectors. Applies only to Sub-task types of issues.
-
priority (optional)
String The priority of the incident in Jira and ServiceNow SecOps connectors.
-
ruleName (optional)
String The rule name for Swimlane connectors.
-
severity (optional)
String The severity of the incident for ServiceNow ITSM and Swimlane connectors.
-
short_description (optional)
String A short description of the incident for ServiceNow ITSM and ServiceNow SecOps connectors. It is used for searching the contents of the knowledge base.
-
source_ip (optional)
-
subcategory (optional)
String The subcategory of the incident for ServiceNow ITSM and ServiceNow SecOps connectors.
-
summary (optional)
String A summary of the incident for Jira connectors.
-
title (optional)
String A title for the incident for Jira connectors. It is used for searching the contents of the knowledge base.
-
urgency (optional)
String The urgency of the incident for ServiceNow ITSM connectors.
-
-
-
-

run_connector_subaction_pushtoservice_subActionParams_incident_dest_ip - Up

-
A list of destination IP addresses related to the security incident for ServiceNow SecOps connectors. The IPs are added as observables to the security incident.
-
-
-
-
-

run_connector_subaction_pushtoservice_subActionParams_incident_malware_hash - Up

-
A list of malware hashes related to the security incident for ServiceNow SecOps connectors. The hashes are added as observables to the security incident.
-
-
-
-
-

run_connector_subaction_pushtoservice_subActionParams_incident_malware_url - Up

-
A list of malware URLs related to the security incident for ServiceNow SecOps connectors. The URLs are added as observables to the security incident.
-
-
-
-
-

run_connector_subaction_pushtoservice_subActionParams_incident_source_ip - Up

-
A list of source IP addresses related to the security incident for ServiceNow SecOps connectors. The IPs are added as observables to the security incident.
-
-
-
-
-

secrets_properties_cases_webhook - Connector secrets properties for Webhook - Case Management connector Up

-
-
-
password (optional)
String The password for HTTP basic authentication. If hasAuth is set to true, this property is required.
-
user (optional)
String The username for HTTP basic authentication. If hasAuth is set to true, this property is required.
-
-
-
-

secrets_properties_d3security - Connector secrets properties for a D3 Security connector Up

-
Defines secrets for connectors when type is .d3security.
-
-
token
String The D3 Security token.
-
-
-
-

secrets_properties_email - Connector secrets properties for an email connector Up

-
Defines secrets for connectors when type is .email.
-
-
clientSecret (optional)
String The Microsoft Exchange Client secret for OAuth 2.0 client credentials authentication. It must be URL-encoded. If service is exchange_server, this property is required.
-
password (optional)
String The password for HTTP basic authentication. If hasAuth is set to true, this property is required.
-
user (optional)
String The username for HTTP basic authentication. If hasAuth is set to true, this property is required.
-
-
-
-

secrets_properties_genai - Connector secrets properties for an OpenAI connector Up

-
Defines secrets for connectors when type is .gen-ai.
-
-
apiKey (optional)
String The OpenAI API key.
-
-
-
-

secrets_properties_jira - Connector secrets properties for a Jira connector Up

-
Defines secrets for connectors when type is .jira.
-
-
apiToken
String The Jira API authentication token for HTTP basic authentication.
-
email
String The account email for HTTP Basic authentication.
-
-
-
-

secrets_properties_opsgenie - Connector secrets properties for an Opsgenie connector Up

-
Defines secrets for connectors when type is .opsgenie.
-
-
apiKey
String The Opsgenie API authentication key for HTTP Basic authentication.
-
-
-
-

secrets_properties_pagerduty - Connector secrets properties for a PagerDuty connector Up

-
Defines secrets for connectors when type is .pagerduty.
-
-
routingKey
String A 32 character PagerDuty Integration Key for an integration on a service.
-
-
-
-

secrets_properties_resilient - Connector secrets properties for IBM Resilient connector Up

-
Defines secrets for connectors when type is .resilient.
-
-
apiKeyId
String The authentication key ID for HTTP Basic authentication.
-
apiKeySecret
String The authentication key secret for HTTP Basic authentication.
-
-
-
-

secrets_properties_servicenow - Connector secrets properties for ServiceNow ITOM, ServiceNow ITSM, and ServiceNow SecOps connectors Up

-
Defines secrets for connectors when type is .servicenow, .servicenow-sir, or .servicenow-itom.
-
-
clientSecret (optional)
String The client secret assigned to your OAuth application. This property is required when isOAuth is true.
-
password (optional)
String The password for HTTP basic authentication. This property is required when isOAuth is false.
-
privateKey (optional)
String The RSA private key that you created for use in ServiceNow. This property is required when isOAuth is true.
-
privateKeyPassword (optional)
String The password for the RSA private key. This property is required when isOAuth is true and you set a password on your private key.
-
username (optional)
String The username for HTTP basic authentication. This property is required when isOAuth is false.
-
-
-
-

secrets_properties_slack_api - Connector secrets properties for a Web API Slack connector Up

-
Defines secrets for connectors when type is .slack.
-
-
token
String Slack bot user OAuth token.
-
-
-
-

secrets_properties_slack_webhook - Connector secrets properties for a Webhook Slack connector Up

-
Defines secrets for connectors when type is .slack.
-
-
webhookUrl
String Slack webhook url.
-
-
-
-

secrets_properties_swimlane - Connector secrets properties for a Swimlane connector Up

-
Defines secrets for connectors when type is .swimlane.
-
-
apiToken (optional)
String Swimlane API authentication token.
-
-
-
-

secrets_properties_teams - Connector secrets properties for a Microsoft Teams connector Up

-
Defines secrets for connectors when type is .teams.
-
-
webhookUrl
String The URL of the incoming webhook. If you are using the xpack.actions.allowedHosts setting, add the hostname to the allowed hosts.
-
-
-
-

secrets_properties_tines - Connector secrets properties for a Tines connector Up

-
Defines secrets for connectors when type is .tines.
-
-
email
String The email used to sign in to Tines.
-
token
String The Tines API token.
-
-
-
-

secrets_properties_torq - Connector secrets properties for a Torq connector Up

-
Defines secrets for connectors when type is .torq.
-
-
token
String The secret of the webhook authentication header.
-
-
-
-

secrets_properties_webhook - Connector secrets properties for a Webhook connector Up

-
Defines secrets for connectors when type is .webhook.
-
-
crt (optional)
String If authType is webhook-authentication-ssl and certType is ssl-crt-key, it is a base64 encoded version of the CRT or CERT file.
-
key (optional)
String If authType is webhook-authentication-ssl and certType is ssl-crt-key, it is a base64 encoded version of the KEY file.
-
pfx (optional)
String If authType is webhook-authentication-ssl and certType is ssl-pfx, it is a base64 encoded version of the PFX or P12 file.
-
password (optional)
String The password for HTTP basic authentication or the passphrase for the SSL certificate files. If hasAuth is set to true and authType is webhook-authentication-basic, this property is required.
-
user (optional)
String The username for HTTP basic authentication. If hasAuth is set to true and authType is webhook-authentication-basic, this property is required.
-
-
-
-

secrets_properties_xmatters - Connector secrets properties for an xMatters connector Up

-
Defines secrets for connectors when type is .xmatters.
-
-
password (optional)
String A user name for HTTP basic authentication. It is applicable only when usesBasic is true.
-
secretsUrl (optional)
String The request URL for the Elastic Alerts trigger in xMatters with the API key included in the URL. It is applicable only when usesBasic is false.
-
user (optional)
String A password for HTTP basic authentication. It is applicable only when usesBasic is true.
-
-
-
-

updateConnector_400_response - Up

-
-
-
error (optional)
-
message (optional)
-
statusCode (optional)
-
-
- - -
-

update_connector_request_email - Update email connector request Up

-
-
-
config
-
name
String The display name for the connector.
-
secrets (optional)
-
-
-
-

update_connector_request_index - Update index connector request Up

-
-
-
config
-
name
String The display name for the connector.
-
-
-
-

update_connector_request_jira - Update Jira connector request Up

-
-
-
config
-
name
String The display name for the connector.
-
secrets
-
-
- - - -
-

update_connector_request_serverlog - Update server log connector request Up

-
-
-
name
String The display name for the connector.
-
-
- - - - - - - -
-

update_connector_request_torq - Update Torq connector request Up

-
-
-
config
-
name
String The display name for the connector.
-
secrets
-
-
- - -
-++++ diff --git a/docs/api-generated/connectors/connector-apis.asciidoc b/docs/api-generated/connectors/connector-apis.asciidoc deleted file mode 100644 index d35bad3d3d633f..00000000000000 --- a/docs/api-generated/connectors/connector-apis.asciidoc +++ /dev/null @@ -1,10 +0,0 @@ -[[connector-apis]] -== Connector APIs - -preview::[] - -//// -This file includes content that has been generated from https://github.com/elastic/kibana/tree/main/x-pack/plugins/actions/docs/openapi. Any modifications required must be done in that open API specification. -//// - -include::connector-apis-passthru.asciidoc[] \ No newline at end of file diff --git a/docs/api-generated/machine-learning/ml-apis-passthru.asciidoc b/docs/api-generated/machine-learning/ml-apis-passthru.asciidoc deleted file mode 100644 index 116ddbe0d72736..00000000000000 --- a/docs/api-generated/machine-learning/ml-apis-passthru.asciidoc +++ /dev/null @@ -1,205 +0,0 @@ -//// -This content is generated from the open API specification. -Any modifications made to this file will be overwritten. -//// - -++++ -
-

Access

-
    -
  1. APIKey KeyParamName:ApiKey KeyInQuery:false KeyInHeader:true
  2. -
  3. HTTP Basic Authentication
  4. -
- -

Methods

- [ Jump to Models ] - -

Table of Contents

-
-

Ml

- - -

Ml

-
-
- Up -
get /s/{spaceId}/api/ml/saved_objects/sync
-
Synchronizes Kibana saved objects for machine learning jobs and trained models. (mlSync)
-
You must have all privileges for the Machine Learning feature in the Analytics section of the Kibana feature privileges. This API runs automatically when you start Kibana and periodically thereafter.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
simulate (optional)
- -
Query Parameter — When true, simulates the synchronization by returning only the list of actions that would be performed. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "datafeedsAdded" : {
-    "key" : {
-      "success" : true
-    }
-  },
-  "savedObjectsCreated" : {
-    "anomaly-detector" : {
-      "key" : {
-        "success" : true
-      }
-    },
-    "data-frame-analytics" : {
-      "key" : {
-        "success" : true
-      }
-    },
-    "trained-model" : {
-      "key" : {
-        "success" : true
-      }
-    }
-  },
-  "savedObjectsDeleted" : {
-    "anomaly-detector" : {
-      "key" : {
-        "success" : true
-      }
-    },
-    "data-frame-analytics" : {
-      "key" : {
-        "success" : true
-      }
-    },
-    "trained-model" : {
-      "key" : {
-        "success" : true
-      }
-    }
-  },
-  "datafeedsRemoved" : {
-    "key" : {
-      "success" : true
-    }
-  }
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call - mlSync200Response -

401

- Authorization information is missing or invalid. - mlSync4xxResponse -
-
- -

Models

- [ Jump to Methods ] - -

Table of Contents

-
    -
  1. mlSync200Response - Successful sync API response
  2. -
  3. mlSync4xxResponse - Unsuccessful sync API response
  4. -
  5. mlSyncResponseAnomalyDetectors - Sync API response for anomaly detection jobs
  6. -
  7. mlSyncResponseDataFrameAnalytics - Sync API response for data frame analytics jobs
  8. -
  9. mlSyncResponseDatafeeds - Sync API response for datafeeds
  10. -
  11. mlSyncResponseSavedObjectsCreated - Sync API response for created saved objects
  12. -
  13. mlSyncResponseSavedObjectsDeleted - Sync API response for deleted saved objects
  14. -
  15. mlSyncResponseTrainedModels - Sync API response for trained models
  16. -
- -
-

mlSync200Response - Successful sync API response Up

-
-
-
datafeedsAdded (optional)
map[String, mlSyncResponseDatafeeds] If a saved object for an anomaly detection job is missing a datafeed identifier, it is added when you run the sync machine learning saved objects API.
-
datafeedsRemoved (optional)
map[String, mlSyncResponseDatafeeds] If a saved object for an anomaly detection job references a datafeed that no longer exists, it is deleted when you run the sync machine learning saved objects API.
-
savedObjectsCreated (optional)
-
savedObjectsDeleted (optional)
-
-
-
-

mlSync4xxResponse - Unsuccessful sync API response Up

-
-
-
error (optional)
-
message (optional)
-
statusCode (optional)
-
-
-
-

mlSyncResponseAnomalyDetectors - Sync API response for anomaly detection jobs Up

-
The sync machine learning saved objects API response contains this object when there are anomaly detection jobs affected by the synchronization. There is an object for each relevant job, which contains the synchronization status.
-
-
success (optional)
Boolean The success or failure of the synchronization.
-
-
-
-

mlSyncResponseDataFrameAnalytics - Sync API response for data frame analytics jobs Up

-
The sync machine learning saved objects API response contains this object when there are data frame analytics jobs affected by the synchronization. There is an object for each relevant job, which contains the synchronization status.
-
-
success (optional)
Boolean The success or failure of the synchronization.
-
-
-
-

mlSyncResponseDatafeeds - Sync API response for datafeeds Up

-
The sync machine learning saved objects API response contains this object when there are datafeeds affected by the synchronization. There is an object for each relevant datafeed, which contains the synchronization status.
-
-
success (optional)
Boolean The success or failure of the synchronization.
-
-
-
-

mlSyncResponseSavedObjectsCreated - Sync API response for created saved objects Up

-
If saved objects are missing for machine learning jobs or trained models, they are created when you run the sync machine learning saved objects API.
-
-
anomalyMinusdetector (optional)
map[String, mlSyncResponseAnomalyDetectors] If saved objects are missing for anomaly detection jobs, they are created.
-
dataMinusframeMinusanalytics (optional)
map[String, mlSyncResponseDataFrameAnalytics] If saved objects are missing for data frame analytics jobs, they are created.
-
trainedMinusmodel (optional)
map[String, mlSyncResponseTrainedModels] If saved objects are missing for trained models, they are created.
-
-
-
-

mlSyncResponseSavedObjectsDeleted - Sync API response for deleted saved objects Up

-
If saved objects exist for machine learning jobs or trained models that no longer exist, they are deleted when you run the sync machine learning saved objects API.
-
-
anomalyMinusdetector (optional)
map[String, mlSyncResponseAnomalyDetectors] If there are saved objects exist for nonexistent anomaly detection jobs, they are deleted.
-
dataMinusframeMinusanalytics (optional)
map[String, mlSyncResponseDataFrameAnalytics] If there are saved objects exist for nonexistent data frame analytics jobs, they are deleted.
-
trainedMinusmodel (optional)
map[String, mlSyncResponseTrainedModels] If there are saved objects exist for nonexistent trained models, they are deleted.
-
-
-
-

mlSyncResponseTrainedModels - Sync API response for trained models Up

-
The sync machine learning saved objects API response contains this object when there are trained models affected by the synchronization. There is an object for each relevant trained model, which contains the synchronization status.
-
-
success (optional)
Boolean The success or failure of the synchronization.
-
-
-
-++++ diff --git a/docs/api-generated/machine-learning/ml-apis.asciidoc b/docs/api-generated/machine-learning/ml-apis.asciidoc deleted file mode 100644 index 2d87d72616a75f..00000000000000 --- a/docs/api-generated/machine-learning/ml-apis.asciidoc +++ /dev/null @@ -1,10 +0,0 @@ -[[machine-learning-apis]] -== Machine learning APIs - -preview::[] - -//// -This file includes content that has been generated from https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/common/openapi. Any modifications required must be done in that open API specification. -//// - -include::ml-apis-passthru.asciidoc[] \ No newline at end of file diff --git a/docs/api-generated/rules/rule-apis-passthru.asciidoc b/docs/api-generated/rules/rule-apis-passthru.asciidoc deleted file mode 100644 index 843f073f95e04c..00000000000000 --- a/docs/api-generated/rules/rule-apis-passthru.asciidoc +++ /dev/null @@ -1,4905 +0,0 @@ -//// -This content is generated from the open API specification. -Any modifications made to this file will be overwritten. -//// - -++++ -
-

Access

-
    -
  1. APIKey KeyParamName:ApiKey KeyInQuery:false KeyInHeader:true
  2. -
  3. HTTP Basic Authentication
  4. -
- -

Methods

- [ Jump to Models ] - -

Table of Contents

-
-

Alerting

- - -

Alerting

-
-
- Up -
post /s/{spaceId}/api/alerting/rule
-
Creates a rule with a randomly generated rule identifier. (createRule)
-
To create a rule, you must have all privileges for the appropriate Kibana features, depending on the consumer and rule_type_id of the rule you're creating. For example, you must have privileges for the Management > Stack rules feature, Analytics > Discover and Machine Learning features, Observability features, or Security features. If the rule has actions, you must also have read privileges for the Management > Actions and Connectors feature. This API supports both key- and token-based authentication. To use key-based authentication, create an API key in Kibana and use it in the header of the API call. To use token-based authentication, provide a username and password; an API key that matches the current privileges of the user is created automatically. In both cases, the API key is subsequently used for authorization when the rule runs.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
create_rule_request create_rule_request (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "throttle" : "10m",
-  "created_at" : "2022-12-05T23:36:58.284Z",
-  "api_key_created_by_user" : false,
-  "enabled" : true,
-  "running" : true,
-  "notify_when" : "notify_when",
-  "next_run" : "2022-12-06T00:14:43.818Z",
-  "updated_at" : "2022-12-05T23:36:58.284Z",
-  "execution_status" : {
-    "last_execution_date" : "2022-12-06T00:13:43.89Z",
-    "last_duration" : 55,
-    "status" : "ok"
-  },
-  "scheduled_task_id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "consumer" : "alerts",
-  "last_run" : {
-    "alerts_count" : {
-      "ignored" : 6,
-      "new" : 1,
-      "recovered" : 5,
-      "active" : 0
-    },
-    "outcome_msg" : [ "outcome_msg", "outcome_msg" ],
-    "outcome_order" : 5,
-    "warning" : "warning",
-    "outcome" : "succeeded"
-  },
-  "params" : {
-    "key" : ""
-  },
-  "created_by" : "elastic",
-  "muted_alert_ids" : [ "muted_alert_ids", "muted_alert_ids" ],
-  "rule_type_id" : "monitoring_alert_cluster_health",
-  "revision" : 2,
-  "tags" : [ "tags", "tags" ],
-  "api_key_owner" : "elastic",
-  "schedule" : {
-    "interval" : "1m"
-  },
-  "name" : "cluster_health_rule",
-  "updated_by" : "elastic",
-  "mute_all" : false,
-  "actions" : [ {
-    "alerts_filter" : {
-      "timeframe" : {
-        "hours" : {
-          "start" : "08:00",
-          "end" : "17:00"
-        },
-        "timezone" : "Europe/Madrid",
-        "days" : [ 1, 2, 3, 4, 5 ]
-      },
-      "query" : {
-        "kql" : "kql",
-        "filters" : [ {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        }, {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        } ]
-      }
-    },
-    "id" : "9dca3e00-74f5-11ed-9801-35303b735aef",
-    "params" : {
-      "key" : ""
-    },
-    "uuid" : "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61",
-    "connector_type_id" : ".server-log",
-    "frequency" : {
-      "summary" : true,
-      "throttle" : "10m",
-      "notify_when" : "onActiveAlert"
-    },
-    "group" : "default"
-  }, {
-    "alerts_filter" : {
-      "timeframe" : {
-        "hours" : {
-          "start" : "08:00",
-          "end" : "17:00"
-        },
-        "timezone" : "Europe/Madrid",
-        "days" : [ 1, 2, 3, 4, 5 ]
-      },
-      "query" : {
-        "kql" : "kql",
-        "filters" : [ {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        }, {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        } ]
-      }
-    },
-    "id" : "9dca3e00-74f5-11ed-9801-35303b735aef",
-    "params" : {
-      "key" : ""
-    },
-    "uuid" : "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61",
-    "connector_type_id" : ".server-log",
-    "frequency" : {
-      "summary" : true,
-      "throttle" : "10m",
-      "notify_when" : "onActiveAlert"
-    },
-    "group" : "default"
-  } ]
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - rule_response_properties -

401

- Authorization information is missing or invalid. - 401_response -

404

- Object is not found. - 404_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerting/rule/{ruleId}
-
Creates a rule with a specific rule identifier. (createRuleId)
-
To create a rule, you must have all privileges for the appropriate Kibana features, depending on the consumer and rule_type_id of the rule you're creating. For example, you must have privileges for the Management > Stack rules feature, Analytics > Discover and Machine Learning features, Observability features, or Security features. If the rule has actions, you must also have read privileges for the Management > Actions and Connectors feature. This API supports both key- and token-based authentication. To use key-based authentication, create an API key in Kibana and use it in the header of the API call. To use token-based authentication, provide a username and password; an API key that matches the current privileges of the user is created automatically. In both cases, the API key is subsequently used for authorization when the rule runs.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
ruleId (required)
- -
Path Parameter — An UUID v1 or v4 identifier for the rule. If you omit this parameter, an identifier is randomly generated. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
create_rule_request create_rule_request (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "throttle" : "10m",
-  "created_at" : "2022-12-05T23:36:58.284Z",
-  "api_key_created_by_user" : false,
-  "enabled" : true,
-  "running" : true,
-  "notify_when" : "notify_when",
-  "next_run" : "2022-12-06T00:14:43.818Z",
-  "updated_at" : "2022-12-05T23:36:58.284Z",
-  "execution_status" : {
-    "last_execution_date" : "2022-12-06T00:13:43.89Z",
-    "last_duration" : 55,
-    "status" : "ok"
-  },
-  "scheduled_task_id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "consumer" : "alerts",
-  "last_run" : {
-    "alerts_count" : {
-      "ignored" : 6,
-      "new" : 1,
-      "recovered" : 5,
-      "active" : 0
-    },
-    "outcome_msg" : [ "outcome_msg", "outcome_msg" ],
-    "outcome_order" : 5,
-    "warning" : "warning",
-    "outcome" : "succeeded"
-  },
-  "params" : {
-    "key" : ""
-  },
-  "created_by" : "elastic",
-  "muted_alert_ids" : [ "muted_alert_ids", "muted_alert_ids" ],
-  "rule_type_id" : "monitoring_alert_cluster_health",
-  "revision" : 2,
-  "tags" : [ "tags", "tags" ],
-  "api_key_owner" : "elastic",
-  "schedule" : {
-    "interval" : "1m"
-  },
-  "name" : "cluster_health_rule",
-  "updated_by" : "elastic",
-  "mute_all" : false,
-  "actions" : [ {
-    "alerts_filter" : {
-      "timeframe" : {
-        "hours" : {
-          "start" : "08:00",
-          "end" : "17:00"
-        },
-        "timezone" : "Europe/Madrid",
-        "days" : [ 1, 2, 3, 4, 5 ]
-      },
-      "query" : {
-        "kql" : "kql",
-        "filters" : [ {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        }, {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        } ]
-      }
-    },
-    "id" : "9dca3e00-74f5-11ed-9801-35303b735aef",
-    "params" : {
-      "key" : ""
-    },
-    "uuid" : "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61",
-    "connector_type_id" : ".server-log",
-    "frequency" : {
-      "summary" : true,
-      "throttle" : "10m",
-      "notify_when" : "onActiveAlert"
-    },
-    "group" : "default"
-  }, {
-    "alerts_filter" : {
-      "timeframe" : {
-        "hours" : {
-          "start" : "08:00",
-          "end" : "17:00"
-        },
-        "timezone" : "Europe/Madrid",
-        "days" : [ 1, 2, 3, 4, 5 ]
-      },
-      "query" : {
-        "kql" : "kql",
-        "filters" : [ {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        }, {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        } ]
-      }
-    },
-    "id" : "9dca3e00-74f5-11ed-9801-35303b735aef",
-    "params" : {
-      "key" : ""
-    },
-    "uuid" : "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61",
-    "connector_type_id" : ".server-log",
-    "frequency" : {
-      "summary" : true,
-      "throttle" : "10m",
-      "notify_when" : "onActiveAlert"
-    },
-    "group" : "default"
-  } ]
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - rule_response_properties -

401

- Authorization information is missing or invalid. - 401_response -

404

- Object is not found. - 404_response -
-
-
-
- Up -
delete /s/{spaceId}/api/alerting/rule/{ruleId}
-
Deletes a rule. (deleteRule)
-
To delete a rule, you must have all privileges for the appropriate Kibana features, depending on the consumer and rule_type_id of the rule you're deleting. For example, the Management > Stack Rules feature, Analytics > Discover or Machine Learning features, Observability, or Security features. WARNING: After you delete a rule, you cannot recover it. If the API key that is used by the rule was created automatically, it is deleted.
- -

Path parameters

-
-
ruleId (required)
- -
Path Parameter — An identifier for the rule. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -

404

- Object is not found. - 404_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerting/rule/{ruleId}/_disable
-
Disables a rule. (disableRule)
-
You must have all privileges for the appropriate Kibana features, depending on the consumer and rule_type_id of the rule. For example, the Management > Stack Rules feature, Analytics > Discover and Machine Learning features, Observability, and Security features.
- -

Path parameters

-
-
ruleId (required)
- -
Path Parameter — An identifier for the rule. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -

404

- Object is not found. - 404_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerting/rule/{ruleId}/_enable
-
Enables a rule. (enableRule)
-
To enable a rule, you must have all privileges for the appropriate Kibana features, depending on the consumer and rule_type_id of the rule. For example, the Management > Stack Rules feature, Analytics > Discover and Machine Learning features, Observability, and Security features. This API supports both key- and token-based authentication. To use key-based authentication, create an API key in Kibana and use it in the header of the API call. To use token-based authentication, provide a username and password; an API key that matches the current privileges of the user is created automatically. In both cases, the API key is subsequently used for authorization when the rule runs.
- -

Path parameters

-
-
ruleId (required)
- -
Path Parameter — An identifier for the rule. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -

404

- Object is not found. - 401_response -
-
-
-
- Up -
get /s/{spaceId}/api/alerting/rules/_find
-
Retrieves information about rules. (findRules)
-
You must have read privileges for the appropriate Kibana features, depending on the consumer and rule_type_id of the rules you're seeking. For example, you must have privileges for the Management > Stack rules feature, Analytics > Discover and Machine Learning features, Observability features, or Security features. To find rules associated with the Stack Monitoring feature, use the monitoring_user built-in role.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
default_search_operator (optional)
- -
Query Parameter — The default operator to use for the simple_query_string. default: OR
fields (optional)
- -
Query Parameter — The fields to return in the attributes key of the response. default: null
filter (optional)
- -
Query Parameter — A KQL string that you filter with an attribute from your saved object. It should look like savedObjectType.attributes.title: "myTitle". However, if you used a direct attribute of a saved object, such as updatedAt, you must define your filter, for example, savedObjectType.updatedAt > 2018-12-22. default: null
has_reference (optional)
- -
Query Parameter — Filters the rules that have a relation with the reference objects with a specific type and identifier. default: null
page (optional)
- -
Query Parameter — The page number to return. default: 1
per_page (optional)
- -
Query Parameter — The number of rules to return per page. default: 20
search (optional)
- -
Query Parameter — An Elasticsearch simple_query_string query that filters the objects in the response. default: null
search_fields (optional)
- -
Query Parameter — The fields to perform the simple_query_string parsed query against. default: null
sort_field (optional)
- -
Query Parameter — Determines which field is used to sort the results. The field must exist in the attributes key of the response. default: null
sort_order (optional)
- -
Query Parameter — Determines the sort order. default: desc
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "per_page" : 6,
-  "total" : 1,
-  "data" : [ {
-    "throttle" : "10m",
-    "created_at" : "2022-12-05T23:36:58.284Z",
-    "api_key_created_by_user" : false,
-    "enabled" : true,
-    "running" : true,
-    "notify_when" : "notify_when",
-    "next_run" : "2022-12-06T00:14:43.818Z",
-    "updated_at" : "2022-12-05T23:36:58.284Z",
-    "execution_status" : {
-      "last_execution_date" : "2022-12-06T00:13:43.89Z",
-      "last_duration" : 55,
-      "status" : "ok"
-    },
-    "scheduled_task_id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-    "id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-    "consumer" : "alerts",
-    "last_run" : {
-      "alerts_count" : {
-        "ignored" : 6,
-        "new" : 1,
-        "recovered" : 5,
-        "active" : 0
-      },
-      "outcome_msg" : [ "outcome_msg", "outcome_msg" ],
-      "outcome_order" : 5,
-      "warning" : "warning",
-      "outcome" : "succeeded"
-    },
-    "params" : {
-      "key" : ""
-    },
-    "created_by" : "elastic",
-    "muted_alert_ids" : [ "muted_alert_ids", "muted_alert_ids" ],
-    "rule_type_id" : "monitoring_alert_cluster_health",
-    "revision" : 2,
-    "tags" : [ "tags", "tags" ],
-    "api_key_owner" : "elastic",
-    "schedule" : {
-      "interval" : "1m"
-    },
-    "name" : "cluster_health_rule",
-    "updated_by" : "elastic",
-    "mute_all" : false,
-    "actions" : [ {
-      "alerts_filter" : {
-        "timeframe" : {
-          "hours" : {
-            "start" : "08:00",
-            "end" : "17:00"
-          },
-          "timezone" : "Europe/Madrid",
-          "days" : [ 1, 2, 3, 4, 5 ]
-        },
-        "query" : {
-          "kql" : "kql",
-          "filters" : [ {
-            "$state" : "{}",
-            "meta" : {
-              "field" : "field",
-              "controlledBy" : "controlledBy",
-              "negate" : true,
-              "alias" : "alias",
-              "index" : "index",
-              "disabled" : true,
-              "params" : "{}",
-              "type" : "type",
-              "value" : "value",
-              "isMultiIndex" : true,
-              "key" : "key",
-              "group" : "group"
-            },
-            "query" : "{}"
-          }, {
-            "$state" : "{}",
-            "meta" : {
-              "field" : "field",
-              "controlledBy" : "controlledBy",
-              "negate" : true,
-              "alias" : "alias",
-              "index" : "index",
-              "disabled" : true,
-              "params" : "{}",
-              "type" : "type",
-              "value" : "value",
-              "isMultiIndex" : true,
-              "key" : "key",
-              "group" : "group"
-            },
-            "query" : "{}"
-          } ]
-        }
-      },
-      "id" : "9dca3e00-74f5-11ed-9801-35303b735aef",
-      "params" : {
-        "key" : ""
-      },
-      "uuid" : "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61",
-      "connector_type_id" : ".server-log",
-      "frequency" : {
-        "summary" : true,
-        "throttle" : "10m",
-        "notify_when" : "onActiveAlert"
-      },
-      "group" : "default"
-    }, {
-      "alerts_filter" : {
-        "timeframe" : {
-          "hours" : {
-            "start" : "08:00",
-            "end" : "17:00"
-          },
-          "timezone" : "Europe/Madrid",
-          "days" : [ 1, 2, 3, 4, 5 ]
-        },
-        "query" : {
-          "kql" : "kql",
-          "filters" : [ {
-            "$state" : "{}",
-            "meta" : {
-              "field" : "field",
-              "controlledBy" : "controlledBy",
-              "negate" : true,
-              "alias" : "alias",
-              "index" : "index",
-              "disabled" : true,
-              "params" : "{}",
-              "type" : "type",
-              "value" : "value",
-              "isMultiIndex" : true,
-              "key" : "key",
-              "group" : "group"
-            },
-            "query" : "{}"
-          }, {
-            "$state" : "{}",
-            "meta" : {
-              "field" : "field",
-              "controlledBy" : "controlledBy",
-              "negate" : true,
-              "alias" : "alias",
-              "index" : "index",
-              "disabled" : true,
-              "params" : "{}",
-              "type" : "type",
-              "value" : "value",
-              "isMultiIndex" : true,
-              "key" : "key",
-              "group" : "group"
-            },
-            "query" : "{}"
-          } ]
-        }
-      },
-      "id" : "9dca3e00-74f5-11ed-9801-35303b735aef",
-      "params" : {
-        "key" : ""
-      },
-      "uuid" : "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61",
-      "connector_type_id" : ".server-log",
-      "frequency" : {
-        "summary" : true,
-        "throttle" : "10m",
-        "notify_when" : "onActiveAlert"
-      },
-      "group" : "default"
-    } ]
-  }, {
-    "throttle" : "10m",
-    "created_at" : "2022-12-05T23:36:58.284Z",
-    "api_key_created_by_user" : false,
-    "enabled" : true,
-    "running" : true,
-    "notify_when" : "notify_when",
-    "next_run" : "2022-12-06T00:14:43.818Z",
-    "updated_at" : "2022-12-05T23:36:58.284Z",
-    "execution_status" : {
-      "last_execution_date" : "2022-12-06T00:13:43.89Z",
-      "last_duration" : 55,
-      "status" : "ok"
-    },
-    "scheduled_task_id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-    "id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-    "consumer" : "alerts",
-    "last_run" : {
-      "alerts_count" : {
-        "ignored" : 6,
-        "new" : 1,
-        "recovered" : 5,
-        "active" : 0
-      },
-      "outcome_msg" : [ "outcome_msg", "outcome_msg" ],
-      "outcome_order" : 5,
-      "warning" : "warning",
-      "outcome" : "succeeded"
-    },
-    "params" : {
-      "key" : ""
-    },
-    "created_by" : "elastic",
-    "muted_alert_ids" : [ "muted_alert_ids", "muted_alert_ids" ],
-    "rule_type_id" : "monitoring_alert_cluster_health",
-    "revision" : 2,
-    "tags" : [ "tags", "tags" ],
-    "api_key_owner" : "elastic",
-    "schedule" : {
-      "interval" : "1m"
-    },
-    "name" : "cluster_health_rule",
-    "updated_by" : "elastic",
-    "mute_all" : false,
-    "actions" : [ {
-      "alerts_filter" : {
-        "timeframe" : {
-          "hours" : {
-            "start" : "08:00",
-            "end" : "17:00"
-          },
-          "timezone" : "Europe/Madrid",
-          "days" : [ 1, 2, 3, 4, 5 ]
-        },
-        "query" : {
-          "kql" : "kql",
-          "filters" : [ {
-            "$state" : "{}",
-            "meta" : {
-              "field" : "field",
-              "controlledBy" : "controlledBy",
-              "negate" : true,
-              "alias" : "alias",
-              "index" : "index",
-              "disabled" : true,
-              "params" : "{}",
-              "type" : "type",
-              "value" : "value",
-              "isMultiIndex" : true,
-              "key" : "key",
-              "group" : "group"
-            },
-            "query" : "{}"
-          }, {
-            "$state" : "{}",
-            "meta" : {
-              "field" : "field",
-              "controlledBy" : "controlledBy",
-              "negate" : true,
-              "alias" : "alias",
-              "index" : "index",
-              "disabled" : true,
-              "params" : "{}",
-              "type" : "type",
-              "value" : "value",
-              "isMultiIndex" : true,
-              "key" : "key",
-              "group" : "group"
-            },
-            "query" : "{}"
-          } ]
-        }
-      },
-      "id" : "9dca3e00-74f5-11ed-9801-35303b735aef",
-      "params" : {
-        "key" : ""
-      },
-      "uuid" : "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61",
-      "connector_type_id" : ".server-log",
-      "frequency" : {
-        "summary" : true,
-        "throttle" : "10m",
-        "notify_when" : "onActiveAlert"
-      },
-      "group" : "default"
-    }, {
-      "alerts_filter" : {
-        "timeframe" : {
-          "hours" : {
-            "start" : "08:00",
-            "end" : "17:00"
-          },
-          "timezone" : "Europe/Madrid",
-          "days" : [ 1, 2, 3, 4, 5 ]
-        },
-        "query" : {
-          "kql" : "kql",
-          "filters" : [ {
-            "$state" : "{}",
-            "meta" : {
-              "field" : "field",
-              "controlledBy" : "controlledBy",
-              "negate" : true,
-              "alias" : "alias",
-              "index" : "index",
-              "disabled" : true,
-              "params" : "{}",
-              "type" : "type",
-              "value" : "value",
-              "isMultiIndex" : true,
-              "key" : "key",
-              "group" : "group"
-            },
-            "query" : "{}"
-          }, {
-            "$state" : "{}",
-            "meta" : {
-              "field" : "field",
-              "controlledBy" : "controlledBy",
-              "negate" : true,
-              "alias" : "alias",
-              "index" : "index",
-              "disabled" : true,
-              "params" : "{}",
-              "type" : "type",
-              "value" : "value",
-              "isMultiIndex" : true,
-              "key" : "key",
-              "group" : "group"
-            },
-            "query" : "{}"
-          } ]
-        }
-      },
-      "id" : "9dca3e00-74f5-11ed-9801-35303b735aef",
-      "params" : {
-        "key" : ""
-      },
-      "uuid" : "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61",
-      "connector_type_id" : ".server-log",
-      "frequency" : {
-        "summary" : true,
-        "throttle" : "10m",
-        "notify_when" : "onActiveAlert"
-      },
-      "group" : "default"
-    } ]
-  } ],
-  "page" : 0
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - findRules_200_response -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
get /s/{spaceId}/api/alerting/_health
-
Retrieves the health status of the alerting framework. (getAlertingHealth)
-
You must have read privileges for the Management > Stack Rules feature or for at least one of the Analytics > Discover, Analytics > Machine Learning, Observability, or Security features.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "alerting_framework_health" : {
-    "execution_health" : {
-      "status" : "ok",
-      "timestamp" : "2023-01-13T01:28:00.28Z"
-    },
-    "read_health" : {
-      "status" : "ok",
-      "timestamp" : "2023-01-13T01:28:00.28Z"
-    },
-    "decryption_health" : {
-      "status" : "ok",
-      "timestamp" : "2023-01-13T01:28:00.28Z"
-    }
-  },
-  "has_permanent_encryption_key" : true,
-  "is_sufficiently_secure" : true
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - getAlertingHealth_200_response -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
get /s/{spaceId}/api/alerting/rule/{ruleId}
-
Retrieves a rule by its identifier. (getRule)
-
You must have read privileges for the appropriate Kibana features, depending on the consumer and rule_type_id of the rules you're seeking. For example, the Management > Stack Rules feature, Analytics > Discover and Machine Learning features, Observability features, or Security features. To get rules associated with the Stack Monitoring feature, use the monitoring_user built-in role.
- -

Path parameters

-
-
ruleId (required)
- -
Path Parameter — An identifier for the rule. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "throttle" : "10m",
-  "created_at" : "2022-12-05T23:36:58.284Z",
-  "api_key_created_by_user" : false,
-  "enabled" : true,
-  "running" : true,
-  "notify_when" : "notify_when",
-  "next_run" : "2022-12-06T00:14:43.818Z",
-  "updated_at" : "2022-12-05T23:36:58.284Z",
-  "execution_status" : {
-    "last_execution_date" : "2022-12-06T00:13:43.89Z",
-    "last_duration" : 55,
-    "status" : "ok"
-  },
-  "scheduled_task_id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "consumer" : "alerts",
-  "last_run" : {
-    "alerts_count" : {
-      "ignored" : 6,
-      "new" : 1,
-      "recovered" : 5,
-      "active" : 0
-    },
-    "outcome_msg" : [ "outcome_msg", "outcome_msg" ],
-    "outcome_order" : 5,
-    "warning" : "warning",
-    "outcome" : "succeeded"
-  },
-  "params" : {
-    "key" : ""
-  },
-  "created_by" : "elastic",
-  "muted_alert_ids" : [ "muted_alert_ids", "muted_alert_ids" ],
-  "rule_type_id" : "monitoring_alert_cluster_health",
-  "revision" : 2,
-  "tags" : [ "tags", "tags" ],
-  "api_key_owner" : "elastic",
-  "schedule" : {
-    "interval" : "1m"
-  },
-  "name" : "cluster_health_rule",
-  "updated_by" : "elastic",
-  "mute_all" : false,
-  "actions" : [ {
-    "alerts_filter" : {
-      "timeframe" : {
-        "hours" : {
-          "start" : "08:00",
-          "end" : "17:00"
-        },
-        "timezone" : "Europe/Madrid",
-        "days" : [ 1, 2, 3, 4, 5 ]
-      },
-      "query" : {
-        "kql" : "kql",
-        "filters" : [ {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        }, {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        } ]
-      }
-    },
-    "id" : "9dca3e00-74f5-11ed-9801-35303b735aef",
-    "params" : {
-      "key" : ""
-    },
-    "uuid" : "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61",
-    "connector_type_id" : ".server-log",
-    "frequency" : {
-      "summary" : true,
-      "throttle" : "10m",
-      "notify_when" : "onActiveAlert"
-    },
-    "group" : "default"
-  }, {
-    "alerts_filter" : {
-      "timeframe" : {
-        "hours" : {
-          "start" : "08:00",
-          "end" : "17:00"
-        },
-        "timezone" : "Europe/Madrid",
-        "days" : [ 1, 2, 3, 4, 5 ]
-      },
-      "query" : {
-        "kql" : "kql",
-        "filters" : [ {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        }, {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        } ]
-      }
-    },
-    "id" : "9dca3e00-74f5-11ed-9801-35303b735aef",
-    "params" : {
-      "key" : ""
-    },
-    "uuid" : "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61",
-    "connector_type_id" : ".server-log",
-    "frequency" : {
-      "summary" : true,
-      "throttle" : "10m",
-      "notify_when" : "onActiveAlert"
-    },
-    "group" : "default"
-  } ]
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - rule_response_properties -

401

- Authorization information is missing or invalid. - 401_response -

404

- Object is not found. - 404_response -
-
-
-
- Up -
get /s/{spaceId}/api/alerting/rule_types
-
Retrieves a list of rule types. (getRuleTypes)
-
If you have read privileges for one or more Kibana features, the API response contains information about the appropriate rule types. For example, there are rule types associated with the Management > Stack Rules feature, Analytics > Discover and Machine Learning features, Observability features, and Security features. To get rule types associated with the Stack Monitoring feature, use the monitoring_user built-in role.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "recovery_action_group" : {
-    "name" : "name",
-    "id" : "id"
-  },
-  "does_set_recovery_context" : true,
-  "is_exportable" : true,
-  "authorized_consumers" : {
-    "alerts" : {
-      "all" : true,
-      "read" : true
-    },
-    "discover" : {
-      "all" : true,
-      "read" : true
-    },
-    "stackAlerts" : {
-      "all" : true,
-      "read" : true
-    },
-    "infrastructure" : {
-      "all" : true,
-      "read" : true
-    },
-    "siem" : {
-      "all" : true,
-      "read" : true
-    },
-    "monitoring" : {
-      "all" : true,
-      "read" : true
-    },
-    "logs" : {
-      "all" : true,
-      "read" : true
-    },
-    "apm" : {
-      "all" : true,
-      "read" : true
-    },
-    "ml" : {
-      "all" : true,
-      "read" : true
-    },
-    "uptime" : {
-      "all" : true,
-      "read" : true
-    }
-  },
-  "action_groups" : [ {
-    "name" : "name",
-    "id" : "id"
-  }, {
-    "name" : "name",
-    "id" : "id"
-  } ],
-  "minimum_license_required" : "basic",
-  "action_variables" : {
-    "context" : [ {
-      "name" : "name",
-      "description" : "description",
-      "useWithTripleBracesInTemplates" : true
-    }, {
-      "name" : "name",
-      "description" : "description",
-      "useWithTripleBracesInTemplates" : true
-    } ],
-    "state" : [ {
-      "name" : "name",
-      "description" : "description"
-    }, {
-      "name" : "name",
-      "description" : "description"
-    } ],
-    "params" : [ {
-      "name" : "name",
-      "description" : "description"
-    }, {
-      "name" : "name",
-      "description" : "description"
-    } ]
-  },
-  "rule_task_timeout" : "5m",
-  "name" : "name",
-  "enabled_in_license" : true,
-  "producer" : "stackAlerts",
-  "id" : "id",
-  "default_action_group_id" : "default_action_group_id"
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerts/alert/{alertId}
-
Create an alert. (legacyCreateAlert)
-
Deprecated in 7.13.0. Use the create rule API instead.
- -

Path parameters

-
-
alertId (required)
- -
Path Parameter — An UUID v1 or v4 identifier for the alert. If this parameter is omitted, the identifier is randomly generated. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
Legacy_create_alert_request_properties Legacy_create_alert_request_properties (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "alertTypeId" : ".index-threshold",
-  "throttle" : "throttle",
-  "updatedBy" : "elastic",
-  "executionStatus" : {
-    "lastExecutionDate" : "2022-12-06T00:13:43.89Z",
-    "status" : "ok"
-  },
-  "params" : {
-    "key" : ""
-  },
-  "enabled" : true,
-  "mutedInstanceIds" : [ "mutedInstanceIds", "mutedInstanceIds" ],
-  "tags" : [ "tags", "tags" ],
-  "createdAt" : "2022-12-05T23:36:58.284Z",
-  "schedule" : {
-    "interval" : "interval"
-  },
-  "notifyWhen" : "onActionGroupChange",
-  "createdBy" : "elastic",
-  "muteAll" : false,
-  "name" : "my alert",
-  "scheduledTaskId" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "actions" : [ "{}", "{}" ],
-  "apiKeyOwner" : "elastic",
-  "updatedAt" : "2022-12-05T23:36:58.284Z"
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - alert_response_properties -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerts/alert/{alertId}/_disable
-
Disables an alert. (legacyDisableAlert)
-
Deprecated in 7.13.0. Use the disable rule API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
alertId (required)
- -
Path Parameter — The identifier for the alert. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerts/alert/{alertId}/_enable
-
Enables an alert. (legacyEnableAlert)
-
Deprecated in 7.13.0. Use the enable rule API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
alertId (required)
- -
Path Parameter — The identifier for the alert. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
get /s/{spaceId}/api/alerts/alerts/_find
-
Retrieves a paginated set of alerts. (legacyFindAlerts)
-
Deprecated in 7.13.0. Use the find rules API instead. NOTE: Alert params are stored as a flattened field type and analyzed as keywords. As alerts change in Kibana, the results on each page of the response also change. Use the find API for traditional paginated results, but avoid using it to export large amounts of data.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
default_search_operator (optional)
- -
Query Parameter — The default operator to use for the simple_query_string. default: OR
fields (optional)
- -
Query Parameter — The fields to return in the attributes key of the response. default: null
filter (optional)
- -
Query Parameter — A KQL string that you filter with an attribute from your saved object. It should look like savedObjectType.attributes.title: "myTitle". However, if you used a direct attribute of a saved object, such as updatedAt, you must define your filter, for example, savedObjectType.updatedAt > 2018-12-22. default: null
has_reference (optional)
- -
Query Parameter — Filters the rules that have a relation with the reference objects with a specific type and identifier. default: null
page (optional)
- -
Query Parameter — The page number to return. default: 1
per_page (optional)
- -
Query Parameter — The number of alerts to return per page. default: 20
search (optional)
- -
Query Parameter — An Elasticsearch simple_query_string query that filters the alerts in the response. default: null
search_fields (optional)
- -
Query Parameter — The fields to perform the simple_query_string parsed query against. default: null
sort_field (optional)
- -
Query Parameter — Determines which field is used to sort the results. The field must exist in the attributes key of the response. default: null
sort_order (optional)
- -
Query Parameter — Determines the sort order. default: desc
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "total" : 1,
-  "perPage" : 6,
-  "data" : [ {
-    "alertTypeId" : ".index-threshold",
-    "throttle" : "throttle",
-    "updatedBy" : "elastic",
-    "executionStatus" : {
-      "lastExecutionDate" : "2022-12-06T00:13:43.89Z",
-      "status" : "ok"
-    },
-    "params" : {
-      "key" : ""
-    },
-    "enabled" : true,
-    "mutedInstanceIds" : [ "mutedInstanceIds", "mutedInstanceIds" ],
-    "tags" : [ "tags", "tags" ],
-    "createdAt" : "2022-12-05T23:36:58.284Z",
-    "schedule" : {
-      "interval" : "interval"
-    },
-    "notifyWhen" : "onActionGroupChange",
-    "createdBy" : "elastic",
-    "muteAll" : false,
-    "name" : "my alert",
-    "scheduledTaskId" : "b530fed0-74f5-11ed-9801-35303b735aef",
-    "id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-    "actions" : [ "{}", "{}" ],
-    "apiKeyOwner" : "elastic",
-    "updatedAt" : "2022-12-05T23:36:58.284Z"
-  }, {
-    "alertTypeId" : ".index-threshold",
-    "throttle" : "throttle",
-    "updatedBy" : "elastic",
-    "executionStatus" : {
-      "lastExecutionDate" : "2022-12-06T00:13:43.89Z",
-      "status" : "ok"
-    },
-    "params" : {
-      "key" : ""
-    },
-    "enabled" : true,
-    "mutedInstanceIds" : [ "mutedInstanceIds", "mutedInstanceIds" ],
-    "tags" : [ "tags", "tags" ],
-    "createdAt" : "2022-12-05T23:36:58.284Z",
-    "schedule" : {
-      "interval" : "interval"
-    },
-    "notifyWhen" : "onActionGroupChange",
-    "createdBy" : "elastic",
-    "muteAll" : false,
-    "name" : "my alert",
-    "scheduledTaskId" : "b530fed0-74f5-11ed-9801-35303b735aef",
-    "id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-    "actions" : [ "{}", "{}" ],
-    "apiKeyOwner" : "elastic",
-    "updatedAt" : "2022-12-05T23:36:58.284Z"
-  } ],
-  "page" : 0
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - legacyFindAlerts_200_response -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
get /s/{spaceId}/api/alerts/alert/{alertId}
-
Retrieves an alert by its identifier. (legacyGetAlert)
-
Deprecated in 7.13.0. Use the get rule API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
alertId (required)
- -
Path Parameter — The identifier for the alert. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "alertTypeId" : ".index-threshold",
-  "throttle" : "throttle",
-  "updatedBy" : "elastic",
-  "executionStatus" : {
-    "lastExecutionDate" : "2022-12-06T00:13:43.89Z",
-    "status" : "ok"
-  },
-  "params" : {
-    "key" : ""
-  },
-  "enabled" : true,
-  "mutedInstanceIds" : [ "mutedInstanceIds", "mutedInstanceIds" ],
-  "tags" : [ "tags", "tags" ],
-  "createdAt" : "2022-12-05T23:36:58.284Z",
-  "schedule" : {
-    "interval" : "interval"
-  },
-  "notifyWhen" : "onActionGroupChange",
-  "createdBy" : "elastic",
-  "muteAll" : false,
-  "name" : "my alert",
-  "scheduledTaskId" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "actions" : [ "{}", "{}" ],
-  "apiKeyOwner" : "elastic",
-  "updatedAt" : "2022-12-05T23:36:58.284Z"
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - alert_response_properties -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
get /s/{spaceId}/api/alerts/alerts/list_alert_types
-
Retrieves a list of alert types. (legacyGetAlertTypes)
-
Deprecated in 7.13.0. Use the get rule types API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "defaultActionGroupId" : "defaultActionGroupId",
-  "isExportable" : true,
-  "actionVariables" : {
-    "context" : [ {
-      "name" : "name",
-      "description" : "description"
-    }, {
-      "name" : "name",
-      "description" : "description"
-    } ],
-    "state" : [ {
-      "name" : "name",
-      "description" : "description"
-    }, {
-      "name" : "name",
-      "description" : "description"
-    } ],
-    "params" : [ {
-      "name" : "name",
-      "description" : "description"
-    }, {
-      "name" : "name",
-      "description" : "description"
-    } ]
-  },
-  "actionGroups" : [ {
-    "name" : "name",
-    "id" : "id"
-  }, {
-    "name" : "name",
-    "id" : "id"
-  } ],
-  "name" : "name",
-  "producer" : "producer",
-  "authorizedConsumers" : "{}",
-  "recoveryActionGroup" : {
-    "name" : "name",
-    "id" : "id"
-  },
-  "enabledInLicense" : true,
-  "id" : "id",
-  "minimumLicenseRequired" : "minimumLicenseRequired"
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
get /s/{spaceId}/api/alerts/alerts/_health
-
Retrieves the health status of the alerting framework. (legacyGetAlertingHealth)
-
Deprecated in 7.13.0. Use the get alerting framework health API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "hasPermanentEncryptionKey" : true,
-  "alertingFrameworkHealth" : {
-    "executionHealth" : {
-      "status" : "ok",
-      "timestamp" : "2023-01-13T01:28:00.28Z"
-    },
-    "decryptionHealth" : {
-      "status" : "ok",
-      "timestamp" : "2023-01-13T01:28:00.28Z"
-    },
-    "readHealth" : {
-      "status" : "ok",
-      "timestamp" : "2023-01-13T01:28:00.28Z"
-    }
-  },
-  "isSufficientlySecure" : true
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - legacyGetAlertingHealth_200_response -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_mute
-
Mutes an alert instance. (legacyMuteAlertInstance)
-
Deprecated in 7.13.0. Use the mute alert API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
alertId (required)
- -
Path Parameter — An identifier for the alert. default: null
alertInstanceId (required)
- -
Path Parameter — An identifier for the alert instance. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerts/alert/{alertId}/_mute_all
-
Mutes all alert instances. (legacyMuteAllAlertInstances)
-
Deprecated in 7.13.0. Use the mute all alerts API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
alertId (required)
- -
Path Parameter — The identifier for the alert. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute
-
Unmutes an alert instance. (legacyUnmuteAlertInstance)
-
Deprecated in 7.13.0. Use the unmute alert API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
alertId (required)
- -
Path Parameter — An identifier for the alert. default: null
alertInstanceId (required)
- -
Path Parameter — An identifier for the alert instance. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerts/alert/{alertId}/_unmute_all
-
Unmutes all alert instances. (legacyUnmuteAllAlertInstances)
-
Deprecated in 7.13.0. Use the unmute all alerts API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
alertId (required)
- -
Path Parameter — The identifier for the alert. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
put /s/{spaceId}/api/alerts/alert/{alertId}
-
Updates the attributes for an alert. (legacyUpdateAlert)
-
Deprecated in 7.13.0. Use the update rule API instead.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
alertId (required)
- -
Path Parameter — The identifier for the alert. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
Legacy_update_alert_request_properties Legacy_update_alert_request_properties (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "alertTypeId" : ".index-threshold",
-  "throttle" : "throttle",
-  "updatedBy" : "elastic",
-  "executionStatus" : {
-    "lastExecutionDate" : "2022-12-06T00:13:43.89Z",
-    "status" : "ok"
-  },
-  "params" : {
-    "key" : ""
-  },
-  "enabled" : true,
-  "mutedInstanceIds" : [ "mutedInstanceIds", "mutedInstanceIds" ],
-  "tags" : [ "tags", "tags" ],
-  "createdAt" : "2022-12-05T23:36:58.284Z",
-  "schedule" : {
-    "interval" : "interval"
-  },
-  "notifyWhen" : "onActionGroupChange",
-  "createdBy" : "elastic",
-  "muteAll" : false,
-  "name" : "my alert",
-  "scheduledTaskId" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "actions" : [ "{}", "{}" ],
-  "apiKeyOwner" : "elastic",
-  "updatedAt" : "2022-12-05T23:36:58.284Z"
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - alert_response_properties -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
delete /s/{spaceId}/api/alerts/alert/{alertId}
-
Permanently removes an alert. (legaryDeleteAlert)
-
Deprecated in 7.13.0. Use the delete rule API instead. WARNING: After you delete an alert, you cannot recover it.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
alertId (required)
- -
Path Parameter — The identifier for the alert. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_mute
-
Mutes an alert. (muteAlert)
-
You must have all privileges for the appropriate Kibana features, depending on the consumer and rule_type_id of the rule. For example, the Management > Stack Rules feature, Analytics > Discover and Machine Learning features, Observability, and Security features. If the rule has actions, you must also have read privileges for the Management > Actions and Connectors feature.
- -

Path parameters

-
-
alertId (required)
- -
Path Parameter — An identifier for the alert. The identifier is generated by the rule and might be any arbitrary string. default: null
ruleId (required)
- -
Path Parameter — An identifier for the rule. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerting/rule/{ruleId}/_mute_all
-
Mutes all alerts. (muteAllAlerts)
-
This API snoozes the notifications for the rule indefinitely. The rule checks continue to occur but alerts will not trigger any actions. You must have all privileges for the appropriate Kibana features, depending on the consumer and rule_type_id of the rule. For example, the Management > Stack Rules feature, Analytics > Discover and Machine Learning features, Observability, and Security features. If the rule has actions, you must also have read privileges for the Management > Actions and Connectors feature.
- -

Path parameters

-
-
ruleId (required)
- -
Path Parameter — An identifier for the rule. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_unmute
-
Unmutes an alert. (unmuteAlert)
-
You must have all privileges for the appropriate Kibana features, depending on the consumer and rule_type_id of the rule. For example, the Management > Stack Rules feature, Analytics > Discover and Machine Learning features, Observability, and Security features. If the rule has actions, you must also have read privileges for the Management > Actions and Connectors feature.
- -

Path parameters

-
-
alertId (required)
- -
Path Parameter — An identifier for the alert. The identifier is generated by the rule and might be any arbitrary string. default: null
ruleId (required)
- -
Path Parameter — An identifier for the rule. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerting/rule/{ruleId}/_unmute_all
-
Unmutes all alerts. (unmuteAllAlerts)
-
If the rule has its notifications snoozed indefinitely, this API cancels the snooze. You must have all privileges for the appropriate Kibana features, depending on the consumer and rule_type_id of the rule. For example, the Management > Stack Rules feature, Analytics > Discover and Machine Learning features, Observability, and Security features. If the rule has actions, you must also have read privileges for the Management > Actions and Connectors feature.
- -

Path parameters

-
-
ruleId (required)
- -
Path Parameter — An identifier for the rule. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

204

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 401_response -
-
-
-
- Up -
put /s/{spaceId}/api/alerting/rule/{ruleId}
-
Updates the attributes for a rule. (updateRule)
-
To update a rule, you must have all privileges for the appropriate Kibana features, depending on the consumer and rule_type_id of the rule you're updating. For example, you must have privileges for the Management > Stack rules feature, Analytics > Discover and Machine Learning features, Observability features, or Security features. If the rule has actions, you must also have read privileges for the Management > Actions and Connectors feature. This API supports both key- and token-based authentication. To use key-based authentication, create an API key in Kibana and use it in the header of the API call. To use token-based authentication, provide a username and password; an API key that matches the current privileges of the user is created automatically. In both cases, the API key is subsequently used for authorization when the rule runs. NOTE: If the API key has different privileges than the key that created or most recently updated the rule, the rule behavior might change. Though some properties are optional, when you update the rule the existing property values are overwritten with default values. Therefore, it is recommended to explicitly set all property values.
- -

Path parameters

-
-
ruleId (required)
- -
Path Parameter — An identifier for the rule. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    -
  • application/json
  • -
- -

Request body

-
-
update_rule_request update_rule_request (required)
- -
Body Parameter
- -
- -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "throttle" : "10m",
-  "created_at" : "2022-12-05T23:36:58.284Z",
-  "api_key_created_by_user" : false,
-  "enabled" : true,
-  "running" : true,
-  "notify_when" : "notify_when",
-  "next_run" : "2022-12-06T00:14:43.818Z",
-  "updated_at" : "2022-12-05T23:36:58.284Z",
-  "execution_status" : {
-    "last_execution_date" : "2022-12-06T00:13:43.89Z",
-    "last_duration" : 55,
-    "status" : "ok"
-  },
-  "scheduled_task_id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "id" : "b530fed0-74f5-11ed-9801-35303b735aef",
-  "consumer" : "alerts",
-  "last_run" : {
-    "alerts_count" : {
-      "ignored" : 6,
-      "new" : 1,
-      "recovered" : 5,
-      "active" : 0
-    },
-    "outcome_msg" : [ "outcome_msg", "outcome_msg" ],
-    "outcome_order" : 5,
-    "warning" : "warning",
-    "outcome" : "succeeded"
-  },
-  "params" : {
-    "key" : ""
-  },
-  "created_by" : "elastic",
-  "muted_alert_ids" : [ "muted_alert_ids", "muted_alert_ids" ],
-  "rule_type_id" : "monitoring_alert_cluster_health",
-  "revision" : 2,
-  "tags" : [ "tags", "tags" ],
-  "api_key_owner" : "elastic",
-  "schedule" : {
-    "interval" : "1m"
-  },
-  "name" : "cluster_health_rule",
-  "updated_by" : "elastic",
-  "mute_all" : false,
-  "actions" : [ {
-    "alerts_filter" : {
-      "timeframe" : {
-        "hours" : {
-          "start" : "08:00",
-          "end" : "17:00"
-        },
-        "timezone" : "Europe/Madrid",
-        "days" : [ 1, 2, 3, 4, 5 ]
-      },
-      "query" : {
-        "kql" : "kql",
-        "filters" : [ {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        }, {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        } ]
-      }
-    },
-    "id" : "9dca3e00-74f5-11ed-9801-35303b735aef",
-    "params" : {
-      "key" : ""
-    },
-    "uuid" : "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61",
-    "connector_type_id" : ".server-log",
-    "frequency" : {
-      "summary" : true,
-      "throttle" : "10m",
-      "notify_when" : "onActiveAlert"
-    },
-    "group" : "default"
-  }, {
-    "alerts_filter" : {
-      "timeframe" : {
-        "hours" : {
-          "start" : "08:00",
-          "end" : "17:00"
-        },
-        "timezone" : "Europe/Madrid",
-        "days" : [ 1, 2, 3, 4, 5 ]
-      },
-      "query" : {
-        "kql" : "kql",
-        "filters" : [ {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        }, {
-          "$state" : "{}",
-          "meta" : {
-            "field" : "field",
-            "controlledBy" : "controlledBy",
-            "negate" : true,
-            "alias" : "alias",
-            "index" : "index",
-            "disabled" : true,
-            "params" : "{}",
-            "type" : "type",
-            "value" : "value",
-            "isMultiIndex" : true,
-            "key" : "key",
-            "group" : "group"
-          },
-          "query" : "{}"
-        } ]
-      }
-    },
-    "id" : "9dca3e00-74f5-11ed-9801-35303b735aef",
-    "params" : {
-      "key" : ""
-    },
-    "uuid" : "1c7a1280-f28c-4e06-96b2-e4e5f05d1d61",
-    "connector_type_id" : ".server-log",
-    "frequency" : {
-      "summary" : true,
-      "throttle" : "10m",
-      "notify_when" : "onActiveAlert"
-    },
-    "group" : "default"
-  } ]
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - rule_response_properties -

401

- Authorization information is missing or invalid. - 401_response -

404

- Object is not found. - 404_response -
-
-
-
- Up -
post /s/{spaceId}/api/alerting/rule/{ruleId}/_update_api_key
-
Updates the API key for a rule. (updateRuleAPIKey)
-
The new API key has the credentials of the user that submits the request.
- -

Path parameters

-
-
ruleId (required)
- -
Path Parameter — An identifier for the rule. default: null
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - -

Request headers

-
-
kbn-xsrf (required)
- -
Header Parameter — Cross-site request forgery protection default: null
- -
- - - - - - - -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

400

- Bad request - 400_response -
-
- -

Models

- [ Jump to Methods ] - -

Table of Contents

-
    -
  1. 400_response - Bad request
  2. -
  3. 401_response - Unsuccessful rule API response
  4. -
  5. 404_response -
  6. -
  7. Count - Count
  8. -
  9. Count_count -
  10. -
  11. Count_criteria -
  12. -
  13. Count_logView -
  14. -
  15. Legacy_create_alert_request_properties - Legacy create alert request properties
  16. -
  17. Legacy_create_alert_request_properties_schedule -
  18. -
  19. Legacy_update_alert_request_properties - Legacy update alert request properties
  20. -
  21. Legacy_update_alert_request_properties_actions_inner -
  22. -
  23. Legacy_update_alert_request_properties_schedule -
  24. -
  25. Ratio - Ratio
  26. -
  27. actions_inner -
  28. -
  29. actions_inner_alerts_filter -
  30. -
  31. actions_inner_alerts_filter_query -
  32. -
  33. actions_inner_alerts_filter_timeframe -
  34. -
  35. actions_inner_alerts_filter_timeframe_hours -
  36. -
  37. actions_inner_frequency -
  38. -
  39. aggtype -
  40. -
  41. alert_response_properties - Legacy alert response properties
  42. -
  43. alert_response_properties_executionStatus -
  44. -
  45. alert_response_properties_schedule -
  46. -
  47. count_criterion - count criterion
  48. -
  49. create_anomaly_detection_alert_rule_request - Create anomaly detection rule request
  50. -
  51. create_anomaly_detection_jobs_health_rule_request - Create anomaly detection jobs health rule request
  52. -
  53. create_apm_anomaly_rule_request - Create APM anomaly rule rule request
  54. -
  55. create_apm_error_count_rule_request - Create APM error count rule request
  56. -
  57. create_apm_transaction_duration_rule_request - Create latency threshold rule request
  58. -
  59. create_apm_transaction_error_rate_rule_request - Create APM transaction error rate rule request
  60. -
  61. create_es_query_rule_request - Create Elasticsearch query rule request
  62. -
  63. create_geo_containment_rule_request - Create traacking containment rule request
  64. -
  65. create_index_threshold_rule_request - Create index threshold rule request
  66. -
  67. create_infra_inventory_rule_request - Create infra inventory rule request
  68. -
  69. create_infra_metric_anomaly_rule_request - Create infrastructure anomaly rule request
  70. -
  71. create_infra_metric_threshold_rule_request - Create infra metric threshold rule request
  72. -
  73. create_log_threshold_rule_request - Create log threshold rule request
  74. -
  75. create_monitoring_ccr_exceptions_rule_request - Create CCR read exceptions rule request
  76. -
  77. create_monitoring_cluster_health_rule_request - Create cluster health rule request
  78. -
  79. create_monitoring_cpu_usage_rule_request - Create CPU usage rule request
  80. -
  81. create_monitoring_disk_usage_rule_request - Create disk usage rule request
  82. -
  83. create_monitoring_elasticsearch_version_mismatch_rule_request - Create Elasticsearch version mismatch rule request
  84. -
  85. create_monitoring_jvm_memory_usage_rule_request - Create JVM memory usage rule request
  86. -
  87. create_monitoring_kibana_version_mismatch_rule_request - Create Kibana version mismatch rule request
  88. -
  89. create_monitoring_license_expiration_rule_request - Create license expiration rule request
  90. -
  91. create_monitoring_logstash_version_mismatch_rule_request - Create Logstash version mismatch rule request
  92. -
  93. create_monitoring_missing_data_rule_request - Create missing monitoring data rule request
  94. -
  95. create_monitoring_nodes_changed_rule_request - Create nodes changed rule request
  96. -
  97. create_monitoring_shard_size_rule_request - Create shard size rule request
  98. -
  99. create_monitoring_thread_pool_search_rejections_rule_request - Create thread pool search rejections rule request
  100. -
  101. create_monitoring_thread_pool_write_rejections_rule_request - Create thread pool write rejections rule request
  102. -
  103. create_rule_request - Create rule request body properties
  104. -
  105. create_siem_eql_rule_request - Create event correlation rule request
  106. -
  107. create_siem_indicator_rule_request - Create indicator match rule request
  108. -
  109. create_siem_ml_rule_request - Create machine learning rule request
  110. -
  111. create_siem_new_terms_rule_request - Create new terms rule request
  112. -
  113. create_siem_notifications_rule_request - Create security solution notification (legacy) rule request
  114. -
  115. create_siem_query_rule_request - Create custom query rule request
  116. -
  117. create_siem_saved_query_rule_request - Create saved query rule request
  118. -
  119. create_siem_threshold_rule_request - Create threshold rule request
  120. -
  121. create_slo_burn_rate_rule_request - Create slo burn rate rule request
  122. -
  123. create_synthetics_monitor_status_rule_request - Create synthetics monitor status rule request
  124. -
  125. create_synthetics_uptime_duration_anomaly_rule_request - Create synthetics uptime duration anomaly rule request
  126. -
  127. create_synthetics_uptime_tls_certificate_rule_request - Create TLS certificate rule request
  128. -
  129. create_synthetics_uptime_tls_rule_request - Create synthetics uptime TLS rule request
  130. -
  131. create_transform_health_rule_request - Create transform health rule request
  132. -
  133. create_uptime_monitor_status_rule_request - Create uptime monitor status rule request
  134. -
  135. custom_criterion - custom criterion
  136. -
  137. custom_criterion_customMetric_inner -
  138. -
  139. custom_criterion_customMetric_inner_oneOf -
  140. -
  141. custom_criterion_customMetric_inner_oneOf_1 -
  142. -
  143. filter -
  144. -
  145. filter_meta -
  146. -
  147. findRules_200_response -
  148. -
  149. findRules_has_reference_parameter -
  150. -
  151. findRules_search_fields_parameter -
  152. -
  153. getAlertingHealth_200_response -
  154. -
  155. getAlertingHealth_200_response_alerting_framework_health -
  156. -
  157. getAlertingHealth_200_response_alerting_framework_health_decryption_health -
  158. -
  159. getAlertingHealth_200_response_alerting_framework_health_execution_health -
  160. -
  161. getAlertingHealth_200_response_alerting_framework_health_read_health -
  162. -
  163. getRuleTypes_200_response_inner -
  164. -
  165. getRuleTypes_200_response_inner_action_groups_inner -
  166. -
  167. getRuleTypes_200_response_inner_action_variables -
  168. -
  169. getRuleTypes_200_response_inner_action_variables_context_inner -
  170. -
  171. getRuleTypes_200_response_inner_action_variables_params_inner -
  172. -
  173. getRuleTypes_200_response_inner_authorized_consumers -
  174. -
  175. getRuleTypes_200_response_inner_authorized_consumers_alerts -
  176. -
  177. getRuleTypes_200_response_inner_recovery_action_group -
  178. -
  179. groupby -
  180. -
  181. legacyFindAlerts_200_response -
  182. -
  183. legacyGetAlertTypes_200_response_inner -
  184. -
  185. legacyGetAlertTypes_200_response_inner_actionVariables -
  186. -
  187. legacyGetAlertTypes_200_response_inner_actionVariables_context_inner -
  188. -
  189. legacyGetAlertTypes_200_response_inner_recoveryActionGroup -
  190. -
  191. legacyGetAlertingHealth_200_response -
  192. -
  193. legacyGetAlertingHealth_200_response_alertingFrameworkHealth -
  194. -
  195. legacyGetAlertingHealth_200_response_alertingFrameworkHealth_decryptionHealth -
  196. -
  197. legacyGetAlertingHealth_200_response_alertingFrameworkHealth_executionHealth -
  198. -
  199. legacyGetAlertingHealth_200_response_alertingFrameworkHealth_readHealth -
  200. -
  201. non_count_criterion - non count criterion
  202. -
  203. notify_when -
  204. -
  205. params_es_query_rule -
  206. -
  207. params_es_query_rule_oneOf -
  208. -
  209. params_es_query_rule_oneOf_1 -
  210. -
  211. params_es_query_rule_oneOf_searchConfiguration -
  212. -
  213. params_es_query_rule_oneOf_searchConfiguration_query -
  214. -
  215. params_index_threshold_rule -
  216. -
  217. params_property_apm_anomaly -
  218. -
  219. params_property_apm_error_count -
  220. -
  221. params_property_apm_transaction_duration -
  222. -
  223. params_property_apm_transaction_error_rate -
  224. -
  225. params_property_infra_inventory -
  226. -
  227. params_property_infra_inventory_criteria_inner -
  228. -
  229. params_property_infra_inventory_criteria_inner_customMetric -
  230. -
  231. params_property_infra_metric_threshold -
  232. -
  233. params_property_infra_metric_threshold_criteria_inner -
  234. -
  235. params_property_log_threshold -
  236. -
  237. params_property_slo_burn_rate -
  238. -
  239. params_property_slo_burn_rate_longWindow -
  240. -
  241. params_property_slo_burn_rate_shortWindow -
  242. -
  243. params_property_synthetics_monitor_status -
  244. -
  245. params_property_synthetics_monitor_status_availability -
  246. -
  247. params_property_synthetics_monitor_status_filters -
  248. -
  249. params_property_synthetics_monitor_status_filters_oneOf -
  250. -
  251. params_property_synthetics_monitor_status_timerange -
  252. -
  253. params_property_synthetics_uptime_tls -
  254. -
  255. rule_response_properties - Rule response properties
  256. -
  257. rule_response_properties_execution_status -
  258. -
  259. rule_response_properties_last_run -
  260. -
  261. rule_response_properties_last_run_alerts_count -
  262. -
  263. schedule -
  264. -
  265. thresholdcomparator -
  266. -
  267. timewindowunit -
  268. -
  269. update_rule_request - Update rule request
  270. -
- -
-

400_response - Bad request Up

-
-
-
error
-
Enum:
-
Bad Request
-
message
-
statusCode
-
Enum:
-
400
-
-
-
-

401_response - Unsuccessful rule API response Up

-
-
-
error (optional)
-
Enum:
-
Unauthorized
-
message (optional)
-
statusCode (optional)
-
Enum:
-
401
-
-
-
-

404_response - Up

-
-
-
error (optional)
-
Enum:
-
Not Found
-
message (optional)
-
statusCode (optional)
-
Enum:
-
404
-
-
-
-

Count - Count Up

-
-
-
criteria (optional)
-
count
-
timeSize
-
timeUnit
-
Enum:
-
s
m
h
d
-
logView
-
groupBy (optional)
-
-
-
-

Count_count - Up

-
-
-
comparator (optional)
-
Enum:
-
more than
more than or equals
less than
less than or equals
equals
does not equal
matches
does not match
matches phrase
does not match phrase
-
value (optional)
-
-
-
-

Count_criteria - Up

-
-
-
field (optional)
-
comparator (optional)
-
Enum:
-
more than
more than or equals
less than
less than or equals
equals
does not equal
matches
does not match
matches phrase
does not match phrase
-
value (optional)
-
-
-
-

Count_logView - Up

-
-
-
logViewId (optional)
-
type (optional)
-
Enum:
-
log-view-reference
-
-
-
-

Legacy_create_alert_request_properties - Legacy create alert request properties Up

-
-
-
actions (optional)
-
alertTypeId
String The ID of the alert type that you want to call when the alert is scheduled to run.
-
consumer
String The name of the application that owns the alert. This name has to match the Kibana feature name, as that dictates the required role-based access control privileges.
-
enabled (optional)
Boolean Indicates if you want to run the alert on an interval basis after it is created.
-
name
String A name to reference and search.
-
notifyWhen
String The condition for throttling the notification.
-
Enum:
-
onActionGroupChange
onActiveAlert
onThrottleInterval
-
params
Object The parameters to pass to the alert type executor params value. This will also validate against the alert type params validator, if defined.
-
schedule
-
tags (optional)
array[String] A list of keywords to reference and search.
-
throttle (optional)
String How often this alert should fire the same actions. This will prevent the alert from sending out the same notification over and over. For example, if an alert with a schedule of 1 minute stays in a triggered state for 90 minutes, setting a throttle of 10m or 1h will prevent it from sending 90 notifications during this period.
-
-
-
-

Legacy_create_alert_request_properties_schedule - Up

-
The schedule specifying when this alert should be run. A schedule is structured such that the key specifies the format you wish to use and its value specifies the schedule.
-
-
interval (optional)
String The interval format specifies the interval in seconds, minutes, hours or days at which the alert should execute.
-
-
-
-

Legacy_update_alert_request_properties - Legacy update alert request properties Up

-
-
-
actions (optional)
-
name
String A name to reference and search.
-
notifyWhen
String The condition for throttling the notification.
-
Enum:
-
onActionGroupChange
onActiveAlert
onThrottleInterval
-
params
Object The parameters to pass to the alert type executor params value. This will also validate against the alert type params validator, if defined.
-
schedule
-
tags (optional)
array[String] A list of keywords to reference and search.
-
throttle (optional)
String How often this alert should fire the same actions. This will prevent the alert from sending out the same notification over and over. For example, if an alert with a schedule of 1 minute stays in a triggered state for 90 minutes, setting a throttle of 10m or 1h will prevent it from sending 90 notifications during this period.
-
-
-
-

Legacy_update_alert_request_properties_actions_inner - Up

-
-
-
actionTypeId
String The identifier for the action type.
-
group
String Grouping actions is recommended for escalations for different types of alert instances. If you don't need this functionality, set it to default.
-
id
String The ID of the action saved object to execute.
-
params
Object The map to the params that the action type will receive. params are handled as Mustache templates and passed a default set of context.
-
-
-
-

Legacy_update_alert_request_properties_schedule - Up

-
The schedule specifying when this alert should be run. A schedule is structured such that the key specifies the format you wish to use and its value specifies the schedule.
-
-
interval (optional)
String The interval format specifies the interval in seconds, minutes, hours or days at which the alert should execute.
-
-
-
-

Ratio - Ratio Up

-
-
-
criteria (optional)
-
count
-
timeSize
-
timeUnit
-
Enum:
-
s
m
h
d
-
logView
-
groupBy (optional)
-
-
-
-

actions_inner - Up

-
An action that runs under defined conditions.
-
-
alerts_filter (optional)
-
connector_type_id (optional)
String The type of connector. This property appears in responses but cannot be set in requests.
-
frequency (optional)
-
group
String The group name, which affects when the action runs (for example, when the threshold is met or when the alert is recovered). Each rule type has a list of valid action group names. If you don't need to group actions, set to default.
-
id
String The identifier for the connector saved object.
-
params
map[String, oas_any_type_not_mapped] The parameters for the action, which are sent to the connector. The params are handled as Mustache templates and passed a default set of context.
-
uuid (optional)
String A universally unique identifier (UUID) for the action.
-
-
-
-

actions_inner_alerts_filter - Up

-
Conditions that affect whether the action runs. If you specify multiple conditions, all conditions must be met for the action to run. For example, if an alert occurs within the specified time frame and matches the query, the action runs.
- -
-
-

actions_inner_alerts_filter_query - Up

-
Defines a query filter that determines whether the action runs.
-
-
kql (optional)
String A filter written in Kibana Query Language (KQL).
-
filters (optional)
-
-
-
-

actions_inner_alerts_filter_timeframe - Up

-
Defines a period that limits whether the action runs.
-
-
days (optional)
array[Integer] Defines the days of the week that the action can run, represented as an array of numbers. For example, 1 represents Monday. An empty array is equivalent to specifying all the days of the week.
-
hours (optional)
-
timezone (optional)
String The ISO time zone for the hours values. Values such as UTC and UTC+1 also work but lack built-in daylight savings time support and are not recommended.
-
-
-
-

actions_inner_alerts_filter_timeframe_hours - Up

-
Defines the range of time in a day that the action can run. If the start value is 00:00 and the end value is 24:00, actions be generated all day.
-
-
end (optional)
String The end of the time frame in 24-hour notation (hh:mm).
-
start (optional)
String The start of the time frame in 24-hour notation (hh:mm).
-
-
-
-

actions_inner_frequency - Up

-
The properties that affect how often actions are generated. If the rule type supports setting summary to true, the action can be a summary of alerts at the specified notification interval. Otherwise, an action runs for each alert at the specified notification interval. NOTE: You cannot specify these parameters when notify_when or throttle are defined at the rule level.
-
-
notify_when
-
summary
Boolean Indicates whether the action is a summary.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

aggtype - Up

-
The type of aggregation to perform.
-
-
-
-
-

alert_response_properties - Legacy alert response properties Up

-
-
-
actions (optional)
-
alertTypeId (optional)
-
apiKeyOwner (optional)
-
createdAt (optional)
Date The date and time that the alert was created. format: date-time
-
createdBy (optional)
String The identifier for the user that created the alert.
-
enabled (optional)
Boolean Indicates whether the alert is currently enabled.
-
executionStatus (optional)
-
id (optional)
String The identifier for the alert.
-
muteAll (optional)
-
mutedInstanceIds (optional)
-
name (optional)
String The name of the alert.
-
notifyWhen (optional)
-
params (optional)
-
schedule (optional)
-
scheduledTaskId (optional)
-
tags (optional)
-
throttle (optional)
-
updatedAt (optional)
-
updatedBy (optional)
String The identifier for the user that updated this alert most recently.
-
-
-
-

alert_response_properties_executionStatus - Up

-
-
-
lastExecutionDate (optional)
Date format: date-time
-
status (optional)
-
-
-
-

alert_response_properties_schedule - Up

-
-
-
interval (optional)
-
-
-
-

count_criterion - count criterion Up

-
-
-
threshold (optional)
-
comparator (optional)
-
Enum:
-
<
<=
>
>=
between
outside
-
timeUnit (optional)
-
timeSize (optional)
-
warningThreshold (optional)
-
warningComparator (optional)
-
Enum:
-
<
<=
>
>=
between
outside
-
aggType (optional)
-
Enum:
-
count
-
-
-
-

create_anomaly_detection_alert_rule_request - Create anomaly detection rule request Up

-
A rule that checks if the anomaly detection job results contain anomalies that match the rule conditions.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for an anomaly detection rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
xpack.ml.anomaly_detection_alert
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_anomaly_detection_jobs_health_rule_request - Create anomaly detection jobs health rule request Up

-
An rule that monitors job health and alerts if an operational issue occurred that may prevent the job from detecting anomalies.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for an anomaly detection jobs health rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
xpack.ml.anomaly_detection_jobs_health
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_apm_anomaly_rule_request - Create APM anomaly rule rule request Up

-
A rule that detects when either the latency, throughput, or failed transaction rate of a service is anomalous.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
apm.anomaly
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_apm_error_count_rule_request - Create APM error count rule request Up

-
A rule that detects when the number of errors in a service exceeds a defined threshold.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
apm.error_rate
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_apm_transaction_duration_rule_request - Create latency threshold rule request Up

-
A rule that detects when the latency of a specific transaction type in a service exceeds a threshold.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
apm.transaction_duration
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_apm_transaction_error_rate_rule_request - Create APM transaction error rate rule request Up

-
A rule that sends notifications when the rate of transaction errors in a service exceeds a threshold.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
apm.transaction_error_rate
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_es_query_rule_request - Create Elasticsearch query rule request Up

-
A rule that runs a user-configured query, compares the number of matches to a configured threshold, and schedules actions to run when the threshold condition is met.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
.es-query
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_geo_containment_rule_request - Create traacking containment rule request Up

-
A rule that runs an Elasticsearch query over indices to determine whether any documents are currently contained within any boundaries from the specified boundary index. In the event that an entity is contained within a boundary, an alert may be generated.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for an tracking containment rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
.geo-containment
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_index_threshold_rule_request - Create index threshold rule request Up

-
A rule that runs an Elasticsearch query, aggregates field values from documents, compares them to threshold values, and schedules actions to run when the thresholds are met.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
.index-threshold
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_infra_inventory_rule_request - Create infra inventory rule request Up

-
A rule that sends notifications when a metric has reached or exceeded a value for a specific resource or a group of resources within your infrastructure.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
metrics.alert.inventory.threshold
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_infra_metric_anomaly_rule_request - Create infrastructure anomaly rule request Up

-
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for an infrastructure anomaly rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
metrics.alert.anomaly
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_infra_metric_threshold_rule_request - Create infra metric threshold rule request Up

-
A rule that sends notifications when a metric has reached or exceeded a value for a specific time period.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
metrics.alert.threshold
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_log_threshold_rule_request - Create log threshold rule request Up

-
A rule that detects when a log aggregation exceeds a threshold.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
logs.alert.document.count
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_ccr_exceptions_rule_request - Create CCR read exceptions rule request Up

-
A rule that detects cross-cluster replication (CCR) read exceptions.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a CCR read exceptions rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_ccr_read_exceptions
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_cluster_health_rule_request - Create cluster health rule request Up

-
A rule that detects when the health of the cluster changes.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a cluster health rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_alert_cluster_health
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_cpu_usage_rule_request - Create CPU usage rule request Up

-
A rule that detects when the CPU load for a node is consistently high.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a CPU usage rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_alert_cpu_usage
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_disk_usage_rule_request - Create disk usage rule request Up

-
A rule that detects when the disk usage for a node is consistently high.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a disk usage rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_alert_disk_usage
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_elasticsearch_version_mismatch_rule_request - Create Elasticsearch version mismatch rule request Up

-
A rule that detects when the cluster has multipe versions of Elasticsearch.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a Elasticsearch version mismatch rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_alert_elasticsearch_version_mismatch
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_jvm_memory_usage_rule_request - Create JVM memory usage rule request Up

-
A rule that detects when a node reports high memory usage.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a JVM memory usage rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_alert_jvm_memory_usage
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_kibana_version_mismatch_rule_request - Create Kibana version mismatch rule request Up

-
A rule that detects when the cluster has multiple versions of Kibana.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a Kibana version mismatch rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_alert_kibana_version_mismatch
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_license_expiration_rule_request - Create license expiration rule request Up

-
A rule that detects when the cluster license is about to expire.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a license expiration rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_alert_license_expiration
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_logstash_version_mismatch_rule_request - Create Logstash version mismatch rule request Up

-
A rule that detects when the cluster has multiple versions of Logstash.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a Logstash version mismatch rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_alert_logstash_version_mismatch
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_missing_data_rule_request - Create missing monitoring data rule request Up

-
A rule that detects when monitoring data is missing.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a missing monitoring data rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_alert_missing_monitoring_data
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_nodes_changed_rule_request - Create nodes changed rule request Up

-
A rule that detects when nodes are added, removed, or restarted.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a nodes changed rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_alert_nodes_changed
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_shard_size_rule_request - Create shard size rule request Up

-
A rule that detects when the average shard size is larger than a threshold.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a shard size rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_shard_size
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_thread_pool_search_rejections_rule_request - Create thread pool search rejections rule request Up

-
A rule that detects when the number of rejections in the thread pool exceeds a threshold.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a thread pool search rejections rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_alert_thread_pool_search_rejections
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_monitoring_thread_pool_write_rejections_rule_request - Create thread pool write rejections rule request Up

-
A rule that detects when the number of rejections in the write thread pool exceeds a threshold.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a thread pool write rejections rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
monitoring_alert_thread_pool_write_rejections
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_rule_request - Create rule request body properties Up

-
The properties vary depending on the rule type.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
xpack.uptime.alerts.monitorStatus
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_siem_eql_rule_request - Create event correlation rule request Up

-
A rule that uses Event Query Language (EQL) to match events, generate sequences, and stack data.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for an event correlation rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
siem.eqlRule
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_siem_indicator_rule_request - Create indicator match rule request Up

-
A rule that uses indicators from intelligence sources to detect matching events and alerts.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for an indicator match rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
siem.indicatorRule
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_siem_ml_rule_request - Create machine learning rule request Up

-
A rule that detects when a machine learning job discovers an anomaly above the defined threshold.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a machine learning rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
siem.mlRule
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_siem_new_terms_rule_request - Create new terms rule request Up

-
A rule that finds documents with values that appear for the first time.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a new terms rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
siem.newTermsRule
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_siem_notifications_rule_request - Create security solution notification (legacy) rule request Up

-
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a notification rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
siem.notifications
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_siem_query_rule_request - Create custom query rule request Up

-
A rule that uses KQL or Lucene to detect issues across indices.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a custom query rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
siem.queryRule
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_siem_saved_query_rule_request - Create saved query rule request Up

-
A rule that searches the defined indices and creates an alert when a document matches the saved search.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a saved query rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
siem.savedQueryRule
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_siem_threshold_rule_request - Create threshold rule request Up

-
A rule that aggregates query results to detect when the number of matches exceeds a threshold.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a threshold rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
siem.thresholdRule
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_slo_burn_rate_rule_request - Create slo burn rate rule request Up

-
A rule that detects when the burn rate is above a defined threshold for two different lookback periods. The two periods are a long period and a short period that is 1/12th of the long period. For each lookback period, the burn rate is computed as the error rate divided by the error budget. When the burn rates for both periods surpass the threshold, an alert occurs.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
slo.rules.burnRate
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_synthetics_monitor_status_rule_request - Create synthetics monitor status rule request Up

-
A rule that detects when a monitor is down or an availability threshold is breached.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for the synthetics monitor status rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
xpack.synthetics.alerts.monitorStatus
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_synthetics_uptime_duration_anomaly_rule_request - Create synthetics uptime duration anomaly rule request Up

-
A rule that detects response durations for all of the geographic locations of each monitor. When a monitor runs for an unusual amount of time, at a particular time, an anomaly is recorded.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for the uptime duration anomaly rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
xpack.uptime.alerts.durationAnomaly
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_synthetics_uptime_tls_certificate_rule_request - Create TLS certificate rule request Up

-
A rule that detects when a monitor has a TLS certificate expiring or when it exceeds an age limit.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a TLS certificate rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
xpack.uptime.alerts.tlsCertificate
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_synthetics_uptime_tls_rule_request - Create synthetics uptime TLS rule request Up

-
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
xpack.uptime.alerts.tls
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_transform_health_rule_request - Create transform health rule request Up

-
A rule that monitors transforms health and alerts if an operational issue occurred.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for a transform health rule.
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
transform_health
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

create_uptime_monitor_status_rule_request - Create uptime monitor status rule request Up

-
A rule that detects monitor errors and outages.
-
-
actions (optional)
-
consumer
String The name of the application or feature that owns the rule. For example: alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
enabled (optional)
Boolean Indicates whether you want to run the rule on an interval basis after it is created.
-
name
String The name of the rule. While this name does not have to be unique, a distinctive name can help you identify a rule.
-
notify_when (optional)
-
params
-
rule_type_id
String The ID of the rule type that you want to call when the rule is scheduled to run.
-
Enum:
-
xpack.uptime.alerts.monitorStatus
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-

custom_criterion - custom criterion Up

-
-
-
threshold (optional)
-
comparator (optional)
-
Enum:
-
<
<=
>
>=
between
outside
-
timeUnit (optional)
-
timeSize (optional)
-
warningThreshold (optional)
-
warningComparator (optional)
-
Enum:
-
<
<=
>
>=
between
outside
-
aggType (optional)
-
Enum:
-
custom
-
customMetric (optional)
-
equation (optional)
-
label (optional)
-
-
-
-

custom_criterion_customMetric_inner - Up

-
-
-
name (optional)
-
aggType (optional)
-
Enum:
-
count
-
field (optional)
-
filter (optional)
-
-
-
-

custom_criterion_customMetric_inner_oneOf - Up

-
-
-
name (optional)
-
aggType (optional)
-
Enum:
-
avg
sum
max
min
cardinality
-
field (optional)
-
-
-
-

custom_criterion_customMetric_inner_oneOf_1 - Up

-
-
-
name (optional)
-
aggType (optional)
-
Enum:
-
count
-
filter (optional)
-
-
-
-

filter - Up

-
A filter written in Elasticsearch Query Domain Specific Language (DSL) as defined in the kbn-es-query package.
-
-
meta (optional)
-
query (optional)
-
Dollarstate (optional)
-
-
-
-

filter_meta - Up

-
-
-
alias (optional)
-
controlledBy (optional)
-
disabled (optional)
-
field (optional)
-
group (optional)
-
index (optional)
-
isMultiIndex (optional)
-
key (optional)
-
negate (optional)
-
params (optional)
-
type (optional)
-
value (optional)
-
-
-
-

findRules_200_response - Up

-
-
-
data (optional)
-
page (optional)
-
per_page (optional)
-
total (optional)
-
-
-
-

findRules_has_reference_parameter - Up

-
-
-
id (optional)
-
type (optional)
-
-
- -
-

getAlertingHealth_200_response - Up

-
-
-
alerting_framework_health (optional)
-
has_permanent_encryption_key (optional)
Boolean If false, the encrypted saved object plugin does not have a permanent encryption key.
-
is_sufficiently_secure (optional)
Boolean If false, security is enabled but TLS is not.
-
-
-
-

getAlertingHealth_200_response_alerting_framework_health - Up

-
Three substates identify the health of the alerting framework: decryption_health, execution_health, and read_health.
- -
-
-

getAlertingHealth_200_response_alerting_framework_health_decryption_health - Up

-
The timestamp and status of the rule decryption.
-
-
status (optional)
-
Enum:
-
error
ok
warn
-
timestamp (optional)
Date format: date-time
-
-
-
-

getAlertingHealth_200_response_alerting_framework_health_execution_health - Up

-
The timestamp and status of the rule run.
-
-
status (optional)
-
Enum:
-
error
ok
warn
-
timestamp (optional)
Date format: date-time
-
-
-
-

getAlertingHealth_200_response_alerting_framework_health_read_health - Up

-
The timestamp and status of the rule reading events.
-
-
status (optional)
-
Enum:
-
error
ok
warn
-
timestamp (optional)
Date format: date-time
-
-
-
-

getRuleTypes_200_response_inner - Up

-
-
-
action_groups (optional)
array[getRuleTypes_200_response_inner_action_groups_inner] An explicit list of groups for which the rule type can schedule actions, each with the action group's unique ID and human readable name. Rule actions validation uses this configuration to ensure that groups are valid.
-
action_variables (optional)
-
authorized_consumers (optional)
-
default_action_group_id (optional)
String The default identifier for the rule type group.
-
does_set_recovery_context (optional)
Boolean Indicates whether the rule passes context variables to its recovery action.
-
enabled_in_license (optional)
Boolean Indicates whether the rule type is enabled or disabled based on the subscription.
-
id (optional)
String The unique identifier for the rule type.
-
is_exportable (optional)
Boolean Indicates whether the rule type is exportable in Stack Management > Saved Objects.
-
minimum_license_required (optional)
String The subscriptions required to use the rule type.
-
name (optional)
String The descriptive name of the rule type.
-
producer (optional)
String An identifier for the application that produces this rule type.
-
recovery_action_group (optional)
-
rule_task_timeout (optional)
-
-
- -
-

getRuleTypes_200_response_inner_action_variables - Up

-
A list of action variables that the rule type makes available via context and state in action parameter templates, and a short human readable description. When you create a rule in Kibana, it uses this information to prompt you for these variables in action parameter editors.
- -
-
-

getRuleTypes_200_response_inner_action_variables_context_inner - Up

-
-
-
name (optional)
-
description (optional)
-
useWithTripleBracesInTemplates (optional)
-
-
-
-

getRuleTypes_200_response_inner_action_variables_params_inner - Up

-
-
-
description (optional)
-
name (optional)
-
-
- - -
-

getRuleTypes_200_response_inner_recovery_action_group - Up

-
An action group to use when an alert goes from an active state to an inactive one.
-
-
id (optional)
-
name (optional)
-
-
-
-

groupby - Up

-
Indicates whether the aggregation is applied over all documents (all) or split into groups (top) using a grouping field (termField). If grouping is used, an alert will be created for each group when it exceeds the threshold; only the top groups (up to termSize number of groups) are checked.
-
-
-
-
-

legacyFindAlerts_200_response - Up

-
-
-
data (optional)
-
page (optional)
-
perPage (optional)
-
total (optional)
-
-
-
-

legacyGetAlertTypes_200_response_inner - Up

-
-
-
actionGroups (optional)
array[getRuleTypes_200_response_inner_action_groups_inner] An explicit list of groups for which the alert type can schedule actions, each with the action group's unique ID and human readable name. Alert actions validation uses this configuration to ensure that groups are valid.
-
actionVariables (optional)
-
authorizedConsumers (optional)
Object The list of the plugins IDs that have access to the alert type.
-
defaultActionGroupId (optional)
String The default identifier for the alert type group.
-
enabledInLicense (optional)
Boolean Indicates whether the rule type is enabled based on the subscription.
-
id (optional)
String The unique identifier for the alert type.
-
isExportable (optional)
Boolean Indicates whether the alert type is exportable in Saved Objects Management UI.
-
minimumLicenseRequired (optional)
String The subscriptions required to use the alert type.
-
name (optional)
String The descriptive name of the alert type.
-
producer (optional)
String An identifier for the application that produces this alert type.
-
recoveryActionGroup (optional)
-
-
-
-

legacyGetAlertTypes_200_response_inner_actionVariables - Up

-
A list of action variables that the alert type makes available via context and state in action parameter templates, and a short human readable description. The Alert UI will use this information to prompt users for these variables in action parameter editors.
- -
- -
-

legacyGetAlertTypes_200_response_inner_recoveryActionGroup - Up

-
An action group to use when an alert instance goes from an active state to an inactive one. If it is not specified, the default recovered action group is used.
-
-
id (optional)
-
name (optional)
-
-
-
-

legacyGetAlertingHealth_200_response - Up

-
-
-
alertingFrameworkHealth (optional)
-
hasPermanentEncryptionKey (optional)
Boolean If false, the encrypted saved object plugin does not have a permanent encryption key.
-
isSufficientlySecure (optional)
Boolean If false, security is enabled but TLS is not.
-
-
-
-

legacyGetAlertingHealth_200_response_alertingFrameworkHealth - Up

-
Three substates identify the health of the alerting framework: decryptionHealth, executionHealth, and readHealth.
- -
-
-

legacyGetAlertingHealth_200_response_alertingFrameworkHealth_decryptionHealth - Up

-
The timestamp and status of the alert decryption.
-
-
status (optional)
-
Enum:
-
error
ok
warn
-
timestamp (optional)
Date format: date-time
-
-
-
-

legacyGetAlertingHealth_200_response_alertingFrameworkHealth_executionHealth - Up

-
The timestamp and status of the alert execution.
-
-
status (optional)
-
Enum:
-
error
ok
warn
-
timestamp (optional)
Date format: date-time
-
-
-
-

legacyGetAlertingHealth_200_response_alertingFrameworkHealth_readHealth - Up

-
The timestamp and status of the alert reading events.
-
-
status (optional)
-
Enum:
-
error
ok
warn
-
timestamp (optional)
Date format: date-time
-
-
-
-

non_count_criterion - non count criterion Up

-
-
-
threshold (optional)
-
comparator (optional)
-
Enum:
-
<
<=
>
>=
between
outside
-
timeUnit (optional)
-
timeSize (optional)
-
warningThreshold (optional)
-
warningComparator (optional)
-
Enum:
-
<
<=
>
>=
between
outside
-
metric (optional)
-
aggType (optional)
-
Enum:
-
avg
max
min
cardinality
rate
count
sum
p95
p99
custom
-
-
-
-

notify_when - Up

-
Indicates how often alerts generate actions. Valid values include: onActionGroupChange: Actions run when the alert status changes; onActiveAlert: Actions run when the alert becomes active and at each check interval while the rule conditions are met; onThrottleInterval: Actions run when the alert becomes active and at the interval specified in the throttle property while the rule conditions are met. NOTE: You cannot specify notify_when at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-
-

params_es_query_rule - Up

-
-
-
aggField (optional)
String The name of the numeric field that is used in the aggregation. This property is required when aggType is avg, max, min or sum.
-
aggType (optional)
-
excludeHitsFromPreviousRun (optional)
Boolean Indicates whether to exclude matches from previous runs. If true, you can avoid alert duplication by excluding documents that have already been detected by the previous rule run. This option is not available when a grouping field is specified.
-
groupBy (optional)
-
searchConfiguration (optional)
-
searchType
String The type of query, in this case a query that uses Elasticsearch Query DSL.
-
Enum:
-
esQuery
-
size
Integer The number of documents to pass to the configured actions when the threshold condition is met.
-
termField (optional)
String This property is required when groupBy is top. The name of the field that is used for grouping the aggregation.
-
termSize (optional)
Integer This property is required when groupBy is top. It specifies the number of groups to check against the threshold and therefore limits the number of alerts on high cardinality fields.
-
threshold
array[Integer] The threshold value that is used with the thresholdComparator. If the thresholdComparator is between or notBetween, you must specify the boundary values.
-
thresholdComparator
-
timeField
String The field that is used to calculate the time window.
-
timeWindowSize
Integer The size of the time window (in timeWindowUnit units), which determines how far back to search for documents. Generally it should be a value higher than the rule check interval to avoid gaps in detection.
-
timeWindowUnit
-
esQuery
String The query definition, which uses Elasticsearch Query DSL.
-
index
oneOf The indices to query.
-
-
-
-

params_es_query_rule_oneOf - Up

-
The parameters for an Elasticsearch query rule that uses KQL or Lucene to define the query.
-
-
aggField (optional)
String The name of the numeric field that is used in the aggregation. This property is required when aggType is avg, max, min or sum.
-
aggType (optional)
-
excludeHitsFromPreviousRun (optional)
Boolean Indicates whether to exclude matches from previous runs. If true, you can avoid alert duplication by excluding documents that have already been detected by the previous rule run. This option is not available when a grouping field is specified.
-
groupBy (optional)
-
searchConfiguration (optional)
-
searchType
String The type of query, in this case a text-based query that uses KQL or Lucene.
-
Enum:
-
searchSource
-
size
Integer The number of documents to pass to the configured actions when the threshold condition is met.
-
termField (optional)
String This property is required when groupBy is top. The name of the field that is used for grouping the aggregation.
-
termSize (optional)
Integer This property is required when groupBy is top. It specifies the number of groups to check against the threshold and therefore limits the number of alerts on high cardinality fields.
-
threshold
array[Integer] The threshold value that is used with the thresholdComparator. If the thresholdComparator is between or notBetween, you must specify the boundary values.
-
thresholdComparator
-
timeField (optional)
String The field that is used to calculate the time window.
-
timeWindowSize
Integer The size of the time window (in timeWindowUnit units), which determines how far back to search for documents. Generally it should be a value higher than the rule check interval to avoid gaps in detection.
-
timeWindowUnit
-
-
-
-

params_es_query_rule_oneOf_1 - Up

-
The parameters for an Elasticsearch query rule that uses Elasticsearch Query DSL to define the query.
-
-
aggField (optional)
String The name of the numeric field that is used in the aggregation. This property is required when aggType is avg, max, min or sum.
-
aggType (optional)
-
esQuery
String The query definition, which uses Elasticsearch Query DSL.
-
excludeHitsFromPreviousRun (optional)
Boolean Indicates whether to exclude matches from previous runs. If true, you can avoid alert duplication by excluding documents that have already been detected by the previous rule run. This option is not available when a grouping field is specified.
-
groupBy (optional)
-
index
oneOf The indices to query.
-
searchType (optional)
String The type of query, in this case a query that uses Elasticsearch Query DSL.
-
Enum:
-
esQuery
-
size (optional)
Integer The number of documents to pass to the configured actions when the threshold condition is met.
-
termField (optional)
String This property is required when groupBy is top. The name of the field that is used for grouping the aggregation.
-
termSize (optional)
Integer This property is required when groupBy is top. It specifies the number of groups to check against the threshold and therefore limits the number of alerts on high cardinality fields.
-
threshold
array[Integer] The threshold value that is used with the thresholdComparator. If the thresholdComparator is between or notBetween, you must specify the boundary values.
-
thresholdComparator
-
timeField
String The field that is used to calculate the time window.
-
timeWindowSize
Integer The size of the time window (in timeWindowUnit units), which determines how far back to search for documents. Generally it should be a value higher than the rule check interval to avoid gaps in detection.
-
timeWindowUnit
-
-
-
-

params_es_query_rule_oneOf_searchConfiguration - Up

-
The query definition, which uses KQL or Lucene to fetch the documents from Elasticsearch.
-
-
filter (optional)
-
index (optional)
oneOf The indices to query.
-
query (optional)
-
-
-
-

params_es_query_rule_oneOf_searchConfiguration_query - Up

-
-
-
language (optional)
-
query (optional)
-
-
-
-

params_index_threshold_rule - Up

-
The parameters for an index threshold rule.
-
-
aggField (optional)
String The name of the numeric field that is used in the aggregation. This property is required when aggType is avg, max, min or sum.
-
aggType (optional)
-
filterKuery (optional)
String A KQL expression thats limits the scope of alerts.
-
groupBy (optional)
-
index
array[String] The indices to query.
-
termField (optional)
String This property is required when groupBy is top. The name of the field that is used for grouping the aggregation.
-
termSize (optional)
Integer This property is required when groupBy is top. It specifies the number of groups to check against the threshold and therefore limits the number of alerts on high cardinality fields.
-
threshold
array[Integer] The threshold value that is used with the thresholdComparator. If the thresholdComparator is between or notBetween, you must specify the boundary values.
-
thresholdComparator
-
timeField
String The field that is used to calculate the time window.
-
timeWindowSize
Integer The size of the time window (in timeWindowUnit units), which determines how far back to search for documents. Generally it should be a value higher than the rule check interval to avoid gaps in detection.
-
timeWindowUnit
-
-
-
-

params_property_apm_anomaly - Up

-
-
-
serviceName (optional)
String The service name from APM
-
transactionType (optional)
String The transaction type from APM
-
windowSize
BigDecimal The window size
-
windowUnit
String The window size unit
-
Enum:
-
m
h
d
-
environment
String The environment from APM
-
anomalySeverityType
String The anomaly threshold value
-
Enum:
-
critical
major
minor
warning
-
-
-
-

params_property_apm_error_count - Up

-
-
-
serviceName (optional)
String The service name from APM
-
windowSize
BigDecimal The window size
-
windowUnit
String The window size unit
-
Enum:
-
m
h
d
-
environment
String The environment from APM
-
threshold
BigDecimal The error count threshold value
-
groupBy (optional)
-
Enum:
- -
errorGroupingKey (optional)
-
-
-
-

params_property_apm_transaction_duration - Up

-
-
-
serviceName (optional)
String The service name from APM
-
transactionType (optional)
String The transaction type from APM
-
transactionName (optional)
String The transaction name from APM
-
windowSize
BigDecimal The window size
-
windowUnit
String ç
-
Enum:
-
m
h
d
-
environment
-
threshold
BigDecimal The latency threshold value
-
groupBy (optional)
-
Enum:
- -
aggregationType
-
Enum:
-
avg
95th
99th
-
-
-
-

params_property_apm_transaction_error_rate - Up

-
-
-
serviceName (optional)
String The service name from APM
-
transactionType (optional)
String The transaction type from APM
-
transactionName (optional)
String The transaction name from APM
-
windowSize
BigDecimal The window size
-
windowUnit
String The window size unit
-
Enum:
-
m
h
d
-
environment
String The environment from APM
-
threshold
BigDecimal The error rate threshold value
-
groupBy (optional)
-
Enum:
- -
-
-
-

params_property_infra_inventory - Up

-
-
-
criteria (optional)
-
filterQuery (optional)
-
filterQueryText (optional)
-
nodeType (optional)
-
Enum:
-
host
pod
container
awsEC2
awsS3
awsSQS
awsRDS
-
sourceId (optional)
-
alertOnNoData (optional)
-
-
-
-

params_property_infra_inventory_criteria_inner - Up

-
-
-
metric (optional)
-
Enum:
-
count
cpu
diskLatency
load
memory
memoryTotal
tx
rx
logRate
diskIOReadBytes
diskIOWriteBytes
s3TotalRequests
s3NumberOfObjects
s3BucketSize
s3DownloadBytes
s3UploadBytes
rdsConnections
rdsQueriesExecuted
rdsActiveTransactions
rdsLatency
sqsMessagesVisible
sqsMessagesDelayed
sqsMessagesSent
sqsMessagesEmpty
sqsOldestMessage
custom
-
timeSize (optional)
-
timeUnit (optional)
-
Enum:
-
s
m
h
d
-
sourceId (optional)
-
threshold (optional)
-
comparator (optional)
-
Enum:
-
<
<=
>
>=
between
outside
-
customMetric (optional)
-
warningThreshold (optional)
-
warningComparator (optional)
-
Enum:
-
<
<=
>
>=
between
outside
-
-
-
-

params_property_infra_inventory_criteria_inner_customMetric - Up

-
-
-
type (optional)
-
Enum:
-
custom
-
field (optional)
-
aggregation (optional)
-
Enum:
-
avg
max
min
rate
-
id (optional)
-
label (optional)
-
-
-
-

params_property_infra_metric_threshold - Up

-
-
-
criteria (optional)
-
groupBy (optional)
-
filterQuery (optional)
-
sourceId (optional)
-
alertOnNoData (optional)
-
alertOnGroupDisappear (optional)
-
-
-
-

params_property_infra_metric_threshold_criteria_inner - Up

-
-
-
threshold (optional)
-
comparator (optional)
-
Enum:
-
<
<=
>
>=
between
outside
-
timeUnit (optional)
-
timeSize (optional)
-
warningThreshold (optional)
-
warningComparator (optional)
-
Enum:
-
<
<=
>
>=
between
outside
-
metric (optional)
-
aggType (optional)
-
Enum:
-
custom
-
customMetric (optional)
-
equation (optional)
-
label (optional)
-
-
-
-

params_property_log_threshold - Up

-
-
-
criteria (optional)
-
count
-
timeSize
-
timeUnit
-
Enum:
-
s
m
h
d
-
logView
-
groupBy (optional)
-
-
-
-

params_property_slo_burn_rate - Up

-
-
-
sloId (optional)
String The SLO identifier used by the rule
-
burnRateThreshold (optional)
BigDecimal The burn rate threshold used to trigger the alert
-
maxBurnRateThreshold (optional)
BigDecimal The maximum burn rate threshold value defined by the SLO error budget
-
longWindow (optional)
-
shortWindow (optional)
-
-
-
-

params_property_slo_burn_rate_longWindow - Up

-
The duration of the long window used to compute the burn rate
-
-
value (optional)
BigDecimal The duration value
-
unit (optional)
String The duration unit
-
-
-
-

params_property_slo_burn_rate_shortWindow - Up

-
The duration of the short window used to compute the burn rate
-
-
value (optional)
BigDecimal The duration value
-
unit (optional)
String The duration unit
-
-
-
-

params_property_synthetics_monitor_status - Up

-
-
-
availability (optional)
-
filters (optional)
-
locations (optional)
-
numTimes
-
search (optional)
-
shouldCheckStatus
-
shouldCheckAvailability
-
timerangeCount (optional)
-
timerangeUnit (optional)
-
timerange (optional)
-
version (optional)
-
isAutoGenerated (optional)
-
-
-
-

params_property_synthetics_monitor_status_availability - Up

-
-
-
range (optional)
-
rangeUnit (optional)
-
threshold (optional)
-
-
-
-

params_property_synthetics_monitor_status_filters - Up

-
-
-
monitorPeriodtype (optional)
-
observerPeriodgeoPeriodname (optional)
-
tags (optional)
-
urlPeriodport (optional)
-
-
-
-

params_property_synthetics_monitor_status_filters_oneOf - Up

-
-
-
monitorPeriodtype (optional)
-
observerPeriodgeoPeriodname (optional)
-
tags (optional)
-
urlPeriodport (optional)
-
-
- -
-

params_property_synthetics_uptime_tls - Up

-
-
-
search (optional)
-
certExpirationThreshold (optional)
-
certAgeThreshold (optional)
-
-
-
-

rule_response_properties - Rule response properties Up

-
-
-
actions
-
api_key_created_by_user (optional)
Boolean Indicates whether the API key that is associated with the rule was created by the user.
-
api_key_owner
String The owner of the API key that is associated with the rule and used to run background tasks.
-
consumer
String The application or feature that owns the rule. For example, alerts, apm, discover, infrastructure, logs, metrics, ml, monitoring, securitySolution, siem, stackAlerts, or uptime.
-
created_at
Date The date and time that the rule was created. format: date-time
-
created_by
String The identifier for the user that created the rule.
-
enabled
Boolean Indicates whether the rule is currently enabled.
-
execution_status
-
id
String The identifier for the rule.
-
last_run (optional)
-
muted_alert_ids
-
mute_all
-
name
String The name of the rule.
-
next_run (optional)
Date format: date-time
-
notify_when (optional)
String Indicates how often alerts generate actions.
-
params
map[String, oas_any_type_not_mapped] The parameters for the rule.
-
revision (optional)
Integer The rule revision number.
-
rule_type_id
String The identifier for the type of rule. For example, .es-query, .index-threshold, logs.alert.document.count, monitoring_alert_cluster_health, siem.thresholdRule, or xpack.ml.anomaly_detection_alert.
-
running (optional)
Boolean Indicates whether the rule is running.
-
schedule
-
scheduled_task_id (optional)
-
tags
array[String] The tags for the rule.
-
throttle
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
updated_at
String The date and time that the rule was updated most recently.
-
updated_by
String The identifier for the user that updated this rule most recently.
-
-
-
-

rule_response_properties_execution_status - Up

-
-
-
last_duration (optional)
-
last_execution_date (optional)
Date format: date-time
-
status (optional)
-
-
-
-

rule_response_properties_last_run - Up

-
-
-
alerts_count (optional)
-
outcome (optional)
-
outcome_msg (optional)
-
outcome_order (optional)
-
warning (optional)
-
-
-
-

rule_response_properties_last_run_alerts_count - Up

-
-
-
active (optional)
-
ignored (optional)
-
new (optional)
-
recovered (optional)
-
-
-
-

schedule - Up

-
The check interval, which specifies how frequently the rule conditions are checked. The interval is specified in seconds, minutes, hours, or days.
-
-
interval (optional)
-
-
-
-

thresholdcomparator - Up

-
The comparison function for the threshold. For example, "is above", "is above or equals", "is below", "is below or equals", "is between", and "is not between".
-
-
-
-
-

timewindowunit - Up

-
The type of units for the time window: seconds, minutes, hours, or days.
-
-
-
-
-

update_rule_request - Update rule request Up

-
The update rule API request body varies depending on the type of rule and actions.
-
-
actions (optional)
-
name
String The name of the rule.
-
notify_when (optional)
-
params
map[String, oas_any_type_not_mapped] The parameters for the rule.
-
schedule
-
tags (optional)
array[String] The tags for the rule.
-
throttle (optional)
String The throttle interval, which defines how often an alert generates repeated actions. It is specified in seconds, minutes, hours, or days and is applicable only if notify_when is set to onThrottleInterval. NOTE: You cannot specify the throttle interval at both the rule and action level. The recommended method is to set it for each action. If you set it at the rule level then update the rule in Kibana, it is automatically changed to use action-specific values.
-
-
-
-++++ diff --git a/docs/api-generated/rules/rule-apis.asciidoc b/docs/api-generated/rules/rule-apis.asciidoc deleted file mode 100644 index fb963582fb6da4..00000000000000 --- a/docs/api-generated/rules/rule-apis.asciidoc +++ /dev/null @@ -1,10 +0,0 @@ -[[rule-apis]] -== Alert and rule APIs - -preview::[] - -//// -This file includes content that has been generated from https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/docs/openapi. Any modifications required must be done in that open API specification. -//// - -include::rule-apis-passthru.asciidoc[] \ No newline at end of file diff --git a/docs/api-generated/template/index.mustache b/docs/api-generated/template/index.mustache deleted file mode 100644 index 8c1162f9095087..00000000000000 --- a/docs/api-generated/template/index.mustache +++ /dev/null @@ -1,170 +0,0 @@ -//// -This content is generated from the open API specification. -Any modifications made to this file will be overwritten. -//// - -++++ -
-

Access

- {{#hasAuthMethods}} -
    - {{#authMethods}} -
  1. {{#isBasic}}HTTP Basic Authentication{{/isBasic}}{{#isOAuth}}OAuth AuthorizationUrl:{{authorizationUrl}}TokenUrl:{{tokenUrl}}{{/isOAuth}}{{#isApiKey}}APIKey KeyParamName:{{keyParamName}} KeyInQuery:{{isKeyInQuery}} KeyInHeader:{{isKeyInHeader}}{{/isApiKey}}
  2. - {{/authMethods}} -
- {{/hasAuthMethods}} - -

Methods

- [ Jump to Models ] - - {{! for the tables of content, I cheat and don't use CSS styles.... }} -

Table of Contents

-
{{access}}
- {{#apiInfo}} - {{#apis}} - {{#operations}} -

{{baseName}}

- - {{/operations}} - {{/apis}} - {{/apiInfo}} - - {{#apiInfo}} - {{#apis}} - {{#operations}} -

{{baseName}}

- {{#operation}} -
-
- Up -
{{httpMethod}} {{path}}
-
{{summary}} ({{nickname}})
- {{! notes is operation.description. So why rename it and make it super confusing???? }} -
{{notes}}
- - {{#hasPathParams}} -

Path parameters

-
- {{#pathParams}}{{>pathParam}}{{/pathParams}} -
- {{/hasPathParams}} - - {{#hasConsumes}} -

Consumes

- This API call consumes the following media types via the Content-Type request header: -
    - {{#consumes}} -
  • {{{mediaType}}}
  • - {{/consumes}} -
- {{/hasConsumes}} - - {{#hasBodyParam}} -

Request body

-
- {{#bodyParams}}{{>bodyParam}}{{/bodyParams}} -
- {{/hasBodyParam}} - - {{#hasHeaderParams}} -

Request headers

-
- {{#headerParams}}{{>headerParam}}{{/headerParams}} -
- {{/hasHeaderParams}} - - {{#hasQueryParams}} -

Query parameters

-
- {{#queryParams}}{{>queryParam}}{{/queryParams}} -
- {{/hasQueryParams}} - - {{#hasFormParams}} -

Form parameters

-
- {{#formParams}}{{>formParam}}{{/formParams}} -
- {{/hasFormParams}} - - {{#returnType}} -

Return type

-
- {{#hasReference}}{{^returnSimpleType}}{{returnContainer}}[{{/returnSimpleType}}{{returnBaseType}}{{^returnSimpleType}}]{{/returnSimpleType}}{{/hasReference}} - {{^hasReference}}{{returnType}}{{/hasReference}} -
- {{/returnType}} - - - - {{#hasExamples}} - {{#examples}} -

Example data

-
Content-Type: {{{contentType}}}
-
{{{example}}}
- {{/examples}} - {{/hasExamples}} - - {{#hasProduces}} -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    - {{#produces}} -
  • {{{mediaType}}}
  • - {{/produces}} -
- {{/hasProduces}} - -

Responses

- {{#responses}} -

{{code}}

- {{message}} - {{^containerType}}{{dataType}}{{/containerType}} - {{#examples}} -

Example data

-
Content-Type: {{{contentType}}}
-
{{example}}
- {{/examples}} - {{/responses}} -
-
- {{/operation}} - {{/operations}} - {{/apis}} - {{/apiInfo}} - -

Models

- [ Jump to Methods ] - -

Table of Contents

-
    - {{#models}} - {{#model}} -
  1. {{name}}{{#title}} - {{.}}{{/title}}
  2. - {{/model}} - {{/models}} -
- - {{#models}} - {{#model}} -
-

{{name}}{{#title}} - {{.}}{{/title}} Up

- {{#unescapedDescription}}
{{.}}
{{/unescapedDescription}} -
- {{#vars}}
{{name}} {{^required}}(optional){{/required}}
{{^isPrimitiveType}}{{dataType}}{{/isPrimitiveType}} {{unescapedDescription}} {{#dataFormat}}format: {{{.}}}{{/dataFormat}}
- {{#isEnum}} -
Enum:
- {{#_enum}}
{{this}}
{{/_enum}} - {{/isEnum}} - {{/vars}} -
-
- {{/model}} - {{/models}} -
-++++ diff --git a/docs/api/actions-and-connectors/create.asciidoc b/docs/api/actions-and-connectors/create.asciidoc index 259c5dfee00af4..55168ecf796ca1 100644 --- a/docs/api/actions-and-connectors/create.asciidoc +++ b/docs/api/actions-and-connectors/create.asciidoc @@ -9,7 +9,7 @@ Creates a connector. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. ==== [[create-connector-api-request]] diff --git a/docs/api/actions-and-connectors/delete.asciidoc b/docs/api/actions-and-connectors/delete.asciidoc index d908f276b74615..81619cdf26b5cd 100644 --- a/docs/api/actions-and-connectors/delete.asciidoc +++ b/docs/api/actions-and-connectors/delete.asciidoc @@ -11,7 +11,7 @@ WARNING: When you delete a connector, _it cannot be recovered_. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. ==== [discrete] diff --git a/docs/api/actions-and-connectors/execute.asciidoc b/docs/api/actions-and-connectors/execute.asciidoc index 6d94c61f6232bf..1f241202b4adca 100644 --- a/docs/api/actions-and-connectors/execute.asciidoc +++ b/docs/api/actions-and-connectors/execute.asciidoc @@ -9,7 +9,7 @@ Runs a connector by ID. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. ==== [[execute-connector-api-request]] diff --git a/docs/api/actions-and-connectors/get.asciidoc b/docs/api/actions-and-connectors/get.asciidoc index a43787dc2a33e7..92414babd16388 100644 --- a/docs/api/actions-and-connectors/get.asciidoc +++ b/docs/api/actions-and-connectors/get.asciidoc @@ -9,7 +9,7 @@ Retrieves a connector by ID. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. ==== [discrete] diff --git a/docs/api/actions-and-connectors/get_all.asciidoc b/docs/api/actions-and-connectors/get_all.asciidoc index 2b5fbe20bf56ed..ba2cab86b654ff 100644 --- a/docs/api/actions-and-connectors/get_all.asciidoc +++ b/docs/api/actions-and-connectors/get_all.asciidoc @@ -9,7 +9,7 @@ Retrieves all connectors. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. ==== [discrete] diff --git a/docs/api/actions-and-connectors/list.asciidoc b/docs/api/actions-and-connectors/list.asciidoc index d7658cdd11da41..e978f75d36c1f0 100644 --- a/docs/api/actions-and-connectors/list.asciidoc +++ b/docs/api/actions-and-connectors/list.asciidoc @@ -9,7 +9,7 @@ Retrieves a list of all connector types. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. ==== [[list-connector-types-api-request]] diff --git a/docs/api/actions-and-connectors/update.asciidoc b/docs/api/actions-and-connectors/update.asciidoc index b690d3fac995bb..7fe3d85ad0ca72 100644 --- a/docs/api/actions-and-connectors/update.asciidoc +++ b/docs/api/actions-and-connectors/update.asciidoc @@ -9,7 +9,7 @@ Updates the attributes for a connector. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[open API specification]. ==== [[update-connector-api-request]] diff --git a/docs/api/alerting/create_rule.asciidoc b/docs/api/alerting/create_rule.asciidoc index 2bce4a1c491937..faac08b2b613e1 100644 --- a/docs/api/alerting/create_rule.asciidoc +++ b/docs/api/alerting/create_rule.asciidoc @@ -9,7 +9,7 @@ Create {kib} rules. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== [[create-rule-api-request]] diff --git a/docs/api/alerting/delete_rule.asciidoc b/docs/api/alerting/delete_rule.asciidoc index 143507fa206009..220b4dfa9ece4e 100644 --- a/docs/api/alerting/delete_rule.asciidoc +++ b/docs/api/alerting/delete_rule.asciidoc @@ -11,7 +11,7 @@ WARNING: After you delete a rule, you cannot recover it. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== [[delete-rule-api-request]] diff --git a/docs/api/alerting/disable_rule.asciidoc b/docs/api/alerting/disable_rule.asciidoc index d1c41eed9eaf10..8f370072a689ce 100644 --- a/docs/api/alerting/disable_rule.asciidoc +++ b/docs/api/alerting/disable_rule.asciidoc @@ -9,7 +9,7 @@ Disable a rule. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== [[disable-rule-api-request]] diff --git a/docs/api/alerting/enable_rule.asciidoc b/docs/api/alerting/enable_rule.asciidoc index b87c0b9228b1be..f51f6c92953329 100644 --- a/docs/api/alerting/enable_rule.asciidoc +++ b/docs/api/alerting/enable_rule.asciidoc @@ -11,7 +11,7 @@ WARNING: This API supports <> only. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== [[enable-rule-api-request]] diff --git a/docs/api/alerting/find_rules.asciidoc b/docs/api/alerting/find_rules.asciidoc index 0879cc77770aaa..a9a9ee225db7e9 100644 --- a/docs/api/alerting/find_rules.asciidoc +++ b/docs/api/alerting/find_rules.asciidoc @@ -9,7 +9,7 @@ Retrieve a paginated set of rules based on condition. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== [[find-rules-api-request]] diff --git a/docs/api/alerting/get_rules.asciidoc b/docs/api/alerting/get_rules.asciidoc index 60c879116948a3..ff60d5bad52d13 100644 --- a/docs/api/alerting/get_rules.asciidoc +++ b/docs/api/alerting/get_rules.asciidoc @@ -9,7 +9,7 @@ Retrieve a rule by ID. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== [[get-rule-api-request]] diff --git a/docs/api/alerting/health.asciidoc b/docs/api/alerting/health.asciidoc index 2a37abc864878b..cd9d1c9449a829 100644 --- a/docs/api/alerting/health.asciidoc +++ b/docs/api/alerting/health.asciidoc @@ -9,7 +9,7 @@ Retrieve the health status of the alerting framework. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== [[get-alerting-framework-health-api-request]] diff --git a/docs/api/alerting/list_rule_types.asciidoc b/docs/api/alerting/list_rule_types.asciidoc index 32b4be086705a7..7640d50b3ccd05 100644 --- a/docs/api/alerting/list_rule_types.asciidoc +++ b/docs/api/alerting/list_rule_types.asciidoc @@ -9,7 +9,7 @@ Retrieve a list of rule types that the user is authorized to access. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== diff --git a/docs/api/alerting/mute_alert.asciidoc b/docs/api/alerting/mute_alert.asciidoc index 3ac99f0d3dda06..ad6d87848dfeeb 100644 --- a/docs/api/alerting/mute_alert.asciidoc +++ b/docs/api/alerting/mute_alert.asciidoc @@ -9,7 +9,7 @@ Mute an alert. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== [[mute-alert-api-request]] diff --git a/docs/api/alerting/mute_all_alerts.asciidoc b/docs/api/alerting/mute_all_alerts.asciidoc index a3c1fc0084245d..b33d337d473caf 100644 --- a/docs/api/alerting/mute_all_alerts.asciidoc +++ b/docs/api/alerting/mute_all_alerts.asciidoc @@ -9,7 +9,7 @@ Mute all alerts. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== [[mute-all-alerts-api-request]] diff --git a/docs/api/alerting/unmute_alert.asciidoc b/docs/api/alerting/unmute_alert.asciidoc index 8efa95a16edd78..81bb641b259f9b 100644 --- a/docs/api/alerting/unmute_alert.asciidoc +++ b/docs/api/alerting/unmute_alert.asciidoc @@ -9,7 +9,7 @@ Unmute an alert. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== [[unmute-alert-api-request]] diff --git a/docs/api/alerting/unmute_all_alerts.asciidoc b/docs/api/alerting/unmute_all_alerts.asciidoc index a4e2a91847397d..0594727c712686 100644 --- a/docs/api/alerting/unmute_all_alerts.asciidoc +++ b/docs/api/alerting/unmute_all_alerts.asciidoc @@ -9,7 +9,7 @@ Unmute all alerts. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== [[unmute-all-alerts-api-all-request]] diff --git a/docs/api/alerting/update_rule.asciidoc b/docs/api/alerting/update_rule.asciidoc index 11ca1dc35fc855..124adc79582fe0 100644 --- a/docs/api/alerting/update_rule.asciidoc +++ b/docs/api/alerting/update_rule.asciidoc @@ -9,7 +9,7 @@ Update the attributes for an existing rule. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[open API specification]. ==== [[update-rule-api-request]] diff --git a/docs/api/cases/cases-api-add-comment.asciidoc b/docs/api/cases/cases-api-add-comment.asciidoc index 48c3ffb5845b82..28b8959d5a0172 100644 --- a/docs/api/cases/cases-api-add-comment.asciidoc +++ b/docs/api/cases/cases-api-add-comment.asciidoc @@ -9,7 +9,7 @@ Adds a comment or alert to a case. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-create.asciidoc b/docs/api/cases/cases-api-create.asciidoc index f124d3500228c0..2145acd3605329 100644 --- a/docs/api/cases/cases-api-create.asciidoc +++ b/docs/api/cases/cases-api-create.asciidoc @@ -9,7 +9,7 @@ Creates a case. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-delete-cases.asciidoc b/docs/api/cases/cases-api-delete-cases.asciidoc index 013dc9567db2ed..abf518d2120951 100644 --- a/docs/api/cases/cases-api-delete-cases.asciidoc +++ b/docs/api/cases/cases-api-delete-cases.asciidoc @@ -9,7 +9,7 @@ Deletes one or more cases. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-delete-comments.asciidoc b/docs/api/cases/cases-api-delete-comments.asciidoc index 130158bd021c22..dc8fe0e1205741 100644 --- a/docs/api/cases/cases-api-delete-comments.asciidoc +++ b/docs/api/cases/cases-api-delete-comments.asciidoc @@ -9,7 +9,7 @@ Deletes one or all comments and alerts from a case. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-find-case-activity.asciidoc b/docs/api/cases/cases-api-find-case-activity.asciidoc index e59540c654e286..d15e2a8bea9d54 100644 --- a/docs/api/cases/cases-api-find-case-activity.asciidoc +++ b/docs/api/cases/cases-api-find-case-activity.asciidoc @@ -9,7 +9,7 @@ Finds user activity for a case. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-find-cases.asciidoc b/docs/api/cases/cases-api-find-cases.asciidoc index 9d9151b13d7e85..4a791a8ddb9d36 100644 --- a/docs/api/cases/cases-api-find-cases.asciidoc +++ b/docs/api/cases/cases-api-find-cases.asciidoc @@ -9,7 +9,7 @@ Retrieves a paginated subset of cases. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-find-connectors.asciidoc b/docs/api/cases/cases-api-find-connectors.asciidoc index 6968bc55d88bb1..974e3e9a2211b4 100644 --- a/docs/api/cases/cases-api-find-connectors.asciidoc +++ b/docs/api/cases/cases-api-find-connectors.asciidoc @@ -13,7 +13,7 @@ returned. Refer to the list of supported external incident management systems in [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-get-alerts.asciidoc b/docs/api/cases/cases-api-get-alerts.asciidoc index 1b9c1da1bd9265..fea5b5f9a73543 100644 --- a/docs/api/cases/cases-api-get-alerts.asciidoc +++ b/docs/api/cases/cases-api-get-alerts.asciidoc @@ -11,7 +11,7 @@ Gets all alerts attached to a case. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-get-case-activity.asciidoc b/docs/api/cases/cases-api-get-case-activity.asciidoc index db5835709a6ab3..2baa19ebf69858 100644 --- a/docs/api/cases/cases-api-get-case-activity.asciidoc +++ b/docs/api/cases/cases-api-get-case-activity.asciidoc @@ -11,7 +11,7 @@ deprecated::[8.1.0,Use <> instead.] [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-get-case.asciidoc b/docs/api/cases/cases-api-get-case.asciidoc index b5942f04244088..fe2b4c54b85e5d 100644 --- a/docs/api/cases/cases-api-get-case.asciidoc +++ b/docs/api/cases/cases-api-get-case.asciidoc @@ -9,7 +9,7 @@ Returns information about a case. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-get-cases-by-alert.asciidoc b/docs/api/cases/cases-api-get-cases-by-alert.asciidoc index 14b45f9b4b0e7d..47a0c5973830a9 100644 --- a/docs/api/cases/cases-api-get-cases-by-alert.asciidoc +++ b/docs/api/cases/cases-api-get-cases-by-alert.asciidoc @@ -11,7 +11,7 @@ Returns the cases associated with a specific alert. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== diff --git a/docs/api/cases/cases-api-get-comments.asciidoc b/docs/api/cases/cases-api-get-comments.asciidoc index 5f7bb938f588ac..fb0e497f4ebf1f 100644 --- a/docs/api/cases/cases-api-get-comments.asciidoc +++ b/docs/api/cases/cases-api-get-comments.asciidoc @@ -9,7 +9,7 @@ Gets a comment or all comments for a case. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-get-configuration.asciidoc b/docs/api/cases/cases-api-get-configuration.asciidoc index fec5eb8bdedd66..e78eaa634f716a 100644 --- a/docs/api/cases/cases-api-get-configuration.asciidoc +++ b/docs/api/cases/cases-api-get-configuration.asciidoc @@ -10,7 +10,7 @@ default connector for cases. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-get-reporters.asciidoc b/docs/api/cases/cases-api-get-reporters.asciidoc index 9792bc77ae517a..48f373c65986af 100644 --- a/docs/api/cases/cases-api-get-reporters.asciidoc +++ b/docs/api/cases/cases-api-get-reporters.asciidoc @@ -9,7 +9,7 @@ Returns information about the users who opened cases. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== diff --git a/docs/api/cases/cases-api-get-status.asciidoc b/docs/api/cases/cases-api-get-status.asciidoc index a6d64bc4e9585c..ce9205febae5ab 100644 --- a/docs/api/cases/cases-api-get-status.asciidoc +++ b/docs/api/cases/cases-api-get-status.asciidoc @@ -9,7 +9,7 @@ Returns the number of cases that are open, closed, and in progress. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== deprecated::[8.1.0] diff --git a/docs/api/cases/cases-api-get-tags.asciidoc b/docs/api/cases/cases-api-get-tags.asciidoc index e22a2f08cfda54..993c7d88f538a3 100644 --- a/docs/api/cases/cases-api-get-tags.asciidoc +++ b/docs/api/cases/cases-api-get-tags.asciidoc @@ -9,7 +9,7 @@ Aggregates and returns a list of case tags. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-push.asciidoc b/docs/api/cases/cases-api-push.asciidoc index 5f7a0c268ff1c5..e3bf2464d19b7f 100644 --- a/docs/api/cases/cases-api-push.asciidoc +++ b/docs/api/cases/cases-api-push.asciidoc @@ -9,7 +9,7 @@ Pushes a case to an external service. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-set-configuration.asciidoc b/docs/api/cases/cases-api-set-configuration.asciidoc index a32cc555ed0526..6d7e9320672e6c 100644 --- a/docs/api/cases/cases-api-set-configuration.asciidoc +++ b/docs/api/cases/cases-api-set-configuration.asciidoc @@ -10,7 +10,7 @@ default connector for cases. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-update-comment.asciidoc b/docs/api/cases/cases-api-update-comment.asciidoc index 13adb2218029ef..fc8d97e779fd05 100644 --- a/docs/api/cases/cases-api-update-comment.asciidoc +++ b/docs/api/cases/cases-api-update-comment.asciidoc @@ -9,7 +9,7 @@ Updates a comment or alert in a case. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-update-configuration.asciidoc b/docs/api/cases/cases-api-update-configuration.asciidoc index dcfe01ef841798..b30a8f0bb79b2c 100644 --- a/docs/api/cases/cases-api-update-configuration.asciidoc +++ b/docs/api/cases/cases-api-update-configuration.asciidoc @@ -10,7 +10,7 @@ connector for cases. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/cases/cases-api-update.asciidoc b/docs/api/cases/cases-api-update.asciidoc index ca75e34597afc6..46c5ac7763600a 100644 --- a/docs/api/cases/cases-api-update.asciidoc +++ b/docs/api/cases/cases-api-update.asciidoc @@ -9,7 +9,7 @@ Updates one or more cases. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. ==== === {api-request-title} diff --git a/docs/api/machine-learning/sync.asciidoc b/docs/api/machine-learning/sync.asciidoc index af4f797ade1f28..bd65ce56dd5d1c 100644 --- a/docs/api/machine-learning/sync.asciidoc +++ b/docs/api/machine-learning/sync.asciidoc @@ -9,7 +9,7 @@ Synchronizes {kib} saved objects for {ml} jobs and trained models. [NOTE] ==== For the most up-to-date API details, refer to the -{kib-repo}/tree/{branch}/x-pack/plugins/ml/common/openapi[open API specification]. For a preview, check out <>. +{kib-repo}/tree/{branch}/x-pack/plugins/ml/common/openapi[open API specification]. ==== [[machine-learning-api-sync-request]] diff --git a/docs/apis.asciidoc b/docs/apis.asciidoc deleted file mode 100644 index d85d9ce3f35eb6..00000000000000 --- a/docs/apis.asciidoc +++ /dev/null @@ -1,17 +0,0 @@ -[role="exclude",id="apis"] -= APIs - -[partintro] --- - -preview::[] - -These APIs are documented using the OpenAPI specification. The current supported -version of the specification is 3.0. For more information, go to https://openapi-generator.tech/[OpenAPI Generator] - --- - -include::api-generated/cases/case-apis.asciidoc[] -include::api-generated/connectors/connector-apis.asciidoc[] -include::api-generated/machine-learning/ml-apis.asciidoc[] -include::api-generated/rules/rule-apis.asciidoc[] \ No newline at end of file diff --git a/docs/index.asciidoc b/docs/index.asciidoc index d72b97a76af2ab..ac9f1f6a28e5dd 100644 --- a/docs/index.asciidoc +++ b/docs/index.asciidoc @@ -17,7 +17,5 @@ include::CHANGELOG.asciidoc[] include::developer/index.asciidoc[] -include::apis.asciidoc[] - include::redirects.asciidoc[] diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc index eac4ff0c800d8a..be017fbd1c94e9 100644 --- a/docs/redirects.asciidoc +++ b/docs/redirects.asciidoc @@ -426,4 +426,10 @@ This content has moved. Refer to <> [role="exclude",id="gen-ai-action-type"] == Generative AI connector and action -This connector was renamed. Refer to <>. \ No newline at end of file +This connector was renamed. Refer to <>. + +[role="exclude",id="apis"] +== APIs + +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/x-pack/plugins/alerting/docs/openapi[alerting], {kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[cases], {kib-repo}/tree/{branch}/x-pack/plugins/actions/docs/openapi[connectors], and {kib-repo}/tree/{branch}/x-pack/plugins/ml/common/openapi[machine learning] open API specifications. \ No newline at end of file From a304007b08942926a03ea23b8da70e80b9510ce0 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Tue, 17 Oct 2023 09:28:46 -0600 Subject: [PATCH 68/87] [ML] Data Frame Analytics: add test pipeline action for DFA trained models in models list (#168400) ## Summary Related issue: [Testing data frame analysis models UI](https://github.com/elastic/kibana/issues/164440) This PR: - Adds ability to test the DFA model directly by adding the 'Test model' action - Added a link to the simulate pipeline API via 'Learn more' - 'View request body' allows the user to view the request being sent to the simulate pipeline endpoint - Checks if the source index exists and adds a dismissible callout with warning text - Adds a 'reload' option that gets a random sample doc to test - The 'reset' button resets the sample doc to the last used sample doc image image image ### 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) - [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 - [ ] 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)) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../add_inference_pipeline_flyout.tsx | 8 +- .../ml_inference/components/test_pipeline.tsx | 235 ++++++++++++++---- .../components/ml_inference/types.ts | 6 + .../model_management/model_actions.tsx | 20 +- .../model_management/models_list.tsx | 6 + .../test_dfa_models_flyout.tsx | 62 +++++ .../model_management/test_models/index.ts | 2 +- .../model_management/test_models/utils.ts | 10 +- .../model_management/model_list.ts | 18 +- .../services/ml/trained_models_table.ts | 51 +++- 10 files changed, 341 insertions(+), 77 deletions(-) create mode 100644 x-pack/plugins/ml/public/application/model_management/test_dfa_models_flyout.tsx diff --git a/x-pack/plugins/ml/public/application/components/ml_inference/add_inference_pipeline_flyout.tsx b/x-pack/plugins/ml/public/application/components/ml_inference/add_inference_pipeline_flyout.tsx index 592df6079603dc..c1e612e3b08d12 100644 --- a/x-pack/plugins/ml/public/application/components/ml_inference/add_inference_pipeline_flyout.tsx +++ b/x-pack/plugins/ml/public/application/components/ml_inference/add_inference_pipeline_flyout.tsx @@ -33,7 +33,7 @@ import { ReviewAndCreatePipeline } from './components/review_and_create_pipeline import { useMlApiContext } from '../../contexts/kibana'; import { getPipelineConfig } from './get_pipeline_config'; import { validateInferencePipelineConfigurationStep } from './validation'; -import type { MlInferenceState, InferenceModelTypes } from './types'; +import { type MlInferenceState, type InferenceModelTypes, TEST_PIPELINE_MODE } from './types'; import { useFetchPipelines } from './hooks/use_fetch_pipelines'; export interface AddInferencePipelineFlyoutProps { @@ -157,7 +157,11 @@ export const AddInferencePipelineFlyout: FC = ( /> )} {step === ADD_INFERENCE_PIPELINE_STEPS.TEST && ( - + )} {step === ADD_INFERENCE_PIPELINE_STEPS.CREATE && ( = memo(({ state, sourceIndex }) => { +export const TestPipeline: FC = memo(({ state, sourceIndex, mode }) => { const [simulatePipelineResult, setSimulatePipelineResult] = useState< undefined | estypes.IngestSimulateResponse >(); const [simulatePipelineError, setSimulatePipelineError] = useState(); + const [sourceIndexMissingError, setSourceIndexMissingError] = useState(); const [sampleDocsString, setSampleDocsString] = useState(''); + const [lastFetchedSampleDocsString, setLastFetchedSampleDocsString] = useState(''); const [isValid, setIsValid] = useState(true); + const [showCallOut, setShowCallOut] = useState(true); const { esSearch, trainedModels: { trainedModelPipelineSimulate }, } = useMlApiContext(); const { notifications: { toasts }, + services: { + docLinks: { links }, + }, } = useMlKibana(); const isSmallerViewport = useIsWithinMaxBreakpoint('s'); + const accordionId = useMemo(() => htmlIdGenerator()(), []); + const pipelineConfig = useMemo(() => getPipelineConfig(state), [state]); + const requestBody = useMemo(() => { + const body = { pipeline: pipelineConfig, docs: [] }; + if (isValidJson(sampleDocsString)) { + body.docs = JSON.parse(sampleDocsString); + } + return body; + }, [pipelineConfig, sampleDocsString]); const simulatePipeline = async () => { try { - const pipelineConfig = getPipelineConfig(state); const result = await trainedModelPipelineSimulate( pipelineConfig, JSON.parse(sampleDocsString) as IngestSimulateDocument[] @@ -95,36 +124,79 @@ export const TestPipeline: FC = memo(({ state, sourceIndex }) => { setIsValid(valid); }; - const getSampleDocs = useCallback(async () => { - let records: IngestSimulateDocument[] = []; - let resp; + const getDocs = useCallback( + async (body: any) => { + let records: IngestSimulateDocument[] = []; + let resp; + try { + resp = await esSearch(body); - try { - resp = await esSearch({ - index: sourceIndex, - body: { - size: 1, - }, - }); + if (resp && resp.hits.total.value > 0) { + records = resp.hits.hits; + } + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + } + setSampleDocsString(JSON.stringify(records, null, 2)); + setSimulatePipelineResult(undefined); + setLastFetchedSampleDocsString(JSON.stringify(records, null, 2)); + setIsValid(true); + }, + [esSearch] + ); + + const { getSampleDoc, getRandomSampleDoc } = useMemo( + () => ({ + getSampleDoc: async () => { + getDocs({ + index: sourceIndex, + body: { + size: 1, + }, + }); + }, + getRandomSampleDoc: async () => { + getDocs({ + index: sourceIndex, + body: { + size: 1, + query: { + function_score: { + query: { match_all: {} }, + random_score: {}, + }, + }, + }, + }); + }, + }), + [getDocs, sourceIndex] + ); - if (resp && resp.hits.total.value > 0) { - records = resp.hits.hits; + useEffect( + function checkSourceIndexExists() { + async function ensureSourceIndexExists() { + const resp = await checkIndexExists(sourceIndex!); + const indexExists = resp.resp && resp.resp[sourceIndex!] && resp.resp[sourceIndex!].exists; + if (indexExists === false) { + setSourceIndexMissingError(sourceIndexMissingMessage); + } } - } catch (error) { - // eslint-disable-next-line no-console - console.error(error); - } - setSampleDocsString(JSON.stringify(records, null, 2)); - setIsValid(true); - }, [sourceIndex, esSearch]); + if (sourceIndex) { + ensureSourceIndexExists(); + } + }, + [sourceIndex, sourceIndexMissingError] + ); useEffect( function fetchSampleDocsFromSource() { - if (sourceIndex) { - getSampleDocs(); + if (sourceIndex && sourceIndexMissingError === undefined) { + getSampleDoc(); } }, - [sourceIndex, getSampleDocs] + [sourceIndex, getSampleDoc, sourceIndexMissingError] ); return ( @@ -147,27 +219,88 @@ export const TestPipeline: FC = memo(({ state, sourceIndex }) => {

- - {i18n.translate( - 'xpack.ml.trainedModels.content.indices.pipelines.addInferencePipelineModal.steps.test.optionalCallout', - { defaultMessage: 'This is an optional step.' } - )} - -   - {' '} - {state.targetField && ( + {mode === TEST_PIPELINE_MODE.STEP ? ( + <> + + {i18n.translate( + 'xpack.ml.trainedModels.content.indices.pipelines.addInferencePipelineModal.steps.test.optionalCallout', + { defaultMessage: 'This is an optional step.' } + )} + +   + + ) : null} + <> {state.targetField} }} + id="xpack.ml.trainedModels.content.indices.pipelines.addInferencePipelineModal.steps.test.description" + defaultMessage="Run a simulation of the pipeline to confirm it produces the anticipated results. {simulatePipelineDocsLink}" + values={{ + simulatePipelineDocsLink: ( + + Learn more. + + ), + }} /> +
+ + {state.targetField && ( + <> + {state.targetField}, + }} + /> +
+ )} + {sampleDocsString && sourceIndexMissingError === undefined ? ( + + ) : null}

+ + {sourceIndexMissingError && showCallOut ? ( + + { + setShowCallOut(false); + }} + size="s" + title={sourceIndexMissingError} + iconType="warning" + /> + + + ) : null} + {mode === TEST_PIPELINE_MODE.STAND_ALONE ? ( + + + } + > + + {JSON.stringify(requestBody, null, 2)} + + + + ) : null} @@ -202,12 +335,26 @@ export const TestPipeline: FC = memo(({ state, sourceIndex }) => { setSampleDocsString(lastFetchedSampleDocsString)} + disabled={ + sampleDocsString === '' || sampleDocsString === lastFetchedSampleDocsString + } > {i18n.translate( 'xpack.ml.trainedModels.content.indices.pipelines.addInferencePipelineModal.steps.test.resetSampleDocsButton', - { defaultMessage: 'Reset sample docs' } + { defaultMessage: 'Reset' } + )} + + + + + {i18n.translate( + 'xpack.ml.trainedModels.content.indices.pipelines.addInferencePipelineModal.steps.test.reloadSampleDocsButton', + { defaultMessage: 'Reload' } )} @@ -261,8 +408,6 @@ export const TestPipeline: FC = memo(({ state, sourceIndex }) => { /> - - void; onTestAction: (model: ModelItem) => void; onModelsDeleteRequest: (models: ModelItem[]) => void; onModelDeployRequest: (model: ModelItem) => void; @@ -463,13 +465,8 @@ export function useModelActions({ onModelDeployRequest(model); }, available: (item) => { - const isDfaTrainedModel = - item.metadata?.analytics_config !== undefined || - item.inference_config?.regression !== undefined || - item.inference_config?.classification !== undefined; - return ( - isDfaTrainedModel && + isDfaTrainedModel(item) && !isBuiltInModel(item) && !item.putModelConfig && canManageIngestPipelines @@ -540,7 +537,13 @@ export function useModelActions({ type: 'icon', isPrimary: true, available: isTestable, - onClick: (item) => onTestAction(item), + onClick: (item) => { + if (isDfaTrainedModel(item) && !isBuiltInModel(item)) { + onDfaTestAction(item); + } else { + onTestAction(item); + } + }, enabled: (item) => { return canTestTrainedModels && isTestable(item, true) && !isLoading; }, @@ -599,6 +602,7 @@ export function useModelActions({ canDeleteTrainedModels, isBuiltInModel, onTestAction, + onDfaTestAction, canTestTrainedModels, canManageIngestPipelines, ] diff --git a/x-pack/plugins/ml/public/application/model_management/models_list.tsx b/x-pack/plugins/ml/public/application/model_management/models_list.tsx index af9b9ba3015e73..56486d1bbbd4f8 100644 --- a/x-pack/plugins/ml/public/application/model_management/models_list.tsx +++ b/x-pack/plugins/ml/public/application/model_management/models_list.tsx @@ -69,6 +69,7 @@ import { useFieldFormatter } from '../contexts/kibana/use_field_formatter'; import { useRefresh } from '../routing/use_refresh'; import { SavedObjectsWarning } from '../components/saved_objects_warning'; import { TestTrainedModelFlyout } from './test_models'; +import { TestDfaModelsFlyout } from './test_dfa_models_flyout'; import { AddInferencePipelineFlyout } from '../components/ml_inference'; import { useEnabledFeatures } from '../contexts/ml'; @@ -163,6 +164,7 @@ export const ModelsList: FC = ({ {} ); const [modelToTest, setModelToTest] = useState(null); + const [dfaModelToTest, setDfaModelToTest] = useState(null); const isBuiltInModel = useCallback( (item: ModelItem) => item.tags.includes(BUILT_IN_MODEL_TAG), @@ -410,6 +412,7 @@ export const ModelsList: FC = ({ isLoading, fetchModels: fetchModelsData, onTestAction: setModelToTest, + onDfaTestAction: setDfaModelToTest, onModelsDeleteRequest: setModelsToDelete, onModelDeployRequest: setModelToDeploy, onLoading: setIsLoading, @@ -763,6 +766,9 @@ export const ModelsList: FC = ({ {modelToTest === null ? null : ( )} + {dfaModelToTest === null ? null : ( + + )} {modelToDeploy !== undefined ? ( void; +} + +export const TestDfaModelsFlyout: FC = ({ model, onClose }) => { + const sourceIndex = useMemo( + () => + Array.isArray(model.metadata?.analytics_config.source.index) + ? model.metadata?.analytics_config.source.index.join() + : model.metadata?.analytics_config.source.index, + // eslint-disable-next-line react-hooks/exhaustive-deps + [model?.model_id] + ); + + const state = useMemo( + () => getInitialState(model), + // eslint-disable-next-line react-hooks/exhaustive-deps + [model?.model_id] + ); + return ( + + + +

+ +

+
+ + +

{model.model_id}

+
+
+ + + +
+ ); +}; diff --git a/x-pack/plugins/ml/public/application/model_management/test_models/index.ts b/x-pack/plugins/ml/public/application/model_management/test_models/index.ts index da7c12c1c0c584..25078a40d42063 100644 --- a/x-pack/plugins/ml/public/application/model_management/test_models/index.ts +++ b/x-pack/plugins/ml/public/application/model_management/test_models/index.ts @@ -6,4 +6,4 @@ */ export { TestTrainedModelFlyout } from './test_flyout'; -export { isTestable } from './utils'; +export { isTestable, isDfaTrainedModel } from './utils'; diff --git a/x-pack/plugins/ml/public/application/model_management/test_models/utils.ts b/x-pack/plugins/ml/public/application/model_management/test_models/utils.ts index 3adecb767f2802..f21d535fddc587 100644 --- a/x-pack/plugins/ml/public/application/model_management/test_models/utils.ts +++ b/x-pack/plugins/ml/public/application/model_management/test_models/utils.ts @@ -15,6 +15,14 @@ import type { ModelItem } from '../models_list'; const PYTORCH_TYPES = Object.values(SUPPORTED_PYTORCH_TASKS); +export function isDfaTrainedModel(modelItem: ModelItem) { + return ( + modelItem.metadata?.analytics_config !== undefined || + modelItem.inference_config?.regression !== undefined || + modelItem.inference_config?.classification !== undefined + ); +} + export function isTestable(modelItem: ModelItem, checkForState = false) { if ( modelItem.model_type === TRAINED_MODEL_TYPE.PYTORCH && @@ -31,5 +39,5 @@ export function isTestable(modelItem: ModelItem, checkForState = false) { return true; } - return false; + return isDfaTrainedModel(modelItem); } diff --git a/x-pack/test/functional/apps/ml/short_tests/model_management/model_list.ts b/x-pack/test/functional/apps/ml/short_tests/model_management/model_list.ts index 7d3cf599558f4c..5a50a34b4ee17d 100644 --- a/x-pack/test/functional/apps/ml/short_tests/model_management/model_list.ts +++ b/x-pack/test/functional/apps/ml/short_tests/model_management/model_list.ts @@ -192,21 +192,19 @@ export default function ({ getService }: FtrProviderContext) { await ml.testExecution.logTestStep('should display the trained model in the table'); await ml.trainedModelsTable.filterWithSearchString(modelWithoutPipelineData.modelId, 1); await ml.testExecution.logTestStep( - 'should not show collapsed actions menu for the model in the table' + 'should show collapsed actions menu for the model in the table' ); await ml.trainedModelsTable.assertModelCollapsedActionsButtonExists( modelWithoutPipelineData.modelId, - false + true ); await ml.testExecution.logTestStep('should show deploy action for the model in the table'); - await ml.trainedModelsTable.assertModelDeployActionButtonExists( + await ml.trainedModelsTable.assertModelDeployActionButtonEnabled( modelWithoutPipelineData.modelId, true ); await ml.testExecution.logTestStep('should open the deploy model flyout'); - await ml.trainedModelsTable.openTrainedModelsInferenceFlyout( - modelWithoutPipelineData.modelId - ); + await ml.trainedModelsTable.clickDeployAction(modelWithoutPipelineData.modelId); await ml.testExecution.logTestStep('should complete the deploy model Details step'); await ml.deployDFAModelFlyout.completeTrainedModelsInferenceFlyoutDetails({ name: modelWithoutPipelineDataExpectedValues.name, @@ -251,17 +249,15 @@ export default function ({ getService }: FtrProviderContext) { ); await ml.trainedModelsTable.assertModelCollapsedActionsButtonExists( modelWithoutPipelineData.modelId, - false + true ); await ml.testExecution.logTestStep('should show deploy action for the model in the table'); await ml.trainedModelsTable.assertModelDeployActionButtonExists( modelWithoutPipelineData.modelId, - true + false ); await ml.testExecution.logTestStep('should open the deploy model flyout'); - await ml.trainedModelsTable.openTrainedModelsInferenceFlyout( - modelWithoutPipelineData.modelId - ); + await ml.trainedModelsTable.clickDeployAction(modelWithoutPipelineData.modelId); await ml.testExecution.logTestStep('should complete the deploy model Details step'); await ml.deployDFAModelFlyout.completeTrainedModelsInferenceFlyoutDetails( { diff --git a/x-pack/test/functional/services/ml/trained_models_table.ts b/x-pack/test/functional/services/ml/trained_models_table.ts index 878d1a0d8d1d1f..1053d8a990e445 100644 --- a/x-pack/test/functional/services/ml/trained_models_table.ts +++ b/x-pack/test/functional/services/ml/trained_models_table.ts @@ -319,15 +319,6 @@ export function TrainedModelsTableProvider( await trainedModelsActions.testModelOutput(modelType, inputParams, expectedResult); } - public async openTrainedModelsInferenceFlyout(modelId: string) { - await mlCommonUI.invokeTableRowAction( - this.rowSelector(modelId), - 'mlModelsTableRowDeployAction', - false - ); - await this.assertDeployModelFlyoutExists(); - } - public async deleteModel(modelId: string) { const fromContextMenu = await this.doesModelCollapsedActionsButtonExist(modelId); await mlCommonUI.invokeTableRowAction( @@ -341,6 +332,33 @@ export function TrainedModelsTableProvider( await this.assertModelDisplayedInTable(modelId, false); } + public async assertModelDeployActionButtonEnabled(modelId: string, expectedValue: boolean) { + const actionsButtonExists = await this.doesModelCollapsedActionsButtonExist(modelId); + + let isEnabled = null; + + if (actionsButtonExists) { + await this.toggleActionsContextMenu(modelId, true); + const panelElement = await find.byCssSelector('.euiContextMenuPanel'); + const actionButton = await panelElement.findByTestSubject('mlModelsTableRowDeployAction'); + isEnabled = await actionButton.isEnabled(); + // escape popover + await browser.pressKeys(browser.keys.ESCAPE); + } else { + await this.assertModelDeployActionButtonExists(modelId, true); + isEnabled = await testSubjects.isEnabled( + this.rowSelector(modelId, 'mlModelsTableRowDeployAction') + ); + } + + expect(isEnabled).to.eql( + expectedValue, + `Expected row deploy action button for trained model '${modelId}' to be '${ + expectedValue ? 'enabled' : 'disabled' + }' (got '${isEnabled ? 'enabled' : 'disabled'}')` + ); + } + public async assertModelDeleteActionButtonEnabled(modelId: string, expectedValue: boolean) { const actionsButtonExists = await this.doesModelCollapsedActionsButtonExist(modelId); @@ -458,6 +476,21 @@ export function TrainedModelsTableProvider( await this.assertDeleteModalExists(); } + public async clickDeployAction(modelId: string) { + const actionsButtonExists = await this.doesModelCollapsedActionsButtonExist(modelId); + + if (actionsButtonExists) { + await this.toggleActionsContextMenu(modelId, true); + const panelElement = await find.byCssSelector('.euiContextMenuPanel'); + const actionButton = await panelElement.findByTestSubject('mlModelsTableRowDeployAction'); + await actionButton.click(); + } else { + await testSubjects.click(this.rowSelector(modelId, 'mlModelsTableRowDeployAction')); + } + + await this.assertDeployModelFlyoutExists(); + } + async assertNumOfAllocations(expectedValue: number) { const actualValue = await testSubjects.getAttribute( 'mlModelsStartDeploymentModalNumOfAllocations', From 916ecf6d751748a777616998b94f99efcf7d0932 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 17 Oct 2023 17:30:47 +0200 Subject: [PATCH 69/87] [docs] add info on how to generate custom Node.js builds (#168919) Co-authored-by: amyjtechwriter <61687663+amyjtechwriter@users.noreply.github.com> --- .../advanced/upgrading-nodejs.asciidoc | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/developer/advanced/upgrading-nodejs.asciidoc b/docs/developer/advanced/upgrading-nodejs.asciidoc index 547ef0080cee8c..1126a0631265e3 100644 --- a/docs/developer/advanced/upgrading-nodejs.asciidoc +++ b/docs/developer/advanced/upgrading-nodejs.asciidoc @@ -4,6 +4,12 @@ {kib} requires a specific Node.js version to run. When running {kib} from source, you must have this version installed locally. +=== Step 1: Generate custom Node.js builds + +Before making a PR to upgrade Node.js, we must first <> matching the desired Node.js version. + +=== Step 2: Create PR to upgrade Node.js + The required version of Node.js is listed in several different files throughout the {kib} source code. These files must be updated when upgrading Node.js: @@ -16,8 +22,8 @@ These files must be updated when upgrading Node.js: - {kib-repo}blob/{branch}/package.json[`package.json`] - The version is specified in the `engines.node` field (if possible, also upgrade `@types/node` to match the new version, both under `devDependencies` and `resolutions`). - {kib-repo}blob/{branch}/WORKSPACE.bazel[`WORKSPACE.bazel`] - The version is specified in the `node_version` property. Besides this property, the list of files under `node_repositories` must be updated along with their respective SHA256 hashes. - These can be found on the https://nodejs.org[nodejs.org] website. - Example for Node.js v18.18.2: https://nodejs.org/dist/v18.18.2/SHASUMS256.txt.asc + These can be found in the `SHASUMS256.txt` file inside the public `kibana-custom-node-artifacts` GCP bucket. + Example for Node.js v18.18.2: https://storage.googleapis.com/kibana-custom-node-artifacts/node-glibc-217/dist/v18.18.2/SHASUMS256.txt[kibana-custom-node-artifacts/node-glibc-217/dist/v18.18.2/SHASUMS256.txt] See PR {kib-repo}pull/128123[#128123] for an example of how the Node.js version has been upgraded previously. @@ -37,6 +43,13 @@ Due to Node.js 16 coming to an https://nodejs.org/en/blog/announcements/nodejs16 To keep support for these older platforms, we're bundling the Linux distributable of {kib} with a https://github.com/elastic/kibana-custom-nodejs-builds[custom build of Node.js] with extended backwards compatibility. The only difference between the offical Node.js build and our custom build, is the version of `glibc` that it's compiled against. +[[start-new-nodejs-build]] +==== How to start a new build + +To generate a new custom Node.js build, https://buildkite.com/elastic/kibana-custom-node-dot-js-builds#new[start a new build] on our dedicated Buildkite pipeline (requires Elastic employee permissions). +Give it a clear name (e.g. `Node 18.18.2`) and remember so set the custom `OVERRIDE_TARGET_VERSION` environment variable to the desired Node.js version - e.g. `OVERRIDE_TARGET_VERSION=18.18.2`. +You find the "Environment Variables" field by expanding "Options >" in the "New Build" dialog. + === Backporting The following rules are not set in stone. From 6df50ea66679478288ec67150c9ed5aab8b8e637 Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Tue, 17 Oct 2023 09:40:49 -0600 Subject: [PATCH 70/87] Remove mention of config SO types from SO.create API docs. (#168538) --- docs/api/saved-objects/bulk_create.asciidoc | 2 +- docs/api/saved-objects/create.asciidoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/saved-objects/bulk_create.asciidoc b/docs/api/saved-objects/bulk_create.asciidoc index 73feb14acf483d..1e56735fa52a24 100644 --- a/docs/api/saved-objects/bulk_create.asciidoc +++ b/docs/api/saved-objects/bulk_create.asciidoc @@ -38,7 +38,7 @@ For the most up-to-date API details, refer to the ==== Request body `type`:: - (Required, string) Valid options include `visualization`, `dashboard`, `search`, `index-pattern`, `config`. + (Required, string) Valid options include `visualization`, `dashboard`, `search`, `index-pattern`. `id`:: (Optional, string) Specifies an ID instead of using a randomly generated ID. diff --git a/docs/api/saved-objects/create.asciidoc b/docs/api/saved-objects/create.asciidoc index 7e26a329fb54dc..154a58bb720255 100644 --- a/docs/api/saved-objects/create.asciidoc +++ b/docs/api/saved-objects/create.asciidoc @@ -32,7 +32,7 @@ For the most up-to-date API details, refer to the (Optional, string) An identifier for the space. If `space_id` is not provided in the URL, the default space is used. ``:: - (Required, string) Valid options include `visualization`, `dashboard`, `search`, `index-pattern`, `config`. + (Required, string) Valid options include `visualization`, `dashboard`, `search`, `index-pattern`. ``:: (Optional, string) Specifies an ID instead of using a randomly generated ID. From ae2680a4d86d45290a53988047d6b91ce8a5f34c Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Tue, 17 Oct 2023 16:55:27 +0100 Subject: [PATCH 71/87] chore(NA): update versions after v8.10.5 bump (#169110) This PR is a simple update of our versions file after the recent bumps. --- versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions.json b/versions.json index 624287e4144442..b6ac52d0272cef 100644 --- a/versions.json +++ b/versions.json @@ -14,7 +14,7 @@ "previousMinor": true }, { - "version": "8.10.4", + "version": "8.10.5", "branch": "8.10", "currentMajor": true, "previousMinor": true From 7914414cab048feec305d91f59cab12b7ee76ed6 Mon Sep 17 00:00:00 2001 From: Ramon Butter Date: Tue, 17 Oct 2023 18:35:23 +0200 Subject: [PATCH 72/87] Improve the production quality gate definitions (#169103) Slice QGs specification are further defined in the environment scoped QG pipeline file. --- .../pipeline.tests-production-canary.yaml | 25 ------------------- .../pipeline.tests-production-noncanary.yaml | 22 ---------------- .../pipeline.tests-production.yaml | 9 ++++--- 3 files changed, 5 insertions(+), 51 deletions(-) delete mode 100644 .buildkite/pipelines/quality-gates/pipeline.tests-production-canary.yaml delete mode 100644 .buildkite/pipelines/quality-gates/pipeline.tests-production-noncanary.yaml diff --git a/.buildkite/pipelines/quality-gates/pipeline.tests-production-canary.yaml b/.buildkite/pipelines/quality-gates/pipeline.tests-production-canary.yaml deleted file mode 100644 index 8b30d4e141b082..00000000000000 --- a/.buildkite/pipelines/quality-gates/pipeline.tests-production-canary.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# These pipeline steps constitute the quality gate for your service within the production-canary environment. -# Incorporate any necessary additional logic to validate the service's integrity. -# A failure in this pipeline build will prevent further progression to the subsequent stage. - -steps: - - label: ":pipeline::kibana::seedling: Trigger SLO check" - trigger: "serverless-quality-gates" # https://buildkite.com/elastic/serverless-quality-gates - build: - message: "${BUILDKITE_MESSAGE} (triggered by pipeline.tests-production-canary.yaml)" - env: - TARGET_ENV: production-canary - CHECK_SLO: true - CHECK_SLO_TAG: kibana - soft_fail: true - - - label: ":pipeline::rocket::seedling: Trigger control-plane e2e tests" - trigger: "ess-k8s-production-e2e-tests" # https://buildkite.com/elastic/ess-k8s-production-e2e-tests - build: - env: - REGION_ID: aws-us-east-1 - NAME_PREFIX: ci_test_kibana-promotion_ - message: "${BUILDKITE_MESSAGE} (triggered by pipeline.tests-production-canary.yaml)" - - - label: ":cookie: 24h bake time before continuing promotion" - command: "sleep 86400" diff --git a/.buildkite/pipelines/quality-gates/pipeline.tests-production-noncanary.yaml b/.buildkite/pipelines/quality-gates/pipeline.tests-production-noncanary.yaml deleted file mode 100644 index 13c974a344f986..00000000000000 --- a/.buildkite/pipelines/quality-gates/pipeline.tests-production-noncanary.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# These pipeline steps constitute the quality gate for your service within the production-noncanary environment. -# Incorporate any necessary additional logic to validate the service's integrity. -# A failure in this pipeline build will prevent further progression to the subsequent stage. - -steps: - - label: ":pipeline::kibana::seedling: Trigger SLO check" - trigger: "serverless-quality-gates" # https://buildkite.com/elastic/serverless-quality-gates - build: - message: "${BUILDKITE_MESSAGE} (triggered by pipeline.tests-production-noncanary.yaml)" - env: - TARGET_ENV: production-noncanary - CHECK_SLO: true - CHECK_SLO_TAG: kibana - soft_fail: true - - - label: ":pipeline::rocket::seedling: Trigger control-plane e2e tests" - trigger: "ess-k8s-production-e2e-tests" # https://buildkite.com/elastic/ess-k8s-production-e2e-tests - build: - env: - REGION_ID: aws-us-east-1 - NAME_PREFIX: ci_test_kibana-promotion_ - message: "${BUILDKITE_MESSAGE} (triggered by pipeline.tests-production-noncanary.yaml)" diff --git a/.buildkite/pipelines/quality-gates/pipeline.tests-production.yaml b/.buildkite/pipelines/quality-gates/pipeline.tests-production.yaml index 4b0bb30d3084c3..fd2fbac8a7b30e 100644 --- a/.buildkite/pipelines/quality-gates/pipeline.tests-production.yaml +++ b/.buildkite/pipelines/quality-gates/pipeline.tests-production.yaml @@ -2,10 +2,6 @@ # Incorporate any necessary additional logic to validate the service's integrity. # A failure in this pipeline build will prevent further progression to the subsequent stage. -# DEPRECATION NOTICE: -# PRODUCTION WILL SOON BE SPLIT INTO "CANARY" AND "NONCANARY" AND THIS FILE WILL BE DELETED. -# ENSURE ANY CHANGE MADE TO THIS FILE IS REFLECTED IN THOSE FILES AS WELL. - steps: - label: ":pipeline::kibana::seedling: Trigger SLO check" trigger: "serverless-quality-gates" # https://buildkite.com/elastic/serverless-quality-gates @@ -18,9 +14,14 @@ steps: soft_fail: true - label: ":pipeline::rocket::seedling: Trigger control-plane e2e tests" + if: build.env("ENVIRONMENT") == "production-canary" trigger: "ess-k8s-production-e2e-tests" # https://buildkite.com/elastic/ess-k8s-production-e2e-tests build: env: REGION_ID: aws-us-east-1 NAME_PREFIX: ci_test_kibana-promotion_ message: "${BUILDKITE_MESSAGE} (triggered by pipeline.tests-production.yaml)" + + - label: ":cookie: 24h bake time before continuing promotion" + if: build.env("ENVIRONMENT") == "production-canary" + command: "sleep 86400" From ad58290101a2cb7085a15632928aa1921ac26521 Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Tue, 17 Oct 2023 18:45:30 +0200 Subject: [PATCH 73/87] [Security Solutions] Fix entity analytics dashboard error that appear during cypress tests (#168709) ## Summary Fix Entity analytics dashboard error that popped up during Cypress tests. Solutions: I added the same check we have for the risk score fetch to the risk score KPI fetch. It prevents the UI from fetching the KPI when the index doesn't exist. ### 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 --- .../metrics/metric_with_sparkline.tsx | 7 ++- .../containers/risk_score/kpi/index.tsx | 43 ++++++++++++++++--- .../explore/dashboards/entity_analytics.cy.ts | 8 ++-- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/overview/components/sections/metrics/metric_with_sparkline.tsx b/x-pack/plugins/observability/public/pages/overview/components/sections/metrics/metric_with_sparkline.tsx index 56e518e835c43b..bbd3b9acd224cf 100644 --- a/x-pack/plugins/observability/public/pages/overview/components/sections/metrics/metric_with_sparkline.tsx +++ b/x-pack/plugins/observability/public/pages/overview/components/sections/metrics/metric_with_sparkline.tsx @@ -8,6 +8,7 @@ import { Chart, Settings, AreaSeries, TooltipType, Tooltip } from '@elastic/charts'; import { EuiFlexItem, EuiFlexGroup, EuiIcon, EuiTextColor } from '@elastic/eui'; import React, { useContext } from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; import { EUI_CHARTS_THEME_DARK, EUI_CHARTS_THEME_LIGHT, @@ -39,7 +40,11 @@ export function MetricWithSparkline({ id, formatter, value, timeseries, color }: return ( -  N/A +   + ); } diff --git a/x-pack/plugins/security_solution/public/explore/containers/risk_score/kpi/index.tsx b/x-pack/plugins/security_solution/public/explore/containers/risk_score/kpi/index.tsx index 36e0a5a44190fd..2d8712556ae242 100644 --- a/x-pack/plugins/security_solution/public/explore/containers/risk_score/kpi/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/containers/risk_score/kpi/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { useEffect, useMemo } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import { getHostRiskIndex, @@ -20,12 +20,12 @@ import { isIndexNotFoundError } from '../../../../common/utils/exceptions'; import type { ESQuery } from '../../../../../common/typed_json'; import type { SeverityCount } from '../../../components/risk_score/severity/types'; import { useSpaceId } from '../../../../common/hooks/use_space_id'; -import { useMlCapabilities } from '../../../../common/components/ml/hooks/use_ml_capabilities'; import { useSearchStrategy } from '../../../../common/containers/use_search_strategy'; import type { InspectResponse } from '../../../../types'; import type { inputsModel } from '../../../../common/store'; import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; import { useIsNewRiskScoreModuleInstalled } from '../../../../entity_analytics/api/hooks/use_risk_engine_status'; +import { useRiskScoreFeatureStatus } from '../feature_status'; interface RiskScoreKpi { error: unknown; @@ -52,7 +52,6 @@ export const useRiskScoreKpi = ({ }: UseRiskScoreKpiProps): RiskScoreKpi => { const { addError } = useAppToasts(); const spaceId = useSpaceId(); - const featureEnabled = useMlCapabilities().isPlatinumOrTrialLicense; const isNewRiskScoreModuleInstalled = useIsNewRiskScoreModuleInstalled(); const defaultIndex = spaceId ? riskEntity === RiskScoreEntity.host @@ -60,6 +59,14 @@ export const useRiskScoreKpi = ({ : getUserRiskIndex(spaceId, true, isNewRiskScoreModuleInstalled) : undefined; + const { + isDeprecated, + isEnabled, + isAuthorized, + isLoading: isDeprecatedLoading, + refetch: refetchDeprecated, + } = useRiskScoreFeatureStatus(riskEntity, defaultIndex); + const { loading, result, search, refetch, inspect, error } = useSearchStrategy({ factoryQueryType: RiskQueries.kpiRiskScore, @@ -73,18 +80,42 @@ export const useRiskScoreKpi = ({ const isModuleDisabled = !!error && isIndexNotFoundError(error); useEffect(() => { - if (!skip && defaultIndex && featureEnabled) { + if ( + !skip && + defaultIndex && + !isDeprecatedLoading && + isAuthorized && + isEnabled && + !isDeprecated + ) { search({ filterQuery, defaultIndex: [defaultIndex], entity: riskEntity, }); } - }, [defaultIndex, search, filterQuery, skip, riskEntity, featureEnabled]); + }, [ + isEnabled, + isDeprecated, + isAuthorized, + isDeprecatedLoading, + skip, + defaultIndex, + search, + filterQuery, + riskEntity, + ]); + + const refetchAll = useCallback(() => { + if (defaultIndex) { + refetchDeprecated(defaultIndex); + refetch(); + } + }, [defaultIndex, refetch, refetchDeprecated]); // since query does not take timerange arg, we need to manually refetch when time range updates useEffect(() => { - refetch(); + refetchAll(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [timerange?.to, timerange?.from]); 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 3ec2943223a817..3cc088f53d3013 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 @@ -69,7 +69,7 @@ describe('Entity Analytics Dashboard', { tags: ['@ess', '@serverless'] }, () => deleteRiskEngineConfiguration(); }); - describe('legcay risk score', () => { + describe('legacy risk score', () => { describe('Without data', () => { beforeEach(() => { login(); @@ -135,8 +135,7 @@ describe('Entity Analytics Dashboard', { tags: ['@ess', '@serverless'] }, () => }); }); - // FLAKY: https://github.com/elastic/kibana/issues/168490 - describe.skip('With host risk data', () => { + describe('With host risk data', () => { before(() => { cy.task('esArchiverLoad', { archiveName: 'risk_hosts' }); }); @@ -163,7 +162,8 @@ describe('Entity Analytics Dashboard', { tags: ['@ess', '@serverless'] }, () => cy.get(HOSTS_TABLE_ALERT_CELL).should('have.length', 5); }); - it('filters by risk level', () => { + // FLAKY: https://github.com/elastic/kibana/issues/168490 + it.skip('filters by risk level', () => { openRiskTableFilterAndSelectTheLowOption(); cy.get(HOSTS_DONUT_CHART).should('include.text', '1Total'); From f05d976c9d01d5a169c4c77ca61a0b5765923133 Mon Sep 17 00:00:00 2001 From: "Devin W. Hurley" Date: Tue, 17 Oct 2023 12:55:28 -0400 Subject: [PATCH 74/87] resets operator_users file to match production + risk score index. (#169102) --- .../src/serverless_resources/operator_users.yml | 16 +--------------- .../kbn-es/src/serverless_resources/roles.yml | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/packages/kbn-es/src/serverless_resources/operator_users.yml b/packages/kbn-es/src/serverless_resources/operator_users.yml index 7e8e7163e6a849..769d52c25f65a5 100644 --- a/packages/kbn-es/src/serverless_resources/operator_users.yml +++ b/packages/kbn-es/src/serverless_resources/operator_users.yml @@ -1,19 +1,5 @@ operator: - - usernames: - [ - 'elastic_serverless', - 'system_indices_superuser', - 't1_analyst', - 't2_analyst', - 't3_analyst', - 'threat_intelligence_analyst', - 'rule_author', - 'soc_manager', - 'detections_admin', - 'platform_engineer', - 'endpoint_operations_analyst', - 'endpoint_policy_manager', - ] + - usernames: ['elastic_serverless', 'system_indices_superuser'] realm_type: 'file' auth_type: 'realm' - usernames: ['elastic/kibana'] diff --git a/packages/kbn-es/src/serverless_resources/roles.yml b/packages/kbn-es/src/serverless_resources/roles.yml index c631f596a8caca..5777f282ff7a46 100644 --- a/packages/kbn-es/src/serverless_resources/roles.yml +++ b/packages/kbn-es/src/serverless_resources/roles.yml @@ -117,6 +117,7 @@ t1_analyst: - metrics-endpoint.metadata_current_* - ".fleet-agents*" - ".fleet-actions*" + - "risk-score.risk-score-*" privileges: - read applications: @@ -157,6 +158,7 @@ t2_analyst: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* + - "risk-score.risk-score-*" privileges: - read applications: @@ -204,6 +206,7 @@ t3_analyst: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* + - "risk-score.risk-score-*" privileges: - read applications: @@ -256,6 +259,7 @@ threat_intelligence_analyst: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* + - "risk-score.risk-score-*" privileges: - read applications: @@ -307,6 +311,7 @@ rule_author: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* + - "risk-score.risk-score-*" privileges: - read applications: @@ -363,6 +368,7 @@ soc_manager: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* + - risk-score.risk-score-* privileges: - read applications: @@ -391,7 +397,7 @@ soc_manager: resources: "*" detections_admin: - cluster: + cluster: ["manage_index_templates", "manage_transform"] indices: - names: - apm-*-transaction* @@ -418,6 +424,10 @@ detections_admin: - .fleet-actions* privileges: - read + - names: + - risk-score.risk-score-* + privileges: + - all applications: - application: "kibana-.kibana" privileges: @@ -450,6 +460,7 @@ platform_engineer: - .siem-signals-* - .preview.alerts-security* - .internal.preview.alerts-security* + - risk-score.risk-score-* privileges: - all applications: @@ -482,6 +493,7 @@ endpoint_operations_analyst: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* + - risk-score.risk-score-* privileges: - read - names: @@ -537,6 +549,7 @@ endpoint_policy_manager: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* + - risk-score.risk-score-* privileges: - read - names: From 26421473f6c7594663180a23cc9cf3a8945d8d8d Mon Sep 17 00:00:00 2001 From: Jedr Blaszyk Date: Tue, 17 Oct 2023 18:07:55 +0100 Subject: [PATCH 75/87] [Enterprise Search][Connectors] Update extraction service UI restrictions of native connectors (#169104) --- packages/kbn-search-connectors/types/native_connectors.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kbn-search-connectors/types/native_connectors.ts b/packages/kbn-search-connectors/types/native_connectors.ts index 69a2d641844658..399ce74892de53 100644 --- a/packages/kbn-search-connectors/types/native_connectors.ts +++ b/packages/kbn-search-connectors/types/native_connectors.ts @@ -743,7 +743,7 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record Date: Tue, 17 Oct 2023 19:14:45 +0200 Subject: [PATCH 76/87] [Enterprise Search]Render native connector docs conditionally (#169121) ## Summary Screenshot 2023-10-17 at 16 36 45 ## Release Note External documentation links are rendered conditionally now to avoid empty links. ### 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 --- .../research_configuration.tsx | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/research_configuration.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/research_configuration.tsx index b76d89396384ee..8f32044356a68f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/research_configuration.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/research_configuration.tsx @@ -44,17 +44,19 @@ export const ResearchConfiguration: React.FC = ({ )} - - - {i18n.translate( - 'xpack.enterpriseSearch.content.indices.configurationConnector.researchConfiguration.serviceDocumentationLinkLabel', - { - defaultMessage: '{name} documentation', - values: { name }, - } - )} - - + {externalDocsUrl && ( + + + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.researchConfiguration.serviceDocumentationLinkLabel', + { + defaultMessage: '{name} documentation', + values: { name }, + } + )} + + + )} ); From 3dc0ba39bed9e14da1e47d2238a6f0e5e90a4054 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 17 Oct 2023 19:18:11 +0200 Subject: [PATCH 77/87] [serverless] Give appex-qa team permissions to manage deployments (#169114) --- catalog-info.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/catalog-info.yaml b/catalog-info.yaml index 00637fb1a039bf..e7aa1200044861 100644 --- a/catalog-info.yaml +++ b/catalog-info.yaml @@ -56,6 +56,8 @@ spec: teams: kibana-operations: access_level: MANAGE_BUILD_AND_READ + appex-qa: + access_level: BUILD_AND_READ security-engineering-productivity: access_level: BUILD_AND_READ fleet: From 930b440c9b91a99a3b3398d5d4941d67c88d9128 Mon Sep 17 00:00:00 2001 From: Nikita Indik Date: Tue, 17 Oct 2023 19:44:13 +0200 Subject: [PATCH 78/87] [Security Solution] Test plan for prebuilt rule flyout (#167727) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Resolves: https://github.com/elastic/kibana/issues/166160** ## Summary Adds a test plan for the prebuilt rules flyout. Covers installation and upgrade actions and also the content shown in Overview and Investigation Guide tabs. Scherm­afbeelding 2023-10-03 om 22 29 39 --------- Co-authored-by: Georgii Gorbachev --- .../installation_and_upgrade.md | 198 +++++++++++++++++- 1 file changed, 196 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md b/x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md index b8ae0c85c82e62..cca0f27be0708e 100644 --- a/x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md +++ b/x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules/installation_and_upgrade.md @@ -45,6 +45,83 @@ Status: `in progress`. The current test plan matches `Milestone 2` of the [Rule - Kibana should not crash with Out Of Memory exception during package installation. - For test purposes, it should be possible to use detection rules package versions lower than the latest. +### Functional requirements + +- User should be able to install prebuilt rules with and without previewing what exactly they would install (rule properties). +- User should be able to upgrade prebuilt rules with and without previewing what updates they would apply (rule properties of target rule versions). +- If user chooses to preview a prebuilt rule to be installed/upgraded, we currently show this preview in a flyout. +- In the prebuilt rule preview a tab that doesn't have any sections should not be displayed and a section that doesn't have any properties also should not be displayed. + +Examples of rule properties we show in the prebuilt rule preview flyout: + +```Gherkin +Examples: +| rule_type | property | tab | section | +│ All rule types │ Author │ Overview │ About │ +│ All rule types │ Building block │ Overview │ About │ +│ All rule types │ Severity │ Overview │ About │ +│ All rule types │ Severity override │ Overview │ About │ +│ All rule types │ Risk score │ Overview │ About │ +│ All rule types │ Risk score override │ Overview │ About │ +│ All rule types │ Reference URLs │ Overview │ About │ +│ All rule types │ False positive examples │ Overview │ About │ +│ All rule types │ Custom highlighted fields │ Overview │ About │ +│ All rule types │ License │ Overview │ About │ +│ All rule types │ Rule name override │ Overview │ About │ +│ All rule types │ MITRE ATT&CK™ │ Overview │ About │ +│ All rule types │ Timestamp override │ Overview │ About │ +│ All rule types │ Tags │ Overview │ About │ +│ All rule types │ Type │ Overview │ Definition │ +│ All rule types │ Related integrations │ Overview │ Definition │ +│ All rule types │ Required fields │ Overview │ Definition │ +│ All rule types │ Timeline template │ Overview │ Definition │ +│ All rule types │ Runs every │ Overview │ Schedule │ +│ All rule types │ Additional look-back time │ Overview │ Schedule │ +│ All rule types │ Setup guide │ Overview │ Setup guide │ +│ All rule types │ Investigation guide │ Investigation guide │ Investigation guide │ +│ Custom Query │ Index patterns │ Overview │ Definition │ +│ Custom Query │ Data view ID │ Overview │ Definition │ +│ Custom Query │ Data view index pattern │ Overview │ Definition │ +│ Custom Query │ Custom query │ Overview │ Definition │ +│ Custom Query │ Filters │ Overview │ Definition │ +│ Custom Query │ Saved query name │ Overview │ Definition │ +│ Custom Query │ Saved query filters │ Overview │ Definition │ +│ Custom Query │ Saved query │ Overview │ Definition │ +│ Custom Query │ Suppress alerts by │ Overview │ Definition │ +│ Custom Query │ Suppress alerts for │ Overview │ Definition │ +│ Custom Query │ If a suppression field is missing │ Overview │ Definition │ +│ Machine Learning │ Anomaly score threshold │ Overview │ Definition │ +│ Machine Learning │ Machine Learning job │ Overview │ Definition │ +│ Threshold │ Threshold │ Overview │ Definition │ +│ Threshold │ Index patterns │ Overview │ Definition │ +│ Threshold │ Data view ID │ Overview │ Definition │ +│ Threshold │ Data view index pattern │ Overview │ Definition │ +│ Threshold │ Custom query │ Overview │ Definition │ +│ Threshold │ Filters │ Overview │ Definition │ +│ Event Correlation │ EQL query │ Overview │ Definition │ +│ Event Correlation │ Filters │ Overview │ Definition │ +│ Event Correlation │ Index patterns │ Overview │ Definition │ +│ Event Correlation │ Data view ID │ Overview │ Definition │ +│ Event Correlation │ Data view index pattern │ Overview │ Definition │ +│ Indicator Match │ Indicator index patterns │ Overview │ Definition │ +│ Indicator Match │ Indicator mapping │ Overview │ Definition │ +│ Indicator Match │ Indicator filters │ Overview │ Definition │ +│ Indicator Match │ Indicator index query │ Overview │ Definition │ +│ Indicator Match │ Index patterns │ Overview │ Definition │ +│ Indicator Match │ Data view ID │ Overview │ Definition │ +│ Indicator Match │ Data view index pattern │ Overview │ Definition │ +│ Indicator Match │ Custom query │ Overview │ Definition │ +│ Indicator Match │ Filters │ Overview │ Definition │ +│ New Terms │ Fields │ Overview │ Definition │ +│ New Terms │ History Window Size │ Overview │ Definition │ +│ New Terms │ Index patterns │ Overview │ Definition │ +│ New Terms │ Data view ID │ Overview │ Definition │ +│ New Terms │ Data view index pattern │ Overview │ Definition │ +│ New Terms │ Custom query │ Overview │ Definition │ +│ New Terms │ Filters │ Overview │ Definition │ +│ ESQL │ ESQL query │ Overview │ Definition │ +``` + ## Scenarios ### Package installation @@ -366,7 +443,7 @@ Given no prebuilt rules are installed in Kibana And there are X prebuilt rules available to install When user opens the Add Rules page Then prebuilt rules available for installation should be displayed in the table -When user installs one individual rule +When user installs one individual rule without previewing it Then success message should be displayed after installation And the installed rule should be removed from the table When user navigates back to the Rule Management page @@ -429,6 +506,64 @@ Then user should see a message indicating that all available rules have been ins And user should see a CTA that leads to the Rule Management page ``` +#### **Scenario: User can preview a rule before installing** + +**Automation**: 1 e2e test + +```Gherkin +Given no prebuilt rules are installed in Kibana +And there are 2 rules available to install +When user opens the Add Rules page +Then all rules available for installation should be displayed in the table +When user opens the rule preview for the 1st rule +Then the preview should open +When user closes the preview +Then it should disappear +When user opens the rule preview for the 2nd rule +Then the preview should open +When user installs the rule using a CTA in the rule preview +Then the 2nd rule should be installed +And a success message should be displayed after installation +And the 2nd rule should be removed from the Add Rules table +When user navigates back to the Rule Management page +Then user should see a CTA to install prebuilt rules +And user should see the number of rules available to install as 1 +``` + +#### **Scenario: User can see correct rule information in preview before installing** + +**Automation**: 1 e2e test + +```Gherkin +Given no prebuilt rules are installed in Kibana +And there are X prebuilt rules of all types available to install +When user opens the Add Rules page +Then all X rules available for installation should be displayed in the table +When user opens the rule preview for the 1st rule +Then the preview should open +And all properties of the 1st rule should be displayed in the correct tab and section of the preview (see examples of rule properties above) +When user selects the 2nd rule in the table +Then the preview should be updated +And all properties of the 2nd rule should be displayed in the correct tab and section of the preview (see examples of rule properties above) +And user should be able to repeat this for all X rules +``` + +#### **Scenario: Tabs and sections without content should be hidden in preview before installing** + +**Automation**: 1 e2e test + +```Gherkin +Given no prebuilt rules are installed in Kibana +And there is at least 1 rule available to install +And this rule has neither Setup guide nor Investigation guide +When user opens the Add Rules page +Then all rules available for installation should be displayed in the table +When user opens the rule preview for this rule +Then the preview should open +And the Setup Guide section should NOT be displayed in the Overview tab +And the Investigation Guide tab should NOT be displayed +``` + ### Rule installation workflow: filtering, sorting, pagination TODO: add scenarios https://github.com/elastic/kibana/issues/166215 @@ -467,7 +602,7 @@ And for Y of the installed rules there are new versions available And user is on the Rule Management page When user opens the Rule Updates table Then Y rules available for upgrade should be displayed in the table -When user upgrades one individual rule +When user upgrades one individual rule without previewing it Then success message should be displayed after upgrade And the upgraded rule should be removed from the table And user should see the number of rules available to upgrade decreased by 1 @@ -513,6 +648,65 @@ And user should NOT see a number of rules available to upgrade And user should NOT see the Rule Updates table ``` +#### **Scenario: User can preview a rule before upgrading** + +**Automation**: 1 e2e test + +```Gherkin +Given 2 prebuilt rules are installed in Kibana +And for these 2 installed rules there are new versions available +And user is on the Rule Management page +When user opens the Rule Updates table +Then all rules available for upgrade should be displayed in the table +When user opens the rule preview for the 1st rule +Then the preview should open +When user closes the preview +Then it should disappear +When user opens the rule preview for the 2nd rule +Then the preview should open +When user upgrades the rule using a CTA in the rule preview +Then the 2nd rule should be upgraded to the latest version +And a success message should be displayed after upgrade +And the 2nd rule should be removed from the Rule Updates table +And user should see the number of rules available to upgrade as 1 +``` + +#### **Scenario: User can see correct rule information in preview before upgrading** + +**Automation**: 1 e2e test + +```Gherkin +Given X prebuilt rules of all types are installed in Kibana +And for all of the installed rules there are new versions available +And user is on the Rule Management page +When user opens the Rule Updates table +Then all X rules available for upgrade should be displayed in the table +When user opens the rule preview for the 1st rule +Then the preview should open +And all properties of the new version of the 1st rule should be displayed in the correct tab and section of the preview (see examples of rule properties above) +When user selects the 2nd rule in the table +Then the preview should be updated +And all properties of the new version of the 2nd rule should be displayed in the correct tab and section of the preview (see examples of rule properties above) +And user should be able to repeat this for all X rules +``` + +#### **Scenario: Tabs and sections without content should be hidden in preview before upgrading** + +**Automation**: 1 e2e test + +```Gherkin +Given at least 1 prebuilt rule is installed in Kibana +And for this rule there is a new version available +And the updated version of a rule has neither Setup guide nor Investigation guide +And user is on the Rule Management page +When user opens the Rule Updates table +Then all rules available for upgrade should be displayed in the table +When user opens the rule preview for a rule without Setup guide and Investigation guide +Then the preview should open +And the Setup Guide section should NOT be displayed in the Overview tab +And the Investigation Guide tab should NOT be displayed +``` + ### Rule upgrade workflow: filtering, sorting, pagination TODO: add scenarios https://github.com/elastic/kibana/issues/166215 From 9b73b87d5c7d639c1798e5d8572af8d0c65ffd21 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Tue, 17 Oct 2023 12:24:03 -0600 Subject: [PATCH 79/87] [Security solution] Rename connector from AWS Bedrock to Amazon Bedrock (#169025) --- .../connectors/images/bedrock-connector.png | Bin 303619 -> 297037 bytes .../connectors/images/bedrock-params.png | Bin 197882 -> 194017 bytes .../action_type_selector_modal.tsx | 8 ++++++++ .../content/prompts/welcome/translations.ts | 2 +- .../server/routes/evaluate/utils.ts | 2 +- .../common/bedrock/constants.ts | 2 +- .../connector_types/bedrock/bedrock.test.tsx | 4 ++-- .../connector_types/bedrock/bedrock.tsx | 2 +- .../connector_types/bedrock/constants.tsx | 2 +- .../connector_types/bedrock/translations.ts | 2 +- .../connector_types/bedrock/index.test.ts | 8 ++++---- .../server/connector_types/bedrock/index.ts | 2 +- .../stack_connectors/server/plugin.test.ts | 2 +- .../tests/actions/connector_types/bedrock.ts | 4 ++-- 14 files changed, 24 insertions(+), 16 deletions(-) diff --git a/docs/management/connectors/images/bedrock-connector.png b/docs/management/connectors/images/bedrock-connector.png index 22a537183171de4e7aa029369923f4d11529c716..cfdb19f3fc6c2fdebcd771b69991ce13d17cf48f 100644 GIT binary patch literal 297037 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%0D&UW&3?34V_H z*<#NY7_Rhp-ci(*CX-oud-pw}TnfdE(_5>R(U3oqqvXw{fnJX&q#dn6-r9Ku6s+fb zN=&lY5{{RgY0-zIZy$|>5E$N_NRE|III6Q{gE(fP+3MJ@ndv_L)|QyJ9{7}HJL4C7 zc%ItG*erJ)0)*2N^P#=$NJ-`hiI2T(XtL_xe_4Ib3w%!WweoUcsg5natgPxru;>YW z)>4>3<=`wLtOt3!Uu-pN5YjyXRD;#-h<|OWh4BE#3ok6Qo4Ze|X&E+{fEoCVm9egK z4{+|1Wcy|62o`ME_!@q%5a(w#;Bii=l{GfI+Fc-uPXZemQQ^D5fkcW9`LZb6mmFEN zl%WDB#tL}GTPZ2d@VWS-r=FSjlL zh-r+5{=2UwM|!HeE`u3`jEEc9HSRCK9Y|T59Yp|&2rGq|e?!UI>yZ8xJWX4G;PPRu zG-~WIBV#e7v}0k)^Vb$w@8?^72?^<$!9&Tf9p~F?eTnV6Tb-tiF<3LT$U3Oc6^ba5 zvjk{h09drsmjop{^6wB&r~Q|4dVi}zhQB$ZqEx1$ZYqsr%X?kTqS_QyRowGJuu6z} zvQrzVV!??K@Gw+*-?p+*iUd{i%PqGJ@7<^?&jwWOvWy;o^EgO&-MFmyGe2ZqHF%28 zd$F^0<7UIs2CX^@{YN|Z zw^XXcPe2$<=w?%qg7?e=R?(XWhM}%tf$;(tOC-OlS64sWx#G`%IWeNM@UOQwpIYJj zV@E~pxm(vW{>{(2|Mh4~lfpssq6NixYv}{Q3qYii^>-){lfFTB(AbRm|xzz!S#&YgT`Q|P0nv`8wBsWIM2&x!mj zKBYAj4EF>uK(Ez^1<>;Oc7}uN#9TSYufMxwt49G z^~x9LKNwbYo=tK6gI_lYmWIggGNjBsok1(eps|GU#ew15hp(uAicwZj%iH#er{kbh z&8$gBeDeC%7udp;kD_?zD>N`PBuAFt1P|!=3|NL2v_L+minM(ZP0|rmN=2_ks`WRb zW?-b<^z*J4GY%-0ob(XSKn*N3kYj8&KVmao`7M;FSrLTM1o~{nENDbluT&GcTyL8` zFtLmfF|VVaYSe-}3Whc;gyiU85Z>R2T!Pm*`m7nBSVf5WjGMEvpVBMIx& z{izy`;!8#qaGO@$_14w0aW?hYCNp6&_Rbkp!ue91byT(?);v$ki%s*E`aT6MYplNf zsx5MRWT$ZmWxWoacy+wcy5-dGB*-_^^fcfOo=ZUDun@wWL;rIUSc*4ufo^y2V+A?z zZGjfISdS?7R6n8PQfneYFF#C^?|Sf7>w*>HXX}ZE$-zHCk`5tD3I6HjoycP=K5m9J z{a-RxC+p(m%%hi<>y~i0%dR4(gF(52_T(>XFZ&f%qiHND>I+WW*tnR~s vo>Kd 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%0Drf;@B+K5?PuH56 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

*%;niR&;=Y;u=&q=jm^~(C&BibpgnzeNW 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�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

^-ArpzGu!EB&0z5)z1p-NBnF#ktWucI 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

O=%=5m`X^dVuE%EaJ)A%-K+aSk6CU}wyrkA968 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 literal 197882 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 z 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 T?#YS)|IV3M{aSYB+He00+65E% diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/action_type_selector_modal.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/action_type_selector_modal.tsx index 84a72e0cd2b5f8..6184525877d1ca 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/action_type_selector_modal.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/action_type_selector_modal.tsx @@ -18,6 +18,7 @@ import { } from '@elastic/eui'; import { ActionType } from '@kbn/actions-plugin/common'; import { ActionTypeRegistryContract } from '@kbn/triggers-actions-ui-plugin/public'; +import { css } from '@emotion/css/dist/emotion-css.cjs'; import * as i18n from '../translations'; interface Props { @@ -26,6 +27,12 @@ interface Props { onClose: () => void; onSelect: (actionType: ActionType) => void; } +const itemClassName = css` + .euiKeyPadMenuItem__label { + white-space: nowrap; + overflow: hidden; + } +`; export const ActionTypeSelectorModal = ({ actionTypes, @@ -46,6 +53,7 @@ export const ActionTypeSelectorModal = ({ return ( { describe('actionTypeRegistry.get() works', () => { test('connector type static data is as expected', () => { expect(actionTypeModel.id).toEqual(ACTION_TYPE_ID); - expect(actionTypeModel.selectMessage).toBe('Send a request to AWS Bedrock.'); - expect(actionTypeModel.actionTypeTitle).toBe('AWS Bedrock'); + expect(actionTypeModel.selectMessage).toBe('Send a request to Amazon Bedrock.'); + expect(actionTypeModel.actionTypeTitle).toBe('Amazon Bedrock'); }); }); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/bedrock/bedrock.tsx b/x-pack/plugins/stack_connectors/public/connector_types/bedrock/bedrock.tsx index e6d674354511a4..361caed6882c29 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/bedrock/bedrock.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/bedrock/bedrock.tsx @@ -21,7 +21,7 @@ export function getConnectorType(): BedrockConnector { id: BEDROCK_CONNECTOR_ID, iconClass: lazy(() => import('./logo')), selectMessage: i18n.translate('xpack.stackConnectors.components.bedrock.selectMessageText', { - defaultMessage: 'Send a request to AWS Bedrock.', + defaultMessage: 'Send a request to Amazon Bedrock.', }), actionTypeTitle: BEDROCK_TITLE, validateParams: async ( diff --git a/x-pack/plugins/stack_connectors/public/connector_types/bedrock/constants.tsx b/x-pack/plugins/stack_connectors/public/connector_types/bedrock/constants.tsx index 7ee3e35cecf157..88fc42e004bf82 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/bedrock/constants.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/bedrock/constants.tsx @@ -33,7 +33,7 @@ export const bedrockConfig: ConfigFieldSchema[] = [ defaultValue: DEFAULT_BEDROCK_URL, helpText: ( { configurationUtilities = actionsConfigMock.create(); connectorType = getConnectorType(); }); - test('exposes the connector as `AWS Bedrock` with id `.bedrock`', () => { + test('exposes the connector as `Amazon Bedrock` with id `.bedrock`', () => { expect(connectorType.id).toEqual('.bedrock'); - expect(connectorType.name).toEqual('AWS Bedrock'); + expect(connectorType.name).toEqual('Amazon Bedrock'); }); describe('config validation', () => { test('config validation passes when only required fields are provided', () => { @@ -55,7 +55,7 @@ describe('Bedrock Connector', () => { expect(() => { configValidator(config, { configurationUtilities }); }).toThrowErrorMatchingInlineSnapshot( - '"Error configuring AWS Bedrock action: Error: URL Error: Invalid URL: example.com/do-something"' + '"Error configuring Amazon Bedrock action: Error: URL Error: Invalid URL: example.com/do-something"' ); }); @@ -75,7 +75,7 @@ describe('Bedrock Connector', () => { expect(() => { configValidator(config, { configurationUtilities: configUtils }); }).toThrowErrorMatchingInlineSnapshot( - `"Error configuring AWS Bedrock action: Error: error validating url: target url is not present in allowedHosts"` + `"Error configuring Amazon Bedrock action: Error: error validating url: target url is not present in allowedHosts"` ); }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/bedrock/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/bedrock/index.ts index 11050628203a9c..02b2bff9a93ae2 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/bedrock/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/bedrock/index.ts @@ -43,7 +43,7 @@ export const configValidator = (configObject: Config, validatorServices: Validat } catch (err) { throw new Error( i18n.translate('xpack.stackConnectors.bedrock.configurationErrorApiProvider', { - defaultMessage: 'Error configuring AWS Bedrock action: {err}', + defaultMessage: 'Error configuring Amazon Bedrock action: {err}', values: { err, }, diff --git a/x-pack/plugins/stack_connectors/server/plugin.test.ts b/x-pack/plugins/stack_connectors/server/plugin.test.ts index c728ee92cea407..c5c16a29647fdf 100644 --- a/x-pack/plugins/stack_connectors/server/plugin.test.ts +++ b/x-pack/plugins/stack_connectors/server/plugin.test.ts @@ -164,7 +164,7 @@ describe('Stack Connectors Plugin', () => { 4, expect.objectContaining({ id: '.bedrock', - name: 'AWS Bedrock', + name: 'Amazon Bedrock', }) ); expect(actionsSetup.registerSubActionConnectorType).toHaveBeenNthCalledWith( diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts index 8d4412cf37a196..4983d19d36b695 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/bedrock.ts @@ -160,7 +160,7 @@ export default function bedrockTest({ getService }: FtrProviderContext) { statusCode: 400, error: 'Bad Request', message: - 'error validating action type config: Error configuring AWS Bedrock action: Error: error validating url: target url "http://bedrock.mynonexistent.com" is not added to the Kibana config xpack.actions.allowedHosts', + 'error validating action type config: Error configuring Amazon Bedrock action: Error: error validating url: target url "http://bedrock.mynonexistent.com" is not added to the Kibana config xpack.actions.allowedHosts', }); }); }); @@ -280,7 +280,7 @@ export default function bedrockTest({ getService }: FtrProviderContext) { status: 'error', retry: true, message: 'an error occurred while running the action', - service_message: `Sub action "invalidAction" is not registered. Connector id: ${bedrockActionId}. Connector name: AWS Bedrock. Connector type: .bedrock`, + service_message: `Sub action "invalidAction" is not registered. Connector id: ${bedrockActionId}. Connector name: Amazon Bedrock. Connector type: .bedrock`, }); }); }); From 0554daacb8e50f44580047701312d5bb14d2c7b4 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Tue, 17 Oct 2023 13:23:43 -0500 Subject: [PATCH 80/87] skip failing test suite (#169133) --- .../pages/policy/view/integration_tests/policy_list.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/integration_tests/policy_list.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/integration_tests/policy_list.test.tsx index ee520a98632bc9..abb68f1d79814d 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/integration_tests/policy_list.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/integration_tests/policy_list.test.tsx @@ -25,7 +25,8 @@ jest.mock('../../../../../common/components/user_privileges'); const getPackagePolicies = sendGetEndpointSpecificPackagePolicies as jest.Mock; const useUserPrivilegesMock = useUserPrivileges as jest.Mock; -describe('When on the policy list page', () => { +// Failing: See https://github.com/elastic/kibana/issues/169133 +describe.skip('When on the policy list page', () => { let render: () => ReturnType; let renderResult: ReturnType; let history: AppContextTestRender['history']; From 843aaf2f04dd12d4599413c34a9c78d089d54224 Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Tue, 17 Oct 2023 20:04:20 +0100 Subject: [PATCH 81/87] [SecuritySolution][DataQualityDashboard] Migrate data quality dashboard APIs to versioned router (#169037) ## Summary https://github.com/elastic/kibana/issues/168334 https://github.com/elastic/kibana/issues/166271 Before: Screenshot 2023-10-16 at 21 45 02 Screenshot 2023-10-16 at 21 45 09 After: Screenshot 2023-10-16 at 22 41 31 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../impl/data_quality/helpers.ts | 3 +- .../mock_auditbeat_pattern_rollup.ts | 6 + .../mock_packetbeat_pattern_rollup.ts | 2 + .../data_quality/use_ilm_explain/index.tsx | 2 + .../impl/data_quality/use_mappings/helpers.ts | 2 + .../impl/data_quality/use_stats/index.tsx | 2 + .../use_unallowed_values/helpers.test.ts | 2 + .../use_unallowed_values/helpers.ts | 2 + .../common/constants.ts | 1 + .../server/__mocks__/server.ts | 75 +++++++--- .../server/plugin.ts | 8 +- .../server/routes/get_ilm_explain.test.ts | 10 +- .../server/routes/get_ilm_explain.ts | 58 ++++---- .../server/routes/get_index_mappings.test.ts | 13 +- .../server/routes/get_index_mappings.ts | 54 +++---- .../server/routes/get_index_stats.test.ts | 11 +- .../server/routes/get_index_stats.ts | 133 ++++++++++-------- .../routes/get_unallowed_field_values.test.ts | 10 +- .../routes/get_unallowed_field_values.ts | 54 +++---- .../server/schemas/common.ts | 2 +- .../ecs_data_quality_dashboard/tsconfig.json | 2 + 21 files changed, 285 insertions(+), 167 deletions(-) diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts index 2ebfec9a7f2576..ba195f0de0e159 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts @@ -27,6 +27,7 @@ import type { } from './types'; const EMPTY_INDEX_NAMES: string[] = []; +export const INTERNAL_API_VERSION = '1'; export const getIndexNames = ({ ilmExplain, @@ -282,7 +283,7 @@ export const getSizeInBytes = ({ }: { indexName: string; stats: Record | null; -}): number => (stats && stats[indexName]?.primaries?.store?.size_in_bytes) ?? 0; +}): number => (stats && stats[indexName]?.primaries?.store?.total_data_set_size_in_bytes) ?? 0; export const getTotalDocsCount = ({ indexNames, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_auditbeat_pattern_rollup.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_auditbeat_pattern_rollup.ts index 7c18523e44aa36..2f83f899dc0d21 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_auditbeat_pattern_rollup.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_auditbeat_pattern_rollup.ts @@ -53,6 +53,7 @@ export const auditbeatNoResults: PatternRollup = { primaries: { store: { size_in_bytes: 18791790, + total_data_set_size_in_bytes: 18791790, reserved_in_bytes: 0, }, }, @@ -70,6 +71,7 @@ export const auditbeatNoResults: PatternRollup = { primaries: { store: { size_in_bytes: 247, + total_data_set_size_in_bytes: 247, reserved_in_bytes: 0, }, }, @@ -87,6 +89,7 @@ export const auditbeatNoResults: PatternRollup = { primaries: { store: { size_in_bytes: 28409, + total_data_set_size_in_bytes: 28409, reserved_in_bytes: 0, }, }, @@ -182,6 +185,7 @@ export const auditbeatWithAllResults: PatternRollup = { primaries: { store: { size_in_bytes: 18791790, + total_data_set_size_in_bytes: 18791790, reserved_in_bytes: 0, }, }, @@ -199,6 +203,7 @@ export const auditbeatWithAllResults: PatternRollup = { primaries: { store: { size_in_bytes: 247, + total_data_set_size_in_bytes: 247, reserved_in_bytes: 0, }, }, @@ -216,6 +221,7 @@ export const auditbeatWithAllResults: PatternRollup = { primaries: { store: { size_in_bytes: 28409, + total_data_set_size_in_bytes: 28409, reserved_in_bytes: 0, }, }, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_packetbeat_pattern_rollup.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_packetbeat_pattern_rollup.ts index b04c8bb87600a1..369803a44a3dd1 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_packetbeat_pattern_rollup.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/mock/pattern_rollup/mock_packetbeat_pattern_rollup.ts @@ -51,6 +51,7 @@ export const packetbeatNoResults: PatternRollup = { primaries: { store: { size_in_bytes: 512194751, + total_data_set_size_in_bytes: 512194751, reserved_in_bytes: 0, }, }, @@ -68,6 +69,7 @@ export const packetbeatNoResults: PatternRollup = { primaries: { store: { size_in_bytes: 584326147, + total_data_set_size_in_bytes: 584326147, reserved_in_bytes: 0, }, }, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.tsx index ae643745bd805c..4e955493388746 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_ilm_explain/index.tsx @@ -9,6 +9,7 @@ import type { IlmExplainLifecycleLifecycleExplain } from '@elastic/elasticsearch import { useEffect, useState } from 'react'; import { useDataQualityContext } from '../data_quality_panel/data_quality_context'; +import { INTERNAL_API_VERSION } from '../helpers'; import * as i18n from '../translations'; const ILM_EXPLAIN_ENDPOINT = '/internal/ecs_data_quality_dashboard/ilm_explain'; @@ -43,6 +44,7 @@ export const useIlmExplain = (pattern: string): UseIlmExplain => { { method: 'GET', signal: abortController.signal, + version: INTERNAL_API_VERSION, } ); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_mappings/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_mappings/helpers.ts index 8aab64729df2f5..809f543c0c0ae1 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_mappings/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_mappings/helpers.ts @@ -9,6 +9,7 @@ import type { HttpHandler } from '@kbn/core-http-browser'; import type { IndicesGetMappingIndexMappingRecord } from '@elastic/elasticsearch/lib/api/types'; import * as i18n from '../translations'; +import { INTERNAL_API_VERSION } from '../helpers'; export const MAPPINGS_API_ROUTE = '/internal/ecs_data_quality_dashboard/mappings'; @@ -29,6 +30,7 @@ export async function fetchMappings({ { method: 'GET', signal: abortController.signal, + version: INTERNAL_API_VERSION, } ); } catch (e) { diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.tsx index 6875dad3d4dfc8..fce940de15f757 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_stats/index.tsx @@ -11,6 +11,7 @@ import { HttpFetchQuery } from '@kbn/core/public'; import { useDataQualityContext } from '../data_quality_panel/data_quality_context'; import * as i18n from '../translations'; +import { INTERNAL_API_VERSION } from '../helpers'; const STATS_ENDPOINT = '/internal/ecs_data_quality_dashboard/stats'; @@ -53,6 +54,7 @@ export const useStats = ({ const response = await httpFetch>( `${STATS_ENDPOINT}/${encodedIndexName}`, { + version: INTERNAL_API_VERSION, method: 'GET', signal: abortController.signal, query, diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.test.ts index 7b0a77d9af564e..cad285a4bc976b 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.test.ts @@ -15,6 +15,7 @@ import { } from './helpers'; import { mockUnallowedValuesResponse } from '../mock/unallowed_values/mock_unallowed_values'; import { UnallowedValueRequestItem, UnallowedValueSearchResult } from '../types'; +import { INTERNAL_API_VERSION } from '../helpers'; describe('helpers', () => { let originalFetch: typeof global['fetch']; @@ -406,6 +407,7 @@ describe('helpers', () => { headers: { 'Content-Type': 'application/json' }, method: 'POST', signal: abortController.signal, + version: INTERNAL_API_VERSION, } ); }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.ts index 5a331e7e1b8dab..a193456d4afa94 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/use_unallowed_values/helpers.ts @@ -6,6 +6,7 @@ */ import type { HttpHandler } from '@kbn/core-http-browser'; +import { INTERNAL_API_VERSION } from '../helpers'; import * as i18n from '../translations'; import type { Bucket, @@ -81,6 +82,7 @@ export async function fetchUnallowedValues({ headers: { 'Content-Type': 'application/json' }, method: 'POST', signal: abortController.signal, + version: INTERNAL_API_VERSION, }); } catch (e) { throw new Error( diff --git a/x-pack/plugins/ecs_data_quality_dashboard/common/constants.ts b/x-pack/plugins/ecs_data_quality_dashboard/common/constants.ts index 51455c071b5193..52c734797f726d 100755 --- a/x-pack/plugins/ecs_data_quality_dashboard/common/constants.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/common/constants.ts @@ -13,3 +13,4 @@ export const GET_INDEX_STATS = `${BASE_PATH}/stats/{pattern}`; export const GET_INDEX_MAPPINGS = `${BASE_PATH}/mappings/{pattern}`; export const GET_UNALLOWED_FIELD_VALUES = `${BASE_PATH}/unallowed_field_values`; export const GET_ILM_EXPLAIN = `${BASE_PATH}/ilm_explain/{pattern}`; +export const INTERNAL_API_VERSION = '1'; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts index 7ac44e1beedf1d..913c226517ce3f 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/__mocks__/server.ts @@ -5,35 +5,73 @@ * 2.0. */ import { httpServiceMock } from '@kbn/core/server/mocks'; -import type { RequestHandler, RouteConfig, KibanaRequest } from '@kbn/core/server'; +import type { IRouter, RouteMethod, RequestHandler, KibanaRequest } from '@kbn/core/server'; import type { RequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; +import type { RouterMock } from '@kbn/core-http-router-server-mocks'; +import type { AddVersionOpts, VersionedRouteConfig } from '@kbn/core-http-server'; import { requestMock } from './request'; import { responseMock as responseFactoryMock } from './response'; import { requestContextMock } from './request_context'; import { responseAdapter } from './test_adapters'; +import { INTERNAL_API_VERSION } from '../../common/constants'; interface Route { - config: RouteConfig; + config: AddVersionOpts; 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, +interface RegisteredVersionedRoute { + routeConfig: VersionedRouteConfig; + versionConfig: AddVersionOpts; + routeHandler: RequestHandler; +} + +type RouterMethod = Extract; + +export const getRegisteredVersionedRouteMock = ( + routerMock: RouterMock, + method: RouterMethod, + path: string, + version: string +): RegisteredVersionedRoute => { + const route = routerMock.versioned.getRoute(method, path); + const routeVersion = route.versions[version]; + + if (!routeVersion) { + throw new Error(`Handler for [${method}][${path}] with version [${version}] no found!`); + } + + return { + routeConfig: route.config, + versionConfig: routeVersion.config, + routeHandler: routeVersion.handler, + }; +}; + +const getRoute = (routerMock: MockServer['router'], request: KibanaRequest): Route => { + const versionedRouteCalls = [ + ...routerMock.versioned.get.mock.calls, + ...routerMock.versioned.post.mock.calls, + ...routerMock.versioned.put.mock.calls, + ...routerMock.versioned.patch.mock.calls, + ...routerMock.versioned.delete.mock.calls, ]; - const [route] = routeCalls; - if (!route) { + const [versionedRoute] = versionedRouteCalls; + + if (!versionedRoute) { throw new Error('No route registered!'); } - const [config, handler] = route; - return { config, handler }; + const { routeHandler, versionConfig } = getRegisteredVersionedRouteMock( + routerMock, + request.route.method, + request.route.path, + INTERNAL_API_VERSION + ); + + return { config: versionConfig, handler: routeHandler }; }; const buildResultMock = () => ({ ok: jest.fn((x) => x), badRequest: jest.fn((x) => x) }); @@ -53,17 +91,19 @@ class MockServer { 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); + await this.getRoute(validatedRequest).handler(context, validatedRequest, this.responseMock); + return responseAdapter(this.responseMock); } - private getRoute(): Route { - return getRoute(this.router); + private getRoute(request: KibanaRequest): Route { + return getRoute(this.router, request); } // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -72,7 +112,8 @@ class MockServer { } private validateRequest(request: KibanaRequest): KibanaRequest { - const validations = this.getRoute().config.validate; + const config = this.getRoute(request).config; + const validations = config.validate && config.validate?.request; if (!validations) { return request; } diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/plugin.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/plugin.ts index d93766d2f3a7ef..0c1cf336dc10df 100755 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/plugin.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/plugin.ts @@ -29,10 +29,10 @@ export class EcsDataQualityDashboardPlugin const router = core.http.createRouter(); // this would be deleted when plugin is removed // Register server side APIs - getIndexMappingsRoute(router); - getIndexStatsRoute(router); - getUnallowedFieldValuesRoute(router); - getILMExplainRoute(router); + getIndexMappingsRoute(router, this.logger); + getIndexStatsRoute(router, this.logger); + getUnallowedFieldValuesRoute(router, this.logger); + getILMExplainRoute(router, this.logger); return {}; } diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.test.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.test.ts index 737ddf781f1a97..329defab80c2b0 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.test.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.test.ts @@ -12,6 +12,7 @@ import { serverMock } from '../__mocks__/server'; import { requestMock } from '../__mocks__/request'; import { requestContextMock } from '../__mocks__/request_context'; import { getILMExplainRoute } from './get_ilm_explain'; +import { loggerMock, MockedLogger } from '@kbn/logging-mocks'; jest.mock('../lib', () => ({ fetchILMExplain: jest.fn(), @@ -20,6 +21,8 @@ jest.mock('../lib', () => ({ describe('getILMExplainRoute route', () => { let server: ReturnType; let { context } = requestContextMock.createTools(); + let logger: MockedLogger; + const req = requestMock.create({ method: 'get', path: GET_ILM_EXPLAIN, @@ -32,9 +35,10 @@ describe('getILMExplainRoute route', () => { jest.clearAllMocks(); server = serverMock.create(); + logger = loggerMock.create(); ({ context } = requestContextMock.createTools()); - getILMExplainRoute(server.router); + getILMExplainRoute(server.router, logger); }); test('Returns index ilm information', async () => { @@ -91,11 +95,13 @@ describe('getILMExplainRoute route', () => { describe('request validation', () => { let server: ReturnType; + let logger: MockedLogger; beforeEach(() => { server = serverMock.create(); + logger = loggerMock.create(); - getILMExplainRoute(server.router); + getILMExplainRoute(server.router, logger); }); test('disallows invalid pattern', () => { diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.ts index dab234eecaae71..c30271c62e3133 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_ilm_explain.ts @@ -5,41 +5,51 @@ * 2.0. */ -import { IRouter } from '@kbn/core/server'; +import { IRouter, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; -import { GET_ILM_EXPLAIN } from '../../common/constants'; +import { GET_ILM_EXPLAIN, INTERNAL_API_VERSION } from '../../common/constants'; import { fetchILMExplain } from '../lib'; import { buildResponse } from '../lib/build_response'; import { buildRouteValidation } from '../schemas/common'; import { GetILMExplainParams } from '../schemas/get_ilm_explain'; -export const getILMExplainRoute = (router: IRouter) => { - router.get( - { +export const getILMExplainRoute = (router: IRouter, logger: Logger) => { + router.versioned + .get({ path: GET_ILM_EXPLAIN, - validate: { params: buildRouteValidation(GetILMExplainParams) }, - }, - async (context, request, response) => { - const resp = buildResponse(response); + access: 'internal', + }) + .addVersion( + { + version: INTERNAL_API_VERSION, + validate: { + request: { + params: buildRouteValidation(GetILMExplainParams), + }, + }, + }, + async (context, request, response) => { + const resp = buildResponse(response); - try { - const { client } = (await context.core).elasticsearch; - const decodedIndexName = decodeURIComponent(request.params.pattern); + try { + const { client } = (await context.core).elasticsearch; + const decodedIndexName = decodeURIComponent(request.params.pattern); - const ilmExplain = await fetchILMExplain(client, decodedIndexName); + const ilmExplain = await fetchILMExplain(client, decodedIndexName); - return response.ok({ - body: ilmExplain.indices, - }); - } catch (err) { - const error = transformError(err); + return response.ok({ + body: ilmExplain.indices, + }); + } catch (err) { + const error = transformError(err); - return resp.error({ - body: error.message, - statusCode: error.statusCode, - }); + logger.error(error.message); + return resp.error({ + body: error.message, + statusCode: error.statusCode, + }); + } } - } - ); + ); }; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.test.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.test.ts index 6c76c843962996..34ce98d4f9378a 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.test.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.test.ts @@ -12,6 +12,7 @@ import { serverMock } from '../__mocks__/server'; import { requestMock } from '../__mocks__/request'; import { requestContextMock } from '../__mocks__/request_context'; import { getIndexMappingsRoute } from './get_index_mappings'; +import { loggerMock, MockedLogger } from '@kbn/logging-mocks'; jest.mock('../lib', () => ({ fetchMappings: jest.fn(), @@ -20,6 +21,8 @@ jest.mock('../lib', () => ({ describe('getIndexMappingsRoute route', () => { let server: ReturnType; let { context } = requestContextMock.createTools(); + let logger: MockedLogger; + const req = requestMock.create({ method: 'get', path: GET_INDEX_MAPPINGS, @@ -32,9 +35,11 @@ describe('getIndexMappingsRoute route', () => { jest.clearAllMocks(); server = serverMock.create(); + logger = loggerMock.create(); + ({ context } = requestContextMock.createTools()); - getIndexMappingsRoute(server.router); + getIndexMappingsRoute(server.router, logger); }); test('Returns index stats', async () => { @@ -58,11 +63,11 @@ describe('getIndexMappingsRoute route', () => { describe('request validation', () => { let server: ReturnType; - + let logger: MockedLogger; beforeEach(() => { server = serverMock.create(); - - getIndexMappingsRoute(server.router); + logger = loggerMock.create(); + getIndexMappingsRoute(server.router, logger); }); test('disallows invalid pattern', () => { diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.ts index 8b81daebeec8d5..c7ab5e1d4a790c 100755 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_mappings.ts @@ -5,41 +5,47 @@ * 2.0. */ -import { IRouter } from '@kbn/core/server'; +import { IRouter, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import { fetchMappings } from '../lib'; import { buildResponse } from '../lib/build_response'; -import { GET_INDEX_MAPPINGS } from '../../common/constants'; +import { GET_INDEX_MAPPINGS, INTERNAL_API_VERSION } from '../../common/constants'; import { GetIndexMappingsParams } from '../schemas/get_index_mappings'; import { buildRouteValidation } from '../schemas/common'; -export const getIndexMappingsRoute = (router: IRouter) => { - router.get( - { +export const getIndexMappingsRoute = (router: IRouter, logger: Logger) => { + router.versioned + .get({ path: GET_INDEX_MAPPINGS, - validate: { params: buildRouteValidation(GetIndexMappingsParams) }, - }, - async (context, request, response) => { - const resp = buildResponse(response); + access: 'internal', + }) + .addVersion( + { + version: INTERNAL_API_VERSION, + validate: { request: { params: buildRouteValidation(GetIndexMappingsParams) } }, + }, + async (context, request, response) => { + const resp = buildResponse(response); - try { - const { client } = (await context.core).elasticsearch; - const decodedIndexName = decodeURIComponent(request.params.pattern); + try { + const { client } = (await context.core).elasticsearch; + const decodedIndexName = decodeURIComponent(request.params.pattern); - const mappings = await fetchMappings(client, decodedIndexName); + const mappings = await fetchMappings(client, decodedIndexName); - return response.ok({ - body: mappings, - }); - } catch (err) { - const error = transformError(err); + return response.ok({ + body: mappings, + }); + } catch (err) { + const error = transformError(err); + logger.error(error.message); - return resp.error({ - body: error.message, - statusCode: error.statusCode, - }); + return resp.error({ + body: error.message, + statusCode: error.statusCode, + }); + } } - } - ); + ); }; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.test.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.test.ts index aa7fc306b47e88..e000809797a01c 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.test.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.test.ts @@ -12,6 +12,7 @@ import { serverMock } from '../__mocks__/server'; import { requestMock } from '../__mocks__/request'; import { requestContextMock } from '../__mocks__/request_context'; import { getIndexStatsRoute } from './get_index_stats'; +import { loggerMock, MockedLogger } from '@kbn/logging-mocks'; jest.mock('../lib', () => ({ fetchStats: jest.fn(), @@ -21,6 +22,8 @@ jest.mock('../lib', () => ({ describe('getIndexStatsRoute route', () => { let server: ReturnType; let { context } = requestContextMock.createTools(); + let logger: MockedLogger; + const req = requestMock.create({ method: 'get', path: GET_INDEX_STATS, @@ -38,9 +41,11 @@ describe('getIndexStatsRoute route', () => { jest.clearAllMocks(); server = serverMock.create(); + logger = loggerMock.create(); + ({ context } = requestContextMock.createTools()); - getIndexStatsRoute(server.router); + getIndexStatsRoute(server.router, logger); }); test('Returns index stats', async () => { @@ -127,11 +132,13 @@ describe('getIndexStatsRoute route', () => { describe('request validation', () => { let server: ReturnType; + let logger: MockedLogger; beforeEach(() => { server = serverMock.create(); + logger = loggerMock.create(); - getIndexStatsRoute(server.router); + getIndexStatsRoute(server.router, logger); }); test('disallows invalid pattern', () => { diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.ts index 839d21931a0641..f98fa03c275230 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_index_stats.ts @@ -5,87 +5,96 @@ * 2.0. */ import { i18n } from '@kbn/i18n'; -import { IRouter } from '@kbn/core/server'; +import { IRouter, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import { IndicesStatsIndicesStats } from '@elastic/elasticsearch/lib/api/types'; import { fetchStats, fetchAvailableIndices } from '../lib'; import { buildResponse } from '../lib/build_response'; -import { GET_INDEX_STATS } from '../../common/constants'; +import { GET_INDEX_STATS, INTERNAL_API_VERSION } from '../../common/constants'; import { buildRouteValidation } from '../schemas/common'; import { GetIndexStatsParams, GetIndexStatsQuery } from '../schemas/get_index_stats'; -export const getIndexStatsRoute = (router: IRouter) => { - router.get( - { +export const getIndexStatsRoute = (router: IRouter, logger: Logger) => { + router.versioned + .get({ path: GET_INDEX_STATS, - validate: { - params: buildRouteValidation(GetIndexStatsParams), - query: buildRouteValidation(GetIndexStatsQuery), + access: 'internal', + }) + .addVersion( + { + version: INTERNAL_API_VERSION, + validate: { + request: { + params: buildRouteValidation(GetIndexStatsParams), + query: buildRouteValidation(GetIndexStatsQuery), + }, + }, }, - }, - async (context, request, response) => { - const resp = buildResponse(response); + async (context, request, response) => { + const resp = buildResponse(response); - try { - const { client } = (await context.core).elasticsearch; - const esClient = client.asCurrentUser; + try { + const { client } = (await context.core).elasticsearch; + const esClient = client.asCurrentUser; - const decodedIndexName = decodeURIComponent(request.params.pattern); + const decodedIndexName = decodeURIComponent(request.params.pattern); - const stats = await fetchStats(client, decodedIndexName); - const { isILMAvailable, startDate, endDate } = request.query; + const stats = await fetchStats(client, decodedIndexName); + const { isILMAvailable, startDate, endDate } = request.query; - if (isILMAvailable === true) { - return response.ok({ - body: stats.indices, - }); - } + if (isILMAvailable === true) { + return response.ok({ + body: stats.indices, + }); + } - /** - * If ILM is not available, we need to fetch the available indices with the given date range. - * `fetchAvailableIndices` returns indices that have data in the given date range. - */ - if (startDate && endDate) { - const decodedStartDate = decodeURIComponent(startDate); - const decodedEndDate = decodeURIComponent(endDate); + /** + * If ILM is not available, we need to fetch the available indices with the given date range. + * `fetchAvailableIndices` returns indices that have data in the given date range. + */ + if (startDate && endDate) { + const decodedStartDate = decodeURIComponent(startDate); + const decodedEndDate = decodeURIComponent(endDate); - const indices = await fetchAvailableIndices(esClient, { - indexPattern: decodedIndexName, - startDate: decodedStartDate, - endDate: decodedEndDate, - }); - const availableIndices = indices?.aggregations?.index?.buckets?.reduce( - (acc: Record, { key }: { key: string }) => { - if (stats.indices?.[key]) { - acc[key] = stats.indices?.[key]; - } - return acc; - }, - {} - ); + const indices = await fetchAvailableIndices(esClient, { + indexPattern: decodedIndexName, + startDate: decodedStartDate, + endDate: decodedEndDate, + }); + const availableIndices = indices?.aggregations?.index?.buckets?.reduce( + (acc: Record, { key }: { key: string }) => { + if (stats.indices?.[key]) { + acc[key] = stats.indices?.[key]; + } + return acc; + }, + {} + ); + + return response.ok({ + body: availableIndices, + }); + } else { + return resp.error({ + body: i18n.translate( + 'xpack.ecsDataQualityDashboard.getIndexStats.dateRangeRequiredErrorMessage', + { + defaultMessage: 'startDate and endDate are required', + } + ), + statusCode: 400, + }); + } + } catch (err) { + const error = transformError(err); + logger.error(error.message); - return response.ok({ - body: availableIndices, - }); - } else { return resp.error({ - body: i18n.translate( - 'xpack.ecsDataQualityDashboard.getIndexStats.dateRangeRequiredErrorMessage', - { - defaultMessage: 'startDate and endDate are required', - } - ), - statusCode: 400, + body: error.message, + statusCode: error.statusCode, }); } - } catch (err) { - const error = transformError(err); - return resp.error({ - body: error.message, - statusCode: error.statusCode, - }); } - } - ); + ); }; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.test.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.test.ts index bb593561116997..fe18893acaec12 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.test.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.test.ts @@ -12,6 +12,7 @@ import { serverMock } from '../__mocks__/server'; import { requestMock } from '../__mocks__/request'; import { requestContextMock } from '../__mocks__/request_context'; import { getUnallowedFieldValuesRoute } from './get_unallowed_field_values'; +import { loggerMock, MockedLogger } from '@kbn/logging-mocks'; jest.mock('../lib', () => ({ getUnallowedFieldValues: jest.fn(), @@ -20,6 +21,8 @@ jest.mock('../lib', () => ({ describe('getUnallowedFieldValuesRoute route', () => { let server: ReturnType; let { context } = requestContextMock.createTools(); + let logger: MockedLogger; + const req = requestMock.create({ method: 'post', path: GET_UNALLOWED_FIELD_VALUES, @@ -37,8 +40,9 @@ describe('getUnallowedFieldValuesRoute route', () => { server = serverMock.create(); ({ context } = requestContextMock.createTools()); + logger = loggerMock.create(); - getUnallowedFieldValuesRoute(server.router); + getUnallowedFieldValuesRoute(server.router, logger); }); test('Returns unallowedValues', async () => { @@ -107,11 +111,13 @@ describe('getUnallowedFieldValuesRoute route', () => { describe('request validation', () => { let server: ReturnType; + let logger: MockedLogger; beforeEach(() => { server = serverMock.create(); + logger = loggerMock.create(); - getUnallowedFieldValuesRoute(server.router); + getUnallowedFieldValuesRoute(server.router, logger); }); test('disallows invalid pattern', () => { diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.ts index be504a812e16bf..db8887c2dfa66f 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/get_unallowed_field_values.ts @@ -5,40 +5,46 @@ * 2.0. */ -import { IRouter } from '@kbn/core/server'; +import { IRouter, Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import { getUnallowedFieldValues } from '../lib'; import { buildResponse } from '../lib/build_response'; -import { GET_UNALLOWED_FIELD_VALUES } from '../../common/constants'; +import { GET_UNALLOWED_FIELD_VALUES, INTERNAL_API_VERSION } from '../../common/constants'; import { buildRouteValidation } from '../schemas/common'; import { GetUnallowedFieldValuesBody } from '../schemas/get_unallowed_field_values'; -export const getUnallowedFieldValuesRoute = (router: IRouter) => { - router.post( - { +export const getUnallowedFieldValuesRoute = (router: IRouter, logger: Logger) => { + router.versioned + .post({ path: GET_UNALLOWED_FIELD_VALUES, - validate: { body: buildRouteValidation(GetUnallowedFieldValuesBody) }, - }, - async (context, request, response) => { - const resp = buildResponse(response); - const esClient = (await context.core).elasticsearch.client.asCurrentUser; + access: 'internal', + }) + .addVersion( + { + version: INTERNAL_API_VERSION, + validate: { request: { body: buildRouteValidation(GetUnallowedFieldValuesBody) } }, + }, + async (context, request, response) => { + const resp = buildResponse(response); + const esClient = (await context.core).elasticsearch.client.asCurrentUser; - try { - const items = request.body; + try { + const items = request.body; - const { responses } = await getUnallowedFieldValues(esClient, items); - return response.ok({ - body: responses, - }); - } catch (err) { - const error = transformError(err); + const { responses } = await getUnallowedFieldValues(esClient, items); + return response.ok({ + body: responses, + }); + } catch (err) { + const error = transformError(err); + logger.error(error.message); - return resp.error({ - body: error.message, - statusCode: error.statusCode, - }); + return resp.error({ + body: error.message, + statusCode: error.statusCode, + }); + } } - } - ); + ); }; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/common.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/common.ts index 00e97a9326c5e6..57dc45d4071f7c 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/common.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/common.ts @@ -7,7 +7,7 @@ import { fold } from 'fp-ts/lib/Either'; import { pipe } from 'fp-ts/lib/pipeable'; -import type * as rt from 'io-ts'; +import * as rt from 'io-ts'; import { exactCheck, formatErrors } from '@kbn/securitysolution-io-ts-utils'; import type { RouteValidationFunction, diff --git a/x-pack/plugins/ecs_data_quality_dashboard/tsconfig.json b/x-pack/plugins/ecs_data_quality_dashboard/tsconfig.json index b5c1ad152b2321..c0603ef91df6b4 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/tsconfig.json +++ b/x-pack/plugins/ecs_data_quality_dashboard/tsconfig.json @@ -20,6 +20,8 @@ "@kbn/securitysolution-io-ts-utils", "@kbn/securitysolution-io-ts-types", "@kbn/i18n", + "@kbn/core-http-router-server-mocks", + "@kbn/logging-mocks", ], "exclude": [ "target/**/*", From 6d06dc3d2d2fd9440ce474c9f8fdfc45b720fc59 Mon Sep 17 00:00:00 2001 From: "Quynh Nguyen (Quinn)" <43350163+qn895@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:34:12 -0500 Subject: [PATCH 82/87] [ML] Fix data drift calculating inaccurate p value when range is not of uniform distribution (#168757) --- .../data_drift/data_drift_page.tsx | 1 - .../document_count_with_dual_brush.tsx | 2 +- .../data_drift/use_data_drift_result.ts | 80 ++++++++++++++++--- 3 files changed, 72 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/data_visualizer/public/application/data_drift/data_drift_page.tsx b/x-pack/plugins/data_visualizer/public/application/data_drift/data_drift_page.tsx index 2411c9096be70c..2c45fd37a6858d 100644 --- a/x-pack/plugins/data_visualizer/public/application/data_drift/data_drift_page.tsx +++ b/x-pack/plugins/data_visualizer/public/application/data_drift/data_drift_page.tsx @@ -359,7 +359,6 @@ export const DataDriftPage: FC = ({ initialSettings }) => { label={comparisonIndexPatternLabel} randomSampler={randomSamplerProd} reload={forceRefresh} - brushSelectionUpdateHandler={brushSelectionUpdate} documentCountStats={documentStatsProd.documentCountStats} documentCountStatsSplit={documentStatsProd.documentCountStatsCompare} isBrushCleared={isBrushCleared} diff --git a/x-pack/plugins/data_visualizer/public/application/data_drift/document_count_with_dual_brush.tsx b/x-pack/plugins/data_visualizer/public/application/data_drift/document_count_with_dual_brush.tsx index 0d83879c37486e..210d364ce7aa68 100644 --- a/x-pack/plugins/data_visualizer/public/application/data_drift/document_count_with_dual_brush.tsx +++ b/x-pack/plugins/data_visualizer/public/application/data_drift/document_count_with_dual_brush.tsx @@ -32,7 +32,7 @@ export interface DocumentCountContentProps | 'interval' | 'chartPointsSplitLabel' > { - brushSelectionUpdateHandler: BrushSelectionUpdateHandler; + brushSelectionUpdateHandler?: BrushSelectionUpdateHandler; documentCountStats?: DocumentCountStats; documentCountStatsSplit?: DocumentCountStats; documentCountStatsSplitLabel?: string; diff --git a/x-pack/plugins/data_visualizer/public/application/data_drift/use_data_drift_result.ts b/x-pack/plugins/data_visualizer/public/application/data_drift/use_data_drift_result.ts index 8b22e1d94db335..4588595ffcc4f3 100644 --- a/x-pack/plugins/data_visualizer/public/application/data_drift/use_data_drift_result.ts +++ b/x-pack/plugins/data_visualizer/public/application/data_drift/use_data_drift_result.ts @@ -29,6 +29,7 @@ import { isDefined } from '@kbn/ml-is-defined'; import { computeChi2PValue, type Histogram } from '@kbn/ml-chi2test'; import { mapAndFlattenFilters } from '@kbn/data-plugin/public'; +import type { AggregationsRangeBucketKeys } from '@elastic/elasticsearch/lib/api/types'; import { createMergedEsQuery } from '../index_data_visualizer/utils/saved_search_utils'; import { useDataVisualizerKibana } from '../kibana_context'; @@ -378,6 +379,7 @@ const fetchComparisonDriftedData = async ({ fields, baselineResponseAggs, baseRequest, + baselineRequest, randomSamplerWrapper, signal, }: { @@ -387,10 +389,19 @@ const fetchComparisonDriftedData = async ({ randomSamplerWrapper: RandomSamplerWrapper; signal: AbortSignal; baselineResponseAggs: object; + baselineRequest: EsRequestParams; }) => { const driftedRequest = { ...baseRequest }; + const driftedRequestAggs: Record = {}; + // Since aggregation is not able to split the values into distinct 5% intervals, + // this breaks our assumption of uniform distributed fractions in the`ks_test`. + // So, to fix this in the general case, we need to run an additional ranges agg to get the doc count for the ranges + // that we get from the percentiles aggregation + // and use it in the bucket_count_ks_test + const rangesRequestAggs: Record = {}; + for (const { field, type } of fields) { if ( isPopulatedObject(baselineResponseAggs, [`${field}_percentiles`]) && @@ -410,19 +421,16 @@ const fetchComparisonDriftedData = async ({ ranges.push({ from: percentiles[idx - 1], to: val }); } }); - // add range and bucket_count_ks_test to the request - driftedRequestAggs[`${field}_ranges`] = { + const rangeAggs = { range: { field, ranges, }, }; - driftedRequestAggs[`${field}_ks_test`] = { - bucket_count_ks_test: { - buckets_path: `${field}_ranges>_count`, - alternative: ['two_sided'], - }, - }; + // add range and bucket_count_ks_test to the request + rangesRequestAggs[`${field}_ranges`] = rangeAggs; + driftedRequestAggs[`${field}_ranges`] = rangeAggs; + // add stats aggregation to the request driftedRequestAggs[`${field}_stats`] = { stats: { @@ -441,6 +449,48 @@ const fetchComparisonDriftedData = async ({ } } + // Compute fractions based on results of ranges + const rangesResp = await dataSearch( + { + ...baselineRequest, + body: { ...baselineRequest.body, aggs: randomSamplerWrapper.wrap(rangesRequestAggs) }, + }, + signal + ); + + const fieldsWithNoOverlap = new Set(); + for (const { field } of fields) { + if (rangesResp.aggregations[`${field}_ranges`]) { + const buckets = rangesResp.aggregations[`${field}_ranges`] + .buckets as AggregationsRangeBucketKeys[]; + + if (buckets) { + const totalSumOfAllBuckets = buckets.reduce((acc, bucket) => acc + bucket.doc_count, 0); + + const fractions = buckets.map((bucket) => ({ + ...bucket, + fraction: bucket.doc_count / totalSumOfAllBuckets, + })); + + if (totalSumOfAllBuckets > 0) { + driftedRequestAggs[`${field}_ks_test`] = { + bucket_count_ks_test: { + buckets_path: `${field}_ranges>_count`, + alternative: ['two_sided'], + ...(totalSumOfAllBuckets > 0 + ? { fractions: fractions.map((bucket) => Number(bucket.fraction.toFixed(3))) } + : {}), + }, + }; + } else { + // If all doc_counts are 0, that means there's no overlap whatsoever + // in which case we don't need to make the ks test agg, because it defaults to astronomically small value + fieldsWithNoOverlap.add(field); + } + } + } + } + const driftedResp = await dataSearch( { ...driftedRequest, @@ -448,6 +498,17 @@ const fetchComparisonDriftedData = async ({ }, signal ); + + fieldsWithNoOverlap.forEach((field) => { + if (driftedResp.aggregations) { + driftedResp.aggregations[`${field}_ks_test`] = { + // Setting -Infinity to represent astronomically small number + // which would be represented as < 0.000001 in table + two_sided: -Infinity, + }; + } + }); + return driftedResp; }; @@ -678,7 +739,7 @@ export const useFetchDataComparisonResult = ( setResult({ data: undefined, status: FETCH_STATUS.LOADING, error: undefined }); - // Place holder for when there might be difference data views in the future + // Placeholder for when there might be difference data views in the future const referenceIndex = initialSettings ? initialSettings.reference : currentDataView?.getIndexPattern(); @@ -802,6 +863,7 @@ export const useFetchDataComparisonResult = ( fetchComparisonDriftedData({ dataSearch, baseRequest: driftedRequest, + baselineRequest, baselineResponseAggs, fields: chunkedFields, randomSamplerWrapper: prodRandomSamplerWrapper, From bc36c699d4967f3e55b920cc6999c7037a879047 Mon Sep 17 00:00:00 2001 From: Robert Austin Date: Tue, 17 Oct 2023 15:52:30 -0400 Subject: [PATCH 83/87] Move Security's codegen step into the checks command as it has a short runtime (#168260) ## Summary Security runs a code generator script on PRs. It only takes a few seconds. This change moves it to the 'checks' command. This will save on build agents. ### 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: Jon --- .buildkite/pipelines/pull_request/base.yml | 7 ------- .buildkite/scripts/steps/checks.sh | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.buildkite/pipelines/pull_request/base.yml b/.buildkite/pipelines/pull_request/base.yml index abc6436e7ee0a8..6437742d31c15e 100644 --- a/.buildkite/pipelines/pull_request/base.yml +++ b/.buildkite/pipelines/pull_request/base.yml @@ -212,13 +212,6 @@ steps: automatic: false soft_fail: true - - command: .buildkite/scripts/steps/code_generation/security_solution_codegen.sh - label: 'Security Solution OpenAPI codegen' - agents: - queue: n2-2-spot - timeout_in_minutes: 60 - parallelism: 1 - - command: .buildkite/scripts/steps/functional/osquery_cypress_burn.sh label: 'Osquery Cypress Tests, burning changed specs' agents: diff --git a/.buildkite/scripts/steps/checks.sh b/.buildkite/scripts/steps/checks.sh index 12077902c1c13d..c2758eb52c7385 100755 --- a/.buildkite/scripts/steps/checks.sh +++ b/.buildkite/scripts/steps/checks.sh @@ -22,3 +22,4 @@ export DISABLE_BOOTSTRAP_VALIDATION=false .buildkite/scripts/steps/checks/test_hardening.sh .buildkite/scripts/steps/checks/ftr_configs.sh .buildkite/scripts/steps/checks/saved_objects_compat_changes.sh +.buildkite/scripts/steps/code_generation/security_solution_codegen.sh From c369545439774c3a4405fd16bc72209b6952c082 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 17 Oct 2023 16:03:27 -0400 Subject: [PATCH 84/87] [Fleet] Fix integration sticky column after EUI upgrade (#169111) --- .../epm/components/package_list_grid/controls.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/controls.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/controls.tsx index cb5c61ff57a143..c50d396c143f85 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/controls.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid/controls.tsx @@ -6,6 +6,7 @@ */ import React, { type ReactNode } from 'react'; +import styled from 'styled-components'; import { EuiFlexGroup, EuiSpacer, EuiTitle } from '@elastic/eui'; @@ -14,6 +15,10 @@ interface ControlsColumnProps { title: string | undefined; } +const FlexGroupWithMaxHeight = styled(EuiFlexGroup)` + max-height: calc(100vh - 120px); +`; + export const ControlsColumn = ({ controls, title }: ControlsColumnProps) => { let titleContent; if (title) { @@ -27,9 +32,9 @@ export const ControlsColumn = ({ controls, title }: ControlsColumnProps) => { ); } return ( - + {titleContent} {controls} - + ); }; From bdf064e075b1d393ae3a7168b14b50d182868ab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Tue, 17 Oct 2023 22:37:56 +0200 Subject: [PATCH 85/87] [Remote clusters] Fix empty states (#169015) ## Summary I noticed that Remote clusters UI has a wrapper on empty states which is probably a regression from the EuiPage deprecations migration. This PR fixes the list and edit views. See screenshots below.

#### List empty state Before Screenshot 2023-10-16 at 19 27 12 After Screenshot 2023-10-16 at 19 42 24 #### List error Before Screenshot 2023-10-16 at 19 34 07 After Screenshot 2023-10-16 at 19 45 18 #### List error permissions Before Screenshot 2023-10-16 at 19 27 50 After Screenshot 2023-10-16 at 19 44 14 #### List loading Before Screenshot 2023-10-16 at 20 08 54 After Screenshot 2023-10-16 at 20 10 18 #### Edit form error Before Screenshot 2023-10-16 at 19 59 54 After Screenshot 2023-10-16 at 20 03 59 #### Edit form loading Before Screenshot 2023-10-16 at 20 00 34 After Screenshot 2023-10-16 at 20 03 41
--- .../section_loading/section_loading.tsx | 17 +- .../remote_cluster_edit.js | 140 ++++++------- .../remote_cluster_list.js | 198 ++++++++---------- 3 files changed, 173 insertions(+), 182 deletions(-) diff --git a/src/plugins/es_ui_shared/public/components/section_loading/section_loading.tsx b/src/plugins/es_ui_shared/public/components/section_loading/section_loading.tsx index 119e053312dc85..cbdaf444ca228f 100644 --- a/src/plugins/es_ui_shared/public/components/section_loading/section_loading.tsx +++ b/src/plugins/es_ui_shared/public/components/section_loading/section_loading.tsx @@ -15,13 +15,24 @@ import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; interface Props { inline?: boolean; children: React.ReactNode; + 'data-test-subj'?: string; [key: string]: any; } -export const SectionLoading: React.FunctionComponent = ({ inline, children, ...rest }) => { +export const SectionLoading: React.FunctionComponent = ({ + inline, + 'data-test-subj': dataTestSubj, + children, + ...rest +}) => { if (inline) { return ( - + @@ -38,7 +49,7 @@ export const SectionLoading: React.FunctionComponent = ({ inline, childre } body={{children}} - data-test-subj="sectionLoading" + data-test-subj={dataTestSubj ?? 'sectionLoading'} /> ); }; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js index 02ae9743806834..04daad5dee8fc3 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js @@ -96,55 +96,51 @@ export class RemoteClusterEdit extends Component { if (isLoading) { return ( - - - - - + + + ); } if (!cluster) { return ( - - - - - } - body={ -

- -

- } - actions={ - - - - } - /> -
+ + + + } + body={ +

+ +

+ } + actions={ + + + + } + /> ); } @@ -152,36 +148,34 @@ export class RemoteClusterEdit extends Component { if (isConfiguredByNode) { return ( - - - - - } - body={ -

- + + + } + body={ +

+ -

- } - actions={ - - - - } - /> -
+ /> +

+ } + actions={ + + + + } + /> ); } diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js index 06948e25a05838..21ed52d08fa83c 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js @@ -93,28 +93,26 @@ export class RemoteClusterList extends Component { renderNoPermission() { return ( - - - - - } - body={ -

- -

- } - /> -
+ + + + } + body={ +

+ +

+ } + /> ); } @@ -124,103 +122,91 @@ export class RemoteClusterList extends Component { const { statusCode, error: errorString } = error.body; return ( - - - - - } - body={ -

- {statusCode} {errorString} -

- } - /> -
+ + + + } + body={ +

+ {statusCode} {errorString} +

+ } + /> ); } renderEmpty() { return ( - - - - - } - body={ -

- + + + } + body={ +

+ -

- } - actions={ - - - - } - footer={ - <> - - - - - {' '} - + /> +

+ } + actions={ + + + + } + footer={ + <> + + -
- - } - /> -
+ + {' '} + + + + + } + /> ); } renderLoading() { return ( - - - - - + + + ); } From 2932b77eec59bcb923814009d2904070f401e4de Mon Sep 17 00:00:00 2001 From: Jon Date: Tue, 17 Oct 2023 15:57:36 -0500 Subject: [PATCH 86/87] Fix storybooks (#169167) https://buildkite.com/elastic/kibana-on-merge/builds/36947#018b3ee2-2f5a-4a69-9d88-8f074cd1b4fa/229-1431 Uses the fix found by mistic at https://github.com/elastic/kibana/pull/168043 --- .../connector_selector_inline/action_type_selector_modal.tsx | 2 +- .../security_solution/public/assistant/get_comments/index.tsx | 2 +- .../right/components/session_preview_container.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/action_type_selector_modal.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/action_type_selector_modal.tsx index 6184525877d1ca..02db4bf391c143 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/action_type_selector_modal.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/connector_selector_inline/action_type_selector_modal.tsx @@ -18,7 +18,7 @@ import { } from '@elastic/eui'; import { ActionType } from '@kbn/actions-plugin/common'; import { ActionTypeRegistryContract } from '@kbn/triggers-actions-ui-plugin/public'; -import { css } from '@emotion/css/dist/emotion-css.cjs'; +import { css } from '@emotion/css'; import * as i18n from '../translations'; interface Props { diff --git a/x-pack/plugins/security_solution/public/assistant/get_comments/index.tsx b/x-pack/plugins/security_solution/public/assistant/get_comments/index.tsx index d91caae855d22c..b87de5bc648748 100644 --- a/x-pack/plugins/security_solution/public/assistant/get_comments/index.tsx +++ b/x-pack/plugins/security_solution/public/assistant/get_comments/index.tsx @@ -11,7 +11,7 @@ import { EuiAvatar, EuiMarkdownFormat, EuiText, tint } from '@elastic/eui'; import React from 'react'; import { AssistantAvatar } from '@kbn/elastic-assistant'; -import { css } from '@emotion/react/dist/emotion-react.cjs'; +import { css } from '@emotion/react'; import { euiThemeVars } from '@kbn/ui-theme'; import { CommentActions } from '../comment_actions'; import * as i18n from './translations'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/session_preview_container.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/session_preview_container.tsx index 101c067ad661d0..10250e74c383c9 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/session_preview_container.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/session_preview_container.tsx @@ -10,7 +10,7 @@ import { TimelineTabs } from '@kbn/securitysolution-data-table'; import { useDispatch } from 'react-redux'; import { EuiLink, useEuiTheme } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { css } from '@emotion/css/dist/emotion-css.cjs'; +import { css } from '@emotion/css'; import { useLicense } from '../../../../common/hooks/use_license'; import { SessionPreview } from './session_preview'; import { useSessionPreview } from '../hooks/use_session_preview'; From befbe10fd37afb3c2dbc7382c75d155a2165d5ff Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 17 Oct 2023 15:58:58 -0600 Subject: [PATCH 87/87] [SLO] Add timeslice metric indicator (#168539) ## Summary This PR adds the new Timeslice Metric indicator for SLOs. Due to the nature of these statistical aggregations, this indicator requires the budgeting method to be set to `timeslices`; we ignore the timeslice threshold in favor of the threshold set in the metric definition. Users can create SLOs based on the following aggregations: - Average - Min - Max - Sum - Cardinality - Percentile - Document count - Std. Deviation - Last Value Other notable feature include: - The ability to define an equation which supports basic math and logic - Users can define a threshold based on the equation for good slices vs bad slices image ### Counter Metric Example image CC: @lucasmoore --------- Co-authored-by: Kevin Delemme --- .../kbn-slo-schema/src/rest_specs/slo.ts | 12 + .../kbn-slo-schema/src/schema/indicators.ts | 88 ++- .../docs/openapi/slo/bundled.json | 216 +++++- .../docs/openapi/slo/bundled.yaml | 160 ++++ .../schemas/create_slo_request.yaml | 1 + ...indicator_properties_timeslice_metric.yaml | 64 ++ .../slo/components/schemas/slo_response.yaml | 6 +- ...eslice_metric_basic_metric_with_field.yaml | 25 + .../timeslice_metric_doc_count_metric.yaml | 21 + .../timeslice_metric_percentile_metric.yaml | 30 + .../schemas/update_slo_request.yaml | 1 + .../components/overview/overview.tsx | 30 +- .../components/common/data_preview_chart.tsx | 90 ++- .../custom_metric/metric_indicator.tsx | 4 +- .../slo_edit_form_indicator_section.tsx | 3 + .../slo_edit_form_objective_section.tsx | 17 + ...edit_form_objective_section_timeslices.tsx | 4 +- .../timeslice_metric/metric_indicator.tsx | 303 ++++++++ .../timeslice_metric/metric_input.tsx | 263 +++++++ .../timeslice_metric_indicator.tsx | 163 ++++ .../public/pages/slo_edit/constants.ts | 75 ++ .../slo_edit/helpers/aggregation_options.ts | 84 +++ .../helpers/process_slo_form_values.ts | 6 + .../hooks/use_section_form_validation.ts | 40 +- .../slo_edit/hooks/use_unregister_fields.ts | 18 + .../observability/public/utils/slo/labels.ts | 10 + .../observability/server/routes/slo/route.ts | 2 + ..._metric_indicator_aggregation.test.ts.snap | 213 ++++++ ...get_custom_metric_indicator_aggregation.ts | 2 +- ...slice_metric_indicator_aggregation.test.ts | 108 +++ ..._timeslice_metric_indicator_aggregation.ts | 130 ++++ .../server/services/slo/aggregations/index.ts | 1 + .../server/services/slo/fixtures/slo.ts | 27 +- .../server/services/slo/get_preview_data.ts | 45 ++ .../timeslice_metric.test.ts.snap | 697 ++++++++++++++++++ .../slo/transform_generators/index.ts | 1 + .../timeslice_metric.test.ts | 178 +++++ .../transform_generators/timeslice_metric.ts | 116 +++ 38 files changed, 3225 insertions(+), 29 deletions(-) create mode 100644 x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_timeslice_metric.yaml create mode 100644 x-pack/plugins/observability/docs/openapi/slo/components/schemas/timeslice_metric_basic_metric_with_field.yaml create mode 100644 x-pack/plugins/observability/docs/openapi/slo/components/schemas/timeslice_metric_doc_count_metric.yaml create mode 100644 x-pack/plugins/observability/docs/openapi/slo/components/schemas/timeslice_metric_percentile_metric.yaml create mode 100644 x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/metric_indicator.tsx create mode 100644 x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/metric_input.tsx create mode 100644 x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/timeslice_metric_indicator.tsx create mode 100644 x-pack/plugins/observability/public/pages/slo_edit/helpers/aggregation_options.ts create mode 100644 x-pack/plugins/observability/server/services/slo/aggregations/__snapshots__/get_timeslice_metric_indicator_aggregation.test.ts.snap create mode 100644 x-pack/plugins/observability/server/services/slo/aggregations/get_timeslice_metric_indicator_aggregation.test.ts create mode 100644 x-pack/plugins/observability/server/services/slo/aggregations/get_timeslice_metric_indicator_aggregation.ts create mode 100644 x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/timeslice_metric.test.ts.snap create mode 100644 x-pack/plugins/observability/server/services/slo/transform_generators/timeslice_metric.test.ts create mode 100644 x-pack/plugins/observability/server/services/slo/transform_generators/timeslice_metric.ts 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 706213003250bb..155fea1aeb6d04 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 @@ -19,6 +19,7 @@ import { indicatorTypesSchema, kqlCustomIndicatorSchema, metricCustomIndicatorSchema, + timesliceMetricIndicatorSchema, objectiveSchema, optionalSettingsSchema, previewDataSchema, @@ -28,6 +29,9 @@ import { tagsSchema, timeWindowSchema, timeWindowTypeSchema, + timesliceMetricBasicMetricWithField, + timesliceMetricDocCountMetric, + timesliceMetricPercentileMetric, } from '../schema'; const createSLOParamsSchema = t.type({ @@ -270,6 +274,10 @@ type Indicator = t.OutputOf; type APMTransactionErrorRateIndicator = t.OutputOf; type APMTransactionDurationIndicator = t.OutputOf; type MetricCustomIndicator = t.OutputOf; +type TimesliceMetricIndicator = t.OutputOf; +type TimesliceMetricBasicMetricWithField = t.OutputOf; +type TimesliceMetricDocCountMetric = t.OutputOf; +type TimesclieMetricPercentileMetric = t.OutputOf; type HistogramIndicator = t.OutputOf; type KQLCustomIndicator = t.OutputOf; @@ -327,6 +335,10 @@ export type { IndicatorType, Indicator, MetricCustomIndicator, + TimesliceMetricIndicator, + TimesliceMetricBasicMetricWithField, + TimesclieMetricPercentileMetric, + TimesliceMetricDocCountMetric, HistogramIndicator, KQLCustomIndicator, TimeWindow, diff --git a/x-pack/packages/kbn-slo-schema/src/schema/indicators.ts b/x-pack/packages/kbn-slo-schema/src/schema/indicators.ts index 07b9c69f4fb974..f8d795275acc66 100644 --- a/x-pack/packages/kbn-slo-schema/src/schema/indicators.ts +++ b/x-pack/packages/kbn-slo-schema/src/schema/indicators.ts @@ -59,6 +59,83 @@ const kqlCustomIndicatorSchema = t.type({ ]), }); +const timesliceMetricComparatorMapping = { + GT: '>', + GTE: '>=', + LT: '<', + LTE: '<=', +}; + +const timesliceMetricComparator = t.keyof(timesliceMetricComparatorMapping); + +const timesliceMetricBasicMetricWithField = t.intersection([ + t.type({ + name: t.string, + aggregation: t.keyof({ + avg: true, + max: true, + min: true, + sum: true, + cardinality: true, + last_value: true, + std_deviation: true, + }), + field: t.string, + }), + t.partial({ + filter: t.string, + }), +]); + +const timesliceMetricDocCountMetric = t.intersection([ + t.type({ + name: t.string, + aggregation: t.literal('doc_count'), + }), + t.partial({ + filter: t.string, + }), +]); + +const timesliceMetricPercentileMetric = t.intersection([ + t.type({ + name: t.string, + aggregation: t.literal('percentile'), + field: t.string, + percentile: t.number, + }), + t.partial({ + filter: t.string, + }), +]); + +const timesliceMetricMetricDef = t.union([ + timesliceMetricBasicMetricWithField, + timesliceMetricDocCountMetric, + timesliceMetricPercentileMetric, +]); + +const timesliceMetricDef = t.type({ + metrics: t.array(timesliceMetricMetricDef), + equation: t.string, + threshold: t.number, + comparator: timesliceMetricComparator, +}); +const timesliceMetricIndicatorTypeSchema = t.literal('sli.metric.timeslice'); +const timesliceMetricIndicatorSchema = t.type({ + type: timesliceMetricIndicatorTypeSchema, + params: t.intersection([ + t.type({ + index: t.string, + metric: timesliceMetricDef, + timestampField: t.string, + }), + t.partial({ + filter: t.string, + }), + ]), +}); + const metricCustomValidAggregations = t.keyof({ sum: true, }); @@ -149,6 +226,7 @@ const indicatorTypesSchema = t.union([ apmTransactionErrorRateIndicatorTypeSchema, kqlCustomIndicatorTypeSchema, metricCustomIndicatorTypeSchema, + timesliceMetricIndicatorTypeSchema, histogramIndicatorTypeSchema, ]); @@ -176,6 +254,7 @@ const indicatorSchema = t.union([ apmTransactionErrorRateIndicatorSchema, kqlCustomIndicatorSchema, metricCustomIndicatorSchema, + timesliceMetricIndicatorSchema, histogramIndicatorSchema, ]); @@ -186,8 +265,15 @@ export { apmTransactionErrorRateIndicatorTypeSchema, kqlCustomIndicatorSchema, kqlCustomIndicatorTypeSchema, - metricCustomIndicatorTypeSchema, metricCustomIndicatorSchema, + metricCustomIndicatorTypeSchema, + timesliceMetricComparatorMapping, + timesliceMetricIndicatorSchema, + timesliceMetricIndicatorTypeSchema, + timesliceMetricMetricDef, + timesliceMetricBasicMetricWithField, + timesliceMetricDocCountMetric, + timesliceMetricPercentileMetric, histogramIndicatorTypeSchema, histogramIndicatorSchema, indicatorSchema, diff --git a/x-pack/plugins/observability/docs/openapi/slo/bundled.json b/x-pack/plugins/observability/docs/openapi/slo/bundled.json index 3ba6ab7762e93a..b4f52b032a9fcb 100644 --- a/x-pack/plugins/observability/docs/openapi/slo/bundled.json +++ b/x-pack/plugins/observability/docs/openapi/slo/bundled.json @@ -1240,6 +1240,210 @@ } } }, + "timeslice_metric_basic_metric_with_field": { + "title": "Timeslice Metric Basic Metric with Field", + "required": [ + "name", + "aggregation", + "field" + ], + "type": "object", + "properties": { + "name": { + "description": "The name of the metric. Only valid options are A-Z", + "type": "string", + "example": "A", + "pattern": "^[A-Z]$" + }, + "aggregation": { + "description": "The aggregation type of the metric.", + "type": "string", + "example": "sum", + "enum": [ + "sum", + "avg", + "min", + "max", + "std_deviation", + "last_value", + "cardinality" + ] + }, + "field": { + "description": "The field of the metric.", + "type": "string", + "example": "processor.processed" + }, + "filter": { + "description": "The filter to apply to the metric.", + "type": "string", + "example": "processor.outcome: \"success\"" + } + } + }, + "timeslice_metric_percentile_metric": { + "title": "Timeslice Metric Percentile Metric", + "required": [ + "name", + "aggregation", + "field", + "percentile" + ], + "type": "object", + "properties": { + "name": { + "description": "The name of the metric. Only valid options are A-Z", + "type": "string", + "example": "A", + "pattern": "^[A-Z]$" + }, + "aggregation": { + "description": "The aggregation type of the metric. Only valid option is \"percentile\"", + "type": "string", + "example": "percentile", + "enum": [ + "percentile" + ] + }, + "field": { + "description": "The field of the metric.", + "type": "string", + "example": "processor.processed" + }, + "percentile": { + "description": "The percentile value.", + "type": "number", + "example": 95 + }, + "filter": { + "description": "The filter to apply to the metric.", + "type": "string", + "example": "processor.outcome: \"success\"" + } + } + }, + "timeslice_metric_doc_count_metric": { + "title": "Timeslice Metric Doc Count Metric", + "required": [ + "name", + "aggregation" + ], + "type": "object", + "properties": { + "name": { + "description": "The name of the metric. Only valid options are A-Z", + "type": "string", + "example": "A", + "pattern": "^[A-Z]$" + }, + "aggregation": { + "description": "The aggregation type of the metric. Only valid option is \"doc_count\"", + "type": "string", + "example": "doc_count", + "enum": [ + "doc_count" + ] + }, + "filter": { + "description": "The filter to apply to the metric.", + "type": "string", + "example": "processor.outcome: \"success\"" + } + } + }, + "indicator_properties_timeslice_metric": { + "title": "Timeslice metric", + "required": [ + "type", + "params" + ], + "description": "Defines properties for a timeslice metric indicator type", + "type": "object", + "properties": { + "params": { + "description": "An object containing the indicator parameters.", + "type": "object", + "nullable": false, + "required": [ + "index", + "timestampField", + "metric" + ], + "properties": { + "index": { + "description": "The index or index pattern to use", + "type": "string", + "example": "my-service-*" + }, + "filter": { + "description": "the KQL query to filter the documents with.", + "type": "string", + "example": "field.environment : \"production\" and service.name : \"my-service\"" + }, + "timestampField": { + "description": "The timestamp field used in the source indice.\n", + "type": "string", + "example": "timestamp" + }, + "metric": { + "description": "An object defining the metrics, equation, and threshold to determine if it's a good slice or not\n", + "type": "object", + "required": [ + "metrics", + "equation", + "comparator", + "threshold" + ], + "properties": { + "metrics": { + "description": "List of metrics with their name, aggregation type, and field.", + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/timeslice_metric_basic_metric_with_field" + }, + { + "$ref": "#/components/schemas/timeslice_metric_percentile_metric" + }, + { + "$ref": "#/components/schemas/timeslice_metric_doc_count_metric" + } + ] + } + }, + "equation": { + "description": "The equation to calculate the metric.", + "type": "string", + "example": "A" + }, + "comparator": { + "description": "The comparator to use to compare the equation to the threshold.", + "type": "string", + "example": "GT", + "enum": [ + "GT", + "GTE", + "LT", + "LTE" + ] + }, + "threshold": { + "description": "The threshold used to determine if the metric is a good slice or not.", + "type": "number", + "example": 100 + } + } + } + } + }, + "type": { + "description": "The type of indicator.", + "type": "string", + "example": "sli.metric.timeslice" + } + } + }, "time_window": { "title": "Time window", "required": [ @@ -1427,7 +1631,8 @@ "sli.kql.custom": "#/components/schemas/indicator_properties_custom_kql", "sli.apm.transactionDuration": "#/components/schemas/indicator_properties_apm_latency", "sli.metric.custom": "#/components/schemas/indicator_properties_custom_metric", - "sli.histogram.custom": "#/components/schemas/indicator_properties_histogram" + "sli.histogram.custom": "#/components/schemas/indicator_properties_histogram", + "sli.metric.timeslice": "#/components/schemas/indicator_properties_timeslice_metric" } }, "oneOf": [ @@ -1445,6 +1650,9 @@ }, { "$ref": "#/components/schemas/indicator_properties_histogram" + }, + { + "$ref": "#/components/schemas/indicator_properties_timeslice_metric" } ] }, @@ -1661,6 +1869,9 @@ }, { "$ref": "#/components/schemas/indicator_properties_histogram" + }, + { + "$ref": "#/components/schemas/indicator_properties_timeslice_metric" } ] }, @@ -1755,6 +1966,9 @@ }, { "$ref": "#/components/schemas/indicator_properties_histogram" + }, + { + "$ref": "#/components/schemas/indicator_properties_timeslice_metric" } ] }, diff --git a/x-pack/plugins/observability/docs/openapi/slo/bundled.yaml b/x-pack/plugins/observability/docs/openapi/slo/bundled.yaml index c50403e5096f87..8efdbd9dfe2c2e 100644 --- a/x-pack/plugins/observability/docs/openapi/slo/bundled.yaml +++ b/x-pack/plugins/observability/docs/openapi/slo/bundled.yaml @@ -837,6 +837,162 @@ components: description: The type of indicator. type: string example: sli.histogram.custom + timeslice_metric_basic_metric_with_field: + title: Timeslice Metric Basic Metric with Field + required: + - name + - aggregation + - field + type: object + properties: + name: + description: The name of the metric. Only valid options are A-Z + type: string + example: A + pattern: ^[A-Z]$ + aggregation: + description: The aggregation type of the metric. + type: string + example: sum + enum: + - sum + - avg + - min + - max + - std_deviation + - last_value + - cardinality + field: + description: The field of the metric. + type: string + example: processor.processed + filter: + description: The filter to apply to the metric. + type: string + example: 'processor.outcome: "success"' + timeslice_metric_percentile_metric: + title: Timeslice Metric Percentile Metric + required: + - name + - aggregation + - field + - percentile + type: object + properties: + name: + description: The name of the metric. Only valid options are A-Z + type: string + example: A + pattern: ^[A-Z]$ + aggregation: + description: The aggregation type of the metric. Only valid option is "percentile" + type: string + example: percentile + enum: + - percentile + field: + description: The field of the metric. + type: string + example: processor.processed + percentile: + description: The percentile value. + type: number + example: 95 + filter: + description: The filter to apply to the metric. + type: string + example: 'processor.outcome: "success"' + timeslice_metric_doc_count_metric: + title: Timeslice Metric Doc Count Metric + required: + - name + - aggregation + type: object + properties: + name: + description: The name of the metric. Only valid options are A-Z + type: string + example: A + pattern: ^[A-Z]$ + aggregation: + description: The aggregation type of the metric. Only valid option is "doc_count" + type: string + example: doc_count + enum: + - doc_count + filter: + description: The filter to apply to the metric. + type: string + example: 'processor.outcome: "success"' + indicator_properties_timeslice_metric: + title: Timeslice metric + required: + - type + - params + description: Defines properties for a timeslice metric indicator type + type: object + properties: + params: + description: An object containing the indicator parameters. + type: object + nullable: false + required: + - index + - timestampField + - metric + properties: + index: + description: The index or index pattern to use + type: string + example: my-service-* + filter: + description: the KQL query to filter the documents with. + type: string + example: 'field.environment : "production" and service.name : "my-service"' + timestampField: + description: | + The timestamp field used in the source indice. + type: string + example: timestamp + metric: + description: | + An object defining the metrics, equation, and threshold to determine if it's a good slice or not + type: object + required: + - metrics + - equation + - comparator + - threshold + properties: + metrics: + description: List of metrics with their name, aggregation type, and field. + type: array + items: + anyOf: + - $ref: '#/components/schemas/timeslice_metric_basic_metric_with_field' + - $ref: '#/components/schemas/timeslice_metric_percentile_metric' + - $ref: '#/components/schemas/timeslice_metric_doc_count_metric' + equation: + description: The equation to calculate the metric. + type: string + example: A + comparator: + description: The comparator to use to compare the equation to the threshold. + type: string + example: GT + enum: + - GT + - GTE + - LT + - LTE + threshold: + description: The threshold used to determine if the metric is a good slice or not. + type: number + example: 100 + type: + description: The type of indicator. + type: string + example: sli.metric.timeslice time_window: title: Time window required: @@ -988,12 +1144,14 @@ components: sli.apm.transactionDuration: '#/components/schemas/indicator_properties_apm_latency' sli.metric.custom: '#/components/schemas/indicator_properties_custom_metric' sli.histogram.custom: '#/components/schemas/indicator_properties_histogram' + sli.metric.timeslice: '#/components/schemas/indicator_properties_timeslice_metric' oneOf: - $ref: '#/components/schemas/indicator_properties_custom_kql' - $ref: '#/components/schemas/indicator_properties_apm_availability' - $ref: '#/components/schemas/indicator_properties_apm_latency' - $ref: '#/components/schemas/indicator_properties_custom_metric' - $ref: '#/components/schemas/indicator_properties_histogram' + - $ref: '#/components/schemas/indicator_properties_timeslice_metric' timeWindow: $ref: '#/components/schemas/time_window' budgetingMethod: @@ -1150,6 +1308,7 @@ components: - $ref: '#/components/schemas/indicator_properties_apm_latency' - $ref: '#/components/schemas/indicator_properties_custom_metric' - $ref: '#/components/schemas/indicator_properties_histogram' + - $ref: '#/components/schemas/indicator_properties_timeslice_metric' timeWindow: $ref: '#/components/schemas/time_window' budgetingMethod: @@ -1212,6 +1371,7 @@ components: - $ref: '#/components/schemas/indicator_properties_apm_latency' - $ref: '#/components/schemas/indicator_properties_custom_metric' - $ref: '#/components/schemas/indicator_properties_histogram' + - $ref: '#/components/schemas/indicator_properties_timeslice_metric' timeWindow: $ref: '#/components/schemas/time_window' budgetingMethod: diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/create_slo_request.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/create_slo_request.yaml index f14a1a134abd8d..c3a848fe521333 100644 --- a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/create_slo_request.yaml +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/create_slo_request.yaml @@ -27,6 +27,7 @@ properties: - $ref: "indicator_properties_apm_latency.yaml" - $ref: "indicator_properties_custom_metric.yaml" - $ref: 'indicator_properties_histogram.yaml' + - $ref: 'indicator_properties_timeslice_metric.yaml' timeWindow: $ref: "time_window.yaml" budgetingMethod: diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_timeslice_metric.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_timeslice_metric.yaml new file mode 100644 index 00000000000000..712420f059fdd3 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/indicator_properties_timeslice_metric.yaml @@ -0,0 +1,64 @@ +title: Timeslice metric +required: + - type + - params +description: Defines properties for a timeslice metric indicator type +type: object +properties: + params: + description: An object containing the indicator parameters. + type: object + nullable: false + required: + - index + - timestampField + - metric + properties: + index: + description: The index or index pattern to use + type: string + example: my-service-* + filter: + description: the KQL query to filter the documents with. + type: string + example: 'field.environment : "production" and service.name : "my-service"' + timestampField: + description: > + The timestamp field used in the source indice. + type: string + example: timestamp + metric: + description: > + An object defining the metrics, equation, and threshold to determine if it's a good slice or not + type: object + required: + - metrics + - equation + - comparator + - threshold + properties: + metrics: + description: List of metrics with their name, aggregation type, and field. + type: array + items: + anyOf: + - $ref: './timeslice_metric_basic_metric_with_field.yaml' + - $ref: './timeslice_metric_percentile_metric.yaml' + - $ref: './timeslice_metric_doc_count_metric.yaml' + equation: + description: The equation to calculate the metric. + type: string + example: A + comparator: + description: The comparator to use to compare the equation to the threshold. + type: string + example: GT + enum: [GT, GTE, LT, LTE] + threshold: + description: The threshold used to determine if the metric is a good slice or not. + type: number + example: 100 + type: + description: The type of indicator. + type: string + example: sli.metric.timeslice diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/slo_response.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/slo_response.yaml index da81009bc20b3f..bd58e88c7b641f 100644 --- a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/slo_response.yaml +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/slo_response.yaml @@ -37,14 +37,16 @@ properties: sli.apm.transactionErrorRate: './indicator_properties_apm_availability.yaml' sli.kql.custom: './indicator_properties_custom_kql.yaml' sli.apm.transactionDuration: './indicator_properties_apm_latency.yaml' - sli.metric.custom: 'indicator_properties_custom_metric.yaml' - sli.histogram.custom: 'indicator_properties_histogram.yaml' + sli.metric.custom: './indicator_properties_custom_metric.yaml' + sli.histogram.custom: './indicator_properties_histogram.yaml' + sli.metric.timeslice: './indicator_properties_timeslice_metric.yaml' oneOf: - $ref: "indicator_properties_custom_kql.yaml" - $ref: "indicator_properties_apm_availability.yaml" - $ref: "indicator_properties_apm_latency.yaml" - $ref: "indicator_properties_custom_metric.yaml" - $ref: "indicator_properties_histogram.yaml" + - $ref: "indicator_properties_timeslice_metric.yaml" timeWindow: $ref: "time_window.yaml" budgetingMethod: diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/timeslice_metric_basic_metric_with_field.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/timeslice_metric_basic_metric_with_field.yaml new file mode 100644 index 00000000000000..570f4b4dda9052 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/timeslice_metric_basic_metric_with_field.yaml @@ -0,0 +1,25 @@ +title: Timeslice Metric Basic Metric with Field +required: + - name + - aggregation + - field +type: object +properties: + name: + description: The name of the metric. Only valid options are A-Z + type: string + example: A + pattern: "^[A-Z]$" + aggregation: + description: The aggregation type of the metric. + type: string + example: sum + enum: [sum, avg, min, max, std_deviation, last_value, cardinality] + field: + description: The field of the metric. + type: string + example: processor.processed + filter: + description: The filter to apply to the metric. + type: string + example: 'processor.outcome: "success"' diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/timeslice_metric_doc_count_metric.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/timeslice_metric_doc_count_metric.yaml new file mode 100644 index 00000000000000..76417fd111975a --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/timeslice_metric_doc_count_metric.yaml @@ -0,0 +1,21 @@ +title: Timeslice Metric Doc Count Metric +required: + - name + - aggregation +type: object +properties: + name: + description: The name of the metric. Only valid options are A-Z + type: string + example: A + pattern: "^[A-Z]$" + aggregation: + description: The aggregation type of the metric. Only valid option is "doc_count" + type: string + example: doc_count + enum: [doc_count] + filter: + description: The filter to apply to the metric. + type: string + example: 'processor.outcome: "success"' + diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/timeslice_metric_percentile_metric.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/timeslice_metric_percentile_metric.yaml new file mode 100644 index 00000000000000..c55b7e1c5abb81 --- /dev/null +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/timeslice_metric_percentile_metric.yaml @@ -0,0 +1,30 @@ +title: Timeslice Metric Percentile Metric +required: + - name + - aggregation + - field + - percentile +type: object +properties: + name: + description: The name of the metric. Only valid options are A-Z + type: string + example: A + pattern: "^[A-Z]$" + aggregation: + description: The aggregation type of the metric. Only valid option is "percentile" + type: string + example: percentile + enum: [percentile] + field: + description: The field of the metric. + type: string + example: processor.processed + percentile: + description: The percentile value. + type: number + example: 95 + filter: + description: The filter to apply to the metric. + type: string + example: 'processor.outcome: "success"' diff --git a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/update_slo_request.yaml b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/update_slo_request.yaml index ddeb2e39159a3f..8d2c61c7b22493 100644 --- a/x-pack/plugins/observability/docs/openapi/slo/components/schemas/update_slo_request.yaml +++ b/x-pack/plugins/observability/docs/openapi/slo/components/schemas/update_slo_request.yaml @@ -17,6 +17,7 @@ properties: - $ref: "indicator_properties_apm_latency.yaml" - $ref: "indicator_properties_custom_metric.yaml" - $ref: "indicator_properties_histogram.yaml" + - $ref: "indicator_properties_timeslice_metric.yaml" timeWindow: $ref: "time_window.yaml" budgetingMethod: diff --git a/x-pack/plugins/observability/public/pages/slo_details/components/overview/overview.tsx b/x-pack/plugins/observability/public/pages/slo_details/components/overview/overview.tsx index f3a6abb829984f..03d76b8dc2a7db 100644 --- a/x-pack/plugins/observability/public/pages/slo_details/components/overview/overview.tsx +++ b/x-pack/plugins/observability/public/pages/slo_details/components/overview/overview.tsx @@ -94,16 +94,26 @@ export function Overview({ slo }: Props) { ) : ( {BUDGETING_METHOD_TIMESLICES} ( - {i18n.translate( - 'xpack.observability.slo.sloDetails.overview.timeslicesBudgetingMethodDetails', - { - defaultMessage: '{duration} slices, {target} target', - values: { - duration: toDurationLabel(slo.objective.timesliceWindow!), - target: numeral(slo.objective.timesliceTarget!).format(percentFormat), - }, - } - )} + {slo.indicator.type === 'sli.metric.timeslice' + ? i18n.translate( + 'xpack.observability.slo.sloDetails.overview.timeslicesBudgetingMethodDetailsForTimesliceMetric', + { + defaultMessage: '{duration} slices', + values: { + duration: toDurationLabel(slo.objective.timesliceWindow!), + }, + } + ) + : i18n.translate( + 'xpack.observability.slo.sloDetails.overview.timeslicesBudgetingMethodDetails', + { + defaultMessage: '{duration} slices, {target} target', + values: { + duration: toDurationLabel(slo.objective.timesliceWindow!), + target: numeral(slo.objective.timesliceTarget!).format(percentFormat), + }, + } + )} ) ) diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/common/data_preview_chart.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/common/data_preview_chart.tsx index 8f6fe11cae3339..7dc2e00f60829b 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/common/data_preview_chart.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/common/data_preview_chart.tsx @@ -5,7 +5,18 @@ * 2.0. */ -import { AreaSeries, Axis, Chart, Position, ScaleType, Settings, Tooltip } from '@elastic/charts'; +import { + AnnotationDomainType, + AreaSeries, + Axis, + Chart, + LineAnnotation, + Position, + RectAnnotation, + ScaleType, + Settings, + Tooltip, +} from '@elastic/charts'; import { EuiFlexGroup, EuiFlexItem, @@ -22,12 +33,27 @@ import moment from 'moment'; import React from 'react'; import { useFormContext } from 'react-hook-form'; import { FormattedMessage } from '@kbn/i18n-react'; +import { min, max } from 'lodash'; import { useKibana } from '../../../../utils/kibana_react'; import { useDebouncedGetPreviewData } from '../../hooks/use_preview'; import { useSectionFormValidation } from '../../hooks/use_section_form_validation'; import { CreateSLOForm } from '../../types'; -export function DataPreviewChart() { +interface DataPreviewChartProps { + formatPattern?: string; + threshold?: number; + thresholdDirection?: 'above' | 'below'; + thresholdColor?: string; + thresholdMessage?: string; +} + +export function DataPreviewChart({ + formatPattern, + threshold, + thresholdDirection, + thresholdColor, + thresholdMessage, +}: DataPreviewChartProps) { const { watch, getFieldState, formState, getValues } = useFormContext(); const { charts, uiSettings } = useKibana().services; const { isIndicatorSectionValid } = useSectionFormValidation({ @@ -47,7 +73,22 @@ export function DataPreviewChart() { const theme = charts.theme.useChartsTheme(); const baseTheme = charts.theme.useChartsBaseTheme(); const dateFormat = uiSettings.get('dateFormat'); - const percentFormat = uiSettings.get('format:percent:defaultPattern'); + const numberFormat = + formatPattern != null + ? formatPattern + : (uiSettings.get('format:percent:defaultPattern') as string); + + const values = (previewData || []).map((row) => row.sliValue); + const maxValue = max(values); + const minValue = min(values); + const domain = { + fit: true, + min: + threshold != null && minValue != null && threshold < minValue ? threshold : minValue || NaN, + max: + threshold != null && maxValue != null && threshold > maxValue ? threshold : maxValue || NaN, + }; + const title = ( <> @@ -85,6 +126,39 @@ export function DataPreviewChart() { ); } + const annotation = threshold != null && ( + <> + + + + ); + return ( {title} @@ -127,6 +201,8 @@ export function DataPreviewChart() { locale={i18n.getLocale()} /> + {annotation} + numeral(d).format(percentFormat)} - domain={{ - fit: true, - min: NaN, - max: NaN, - }} + tickFormat={(d) => numeral(d).format(numberFormat)} + domain={domain} /> { const defaultEquation = createEquationFromMetric(previousNames); diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_indicator_section.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_indicator_section.tsx index 1be3a5b10e537e..3c87168792303a 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_indicator_section.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_indicator_section.tsx @@ -18,6 +18,7 @@ import { CustomKqlIndicatorTypeForm } from './custom_kql/custom_kql_indicator_ty import { CustomMetricIndicatorTypeForm } from './custom_metric/custom_metric_type_form'; import { HistogramIndicatorTypeForm } from './histogram/histogram_indicator_type_form'; import { maxWidth } from './slo_edit_form'; +import { TimesliceMetricIndicatorTypeForm } from './timeslice_metric/timeslice_metric_indicator'; interface SloEditFormIndicatorSectionProps { isEditMode: boolean; @@ -39,6 +40,8 @@ export function SloEditFormIndicatorSection({ isEditMode }: SloEditFormIndicator return ; case 'sli.histogram.custom': return ; + case 'sli.metric.timeslice': + return ; default: return null; } diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objective_section.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objective_section.tsx index 951e879f43cf19..ad1f84183a1380 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objective_section.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form_objective_section.tsx @@ -6,6 +6,7 @@ */ import { + EuiCallOut, EuiFieldNumber, EuiFlexGrid, EuiFlexItem, @@ -20,6 +21,7 @@ import { i18n } from '@kbn/i18n'; import { TimeWindow } from '@kbn/slo-schema'; import React, { useEffect, useState } from 'react'; import { Controller, useFormContext } from 'react-hook-form'; +import { FormattedMessage } from '@kbn/i18n-react'; import { BUDGETING_METHOD_OPTIONS, CALENDARALIGNED_TIMEWINDOW_OPTIONS, @@ -42,6 +44,7 @@ export function SloEditFormObjectiveSection() { const timeWindowTypeSelect = useGeneratedHtmlId({ prefix: 'timeWindowTypeSelect' }); const timeWindowSelect = useGeneratedHtmlId({ prefix: 'timeWindowSelect' }); const timeWindowType = watch('timeWindow.type'); + const indicator = watch('indicator.type'); const [timeWindowTypeState, setTimeWindowTypeState] = useState( defaultValues?.timeWindow?.type @@ -169,6 +172,19 @@ export function SloEditFormObjectiveSection() { + {indicator === 'sli.metric.timeslice' && ( + + +

+ +

+
+ +
+ )} @@ -198,6 +214,7 @@ export function SloEditFormObjectiveSection() { render={({ field: { ref, ...field } }) => ( (); + const { control, getFieldState, watch } = useFormContext(); + const indicator = watch('indicator.type'); return ( <> @@ -47,6 +48,7 @@ export function SloEditFormObjectiveSectionTimeslices() { String.fromCharCode(c)); +const INVALID_EQUATION_REGEX = /[^A-Z|+|\-|\s|\d+|\.|\(|\)|\/|\*|>|<|=|\?|\:|&|\!|\|]+/; + +const validateEquation = (value: string) => { + const result = value.match(INVALID_EQUATION_REGEX); + return result === null; +}; + +function createEquationFromMetric(names: string[]) { + return names.join(' + '); +} + +const equationLabel = i18n.translate( + 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.equationLabel', + { defaultMessage: 'Equation' } +); + +const equationTooltip = ( + +); + +const thresholdLabel = i18n.translate( + 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.thresholdLabel', + { + defaultMessage: 'Threshold', + } +); + +const thresholdTooltip = ( + +); + +export function MetricIndicator({ indexFields, isLoadingIndex }: MetricIndicatorProps) { + const { control, watch, setValue, register, getFieldState } = useFormContext(); + + const { fields, append, remove } = useFieldArray({ + control, + name: `indicator.params.metric.metrics`, + }); + const equation = watch(`indicator.params.metric.equation`); + const indexPattern = watch('indicator.params.index'); + + const disableAdd = fields?.length === MAX_VARIABLES || !indexPattern; + const disableDelete = fields?.length === 1 || !indexPattern; + + const setDefaultEquationIfUnchanged = (previousNames: string[], nextNames: string[]) => { + const defaultEquation = createEquationFromMetric(previousNames); + if (defaultEquation === equation) { + setValue(`indicator.params.metric.equation`, createEquationFromMetric(nextNames)); + } + }; + + const handleDeleteMetric = (index: number) => () => { + const currentVars = fields.map((m) => m.name) ?? ['A']; + const deletedVar = currentVars[index]; + setDefaultEquationIfUnchanged(currentVars, xor(currentVars, [deletedVar])); + remove(index); + }; + + const handleAddMetric = () => { + const currentVars = fields.map((m) => m.name) ?? ['A']; + const name = first(xor(VAR_NAMES, currentVars))!; + setDefaultEquationIfUnchanged(currentVars, [...currentVars, name]); + append({ ...NEW_TIMESLICE_METRIC, name }); + }; + + return ( + <> + + {fields?.map((metric, index) => ( + + + + + + + + + + + ))} + + + + + + + + + + + + + + ( + + {equationLabel} {equationTooltip} + + } + isInvalid={fieldState.invalid} + error={[ + i18n.translate( + 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.equation.invalidCharacters', + { + defaultMessage: + 'The equation field only supports the following characters: A-Z, +, -, /, *, (, ), ?, !, &, :, |, >, <, =', + } + ), + ]} + > + field.onChange(event.target.value)} + /> + + )} + /> + + + ( + + field.onChange(event.target.value)} + /> + + )} + /> + + + + {thresholdLabel} {thresholdTooltip} + + } + > + ( + field.onChange(Number(event.target.value))} + /> + )} + /> + + + + + + +

+ {i18n.translate( + 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.equationHelpText', + { + defaultMessage: + 'Supports basic math equations, valid charaters are: A-Z, +, -, /, *, (, ), ?, !, &, :, |, >, <, =', + } + )} +

+
+
+
+ + ); +} diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/metric_input.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/metric_input.tsx new file mode 100644 index 00000000000000..0db4c1d585782d --- /dev/null +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/metric_input.tsx @@ -0,0 +1,263 @@ +/* + * 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 { + EuiComboBox, + EuiComboBoxOptionOption, + EuiFieldNumber, + EuiFlexItem, + EuiFormRow, + EuiIconTip, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { Controller, useFormContext } from 'react-hook-form'; +import { createOptionsFromFields } from '../../helpers/create_options'; +import { QueryBuilder } from '../common/query_builder'; +import { CreateSLOForm } from '../../types'; +import { AGGREGATION_OPTIONS, aggValueToLabel } from '../../helpers/aggregation_options'; +import { Field } from '../../../../hooks/slo/use_fetch_index_pattern_fields'; + +const fieldLabel = i18n.translate( + 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.fieldLabel', + { defaultMessage: 'Field' } +); + +const aggregationLabel = i18n.translate( + 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.aggregationLabel', + { defaultMessage: 'Aggregation' } +); + +const filterLabel = i18n.translate( + 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.filterLabel', + { defaultMessage: 'Filter' } +); + +const fieldTooltip = ( + +); + +const NUMERIC_FIELD_TYPES = ['number', 'histogram']; +const CARDINALITY_FIELD_TYPES = ['number', 'string']; + +interface MetricInputProps { + metricIndex: number; + indexPattern: string; + isLoadingIndex: boolean; + indexFields: Field[]; +} + +export function MetricInput({ + metricIndex: index, + indexPattern, + isLoadingIndex, + indexFields, +}: MetricInputProps) { + const { control, watch } = useFormContext(); + const metric = watch(`indicator.params.metric.metrics.${index}`); + const metricFields = indexFields.filter((field) => + metric.aggregation === 'cardinality' + ? CARDINALITY_FIELD_TYPES.includes(field.type) + : NUMERIC_FIELD_TYPES.includes(field.type) + ); + return ( + <> + + ( + + {aggregationLabel} {metric.name} + + } + isInvalid={fieldState.invalid} + > + { + if (selected.length) { + return field.onChange(selected[0].value); + } + field.onChange(''); + }} + selectedOptions={ + !!indexPattern && + !!field.value && + AGGREGATION_OPTIONS.some((agg) => agg.value === agg.value) + ? [ + { + value: field.value, + label: aggValueToLabel(field.value), + }, + ] + : [] + } + options={AGGREGATION_OPTIONS} + /> + + )} + /> + + {metric.aggregation === 'percentile' && ( + + ( + + {i18n.translate( + 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.percentileLabel', + { defaultMessage: 'Percentile' } + )}{' '} + {metric.name} + + } + > + onChange(Number(event.target.value))} + /> + + )} + /> + + )} + {metric.aggregation !== 'doc_count' && ( + + ( + + {fieldLabel} {metric.name} {fieldTooltip} + + } + > + { + if (selected.length) { + return field.onChange(selected[0].value); + } + field.onChange(''); + }} + selectedOptions={ + !!indexPattern && + !!field.value && + metricFields.some((metricField) => metricField.name === field.value) + ? [ + { + value: field.value, + label: field.value, + }, + ] + : [] + } + options={createOptionsFromFields(metricFields)} + /> + + )} + /> + + )} + + + } + /> + + + ); +} diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/timeslice_metric_indicator.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/timeslice_metric_indicator.tsx new file mode 100644 index 00000000000000..5d455a601e3d76 --- /dev/null +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/timeslice_metric_indicator.tsx @@ -0,0 +1,163 @@ +/* + * 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 { + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiIconTip, + EuiSpacer, + EuiTitle, + useEuiTheme, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; +import { useFormContext } from 'react-hook-form'; +import { useFetchIndexPatternFields } from '../../../../hooks/slo/use_fetch_index_pattern_fields'; +import { CreateSLOForm } from '../../types'; +import { DataPreviewChart } from '../common/data_preview_chart'; +import { IndexFieldSelector } from '../common/index_field_selector'; +import { QueryBuilder } from '../common/query_builder'; +import { IndexSelection } from '../custom_common/index_selection'; +import { MetricIndicator } from './metric_indicator'; +import { useKibana } from '../../../../utils/kibana_react'; +import { COMPARATOR_MAPPING } from '../../constants'; + +export { NEW_TIMESLICE_METRIC } from './metric_indicator'; + +export function TimesliceMetricIndicatorTypeForm() { + const { watch } = useFormContext(); + const index = watch('indicator.params.index'); + const { isLoading: isIndexFieldsLoading, data: indexFields = [] } = + useFetchIndexPatternFields(index); + const timestampFields = indexFields.filter((field) => field.type === 'date'); + const partitionByFields = indexFields.filter((field) => field.aggregatable); + const { uiSettings } = useKibana().services; + const threshold = watch('indicator.params.metric.threshold'); + const comparator = watch('indicator.params.metric.comparator'); + const { euiTheme } = useEuiTheme(); + + return ( + <> + +

+ +

+
+ + + + + + + + + + + + + + } + /> + + + + + + + + +

+ +

+
+ + +
+ + + + + + + {i18n.translate('xpack.observability.slo.sloEdit.groupBy.label', { + defaultMessage: 'Partition by', + })}{' '} + + + } + placeholder={i18n.translate('xpack.observability.slo.sloEdit.groupBy.placeholder', { + defaultMessage: 'Select an optional field to partition by', + })} + isLoading={!!index && isIndexFieldsLoading} + isDisabled={!index} + /> + + +
+ + ); +} diff --git a/x-pack/plugins/observability/public/pages/slo_edit/constants.ts b/x-pack/plugins/observability/public/pages/slo_edit/constants.ts index 4c38525784a100..9c5284855c7721 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/constants.ts +++ b/x-pack/plugins/observability/public/pages/slo_edit/constants.ts @@ -15,6 +15,7 @@ import { IndicatorType, KQLCustomIndicator, MetricCustomIndicator, + TimesliceMetricIndicator, TimeWindow, } from '@kbn/slo-schema'; import { @@ -25,6 +26,7 @@ import { INDICATOR_CUSTOM_KQL, INDICATOR_CUSTOM_METRIC, INDICATOR_HISTOGRAM, + INDICATOR_TIMESLICE_METRIC, } from '../../utils/slo/labels'; import { CreateSLOForm } from './types'; @@ -40,6 +42,10 @@ export const SLI_OPTIONS: Array<{ value: 'sli.metric.custom', text: INDICATOR_CUSTOM_METRIC, }, + { + value: 'sli.metric.timeslice', + text: INDICATOR_TIMESLICE_METRIC, + }, { value: 'sli.histogram.custom', text: INDICATOR_HISTOGRAM, @@ -125,6 +131,21 @@ export const CUSTOM_METRIC_DEFAULT_VALUES: MetricCustomIndicator = { }, }; +export const TIMESLICE_METRIC_DEFAULT_VALUES: TimesliceMetricIndicator = { + type: 'sli.metric.timeslice' as const, + params: { + index: '', + filter: '', + metric: { + metrics: [{ name: 'A', aggregation: 'avg' as const, field: '' }], + equation: 'A', + comparator: 'GT', + threshold: 0, + }, + timestampField: '', + }, +}; + export const HISTOGRAM_DEFAULT_VALUES: HistogramIndicator = { type: 'sli.histogram.custom' as const, params: { @@ -198,3 +219,57 @@ export const SLO_EDIT_FORM_DEFAULT_VALUES_CUSTOM_METRIC: CreateSLOForm = { }, groupBy: ALL_VALUE, }; + +export const COMPARATOR_GT = i18n.translate( + 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.gtLabel', + { + defaultMessage: 'Greater than', + } +); + +export const COMPARATOR_GTE = i18n.translate( + 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.gteLabel', + { + defaultMessage: 'Greater than or equal to', + } +); + +export const COMPARATOR_LT = i18n.translate( + 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.ltLabel', + { + defaultMessage: 'Less than', + } +); + +export const COMPARATOR_LTE = i18n.translate( + 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.lteLabel', + { + defaultMessage: 'Less than or equal to', + } +); + +export const COMPARATOR_MAPPING = { + GT: COMPARATOR_GT, + GTE: COMPARATOR_GTE, + LT: COMPARATOR_LT, + LTE: COMPARATOR_LTE, +}; + +export const COMPARATOR_OPTIONS = [ + { + text: COMPARATOR_GT, + value: 'GT' as const, + }, + { + text: COMPARATOR_GTE, + value: 'GTE' as const, + }, + { + text: COMPARATOR_LT, + value: 'LT' as const, + }, + { + text: COMPARATOR_LTE, + value: 'LTE' as const, + }, +]; diff --git a/x-pack/plugins/observability/public/pages/slo_edit/helpers/aggregation_options.ts b/x-pack/plugins/observability/public/pages/slo_edit/helpers/aggregation_options.ts new file mode 100644 index 00000000000000..4a3a5fb9cf28ac --- /dev/null +++ b/x-pack/plugins/observability/public/pages/slo_edit/helpers/aggregation_options.ts @@ -0,0 +1,84 @@ +/* + * 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'; +export const AGGREGATION_OPTIONS = [ + { + value: 'avg', + label: i18n.translate('xpack.observability.slo.sloEdit.timesliceMetric.aggregation.average', { + defaultMessage: 'Average', + }), + }, + { + value: 'max', + label: i18n.translate('xpack.observability.slo.sloEdit.timesliceMetric.aggregation.max', { + defaultMessage: 'Max', + }), + }, + { + value: 'min', + label: i18n.translate('xpack.observability.slo.sloEdit.timesliceMetric.aggregation.min', { + defaultMessage: 'Min', + }), + }, + { + value: 'sum', + label: i18n.translate('xpack.observability.slo.sloEdit.timesliceMetric.aggregation.sum', { + defaultMessage: 'Sum', + }), + }, + { + value: 'cardinality', + label: i18n.translate( + 'xpack.observability.slo.sloEdit.timesliceMetric.aggregation.cardinality', + { + defaultMessage: 'Cardinality', + } + ), + }, + { + value: 'last_value', + label: i18n.translate( + 'xpack.observability.slo.sloEdit.timesliceMetric.aggregation.last_value', + { + defaultMessage: 'Last value', + } + ), + }, + { + value: 'std_deviation', + label: i18n.translate( + 'xpack.observability.slo.sloEdit.timesliceMetric.aggregation.std_deviation', + { + defaultMessage: 'Std. Deviation', + } + ), + }, + { + value: 'doc_count', + label: i18n.translate('xpack.observability.slo.sloEdit.timesliceMetric.aggregation.doc_count', { + defaultMessage: 'Doc count', + }), + }, + { + value: 'percentile', + label: i18n.translate( + 'xpack.observability.slo.sloEdit.timesliceMetric.aggregation.percentile', + { + defaultMessage: 'Percentile', + } + ), + }, +]; + +export function aggValueToLabel(value: string) { + const aggregation = AGGREGATION_OPTIONS.find((agg) => agg.value === value); + if (aggregation) { + return aggregation.label; + } + return value; +} diff --git a/x-pack/plugins/observability/public/pages/slo_edit/helpers/process_slo_form_values.ts b/x-pack/plugins/observability/public/pages/slo_edit/helpers/process_slo_form_values.ts index c6de2126adacfd..f523cc1ce1ce1f 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/helpers/process_slo_form_values.ts +++ b/x-pack/plugins/observability/public/pages/slo_edit/helpers/process_slo_form_values.ts @@ -15,6 +15,7 @@ import { CUSTOM_KQL_DEFAULT_VALUES, CUSTOM_METRIC_DEFAULT_VALUES, HISTOGRAM_DEFAULT_VALUES, + TIMESLICE_METRIC_DEFAULT_VALUES, } from '../constants'; import { CreateSLOForm } from '../types'; @@ -132,6 +133,11 @@ function transformPartialIndicatorState( type: 'sli.metric.custom' as const, params: Object.assign({}, CUSTOM_METRIC_DEFAULT_VALUES.params, indicator.params ?? {}), }; + case 'sli.metric.timeslice': + return { + type: 'sli.metric.timeslice' as const, + params: Object.assign({}, TIMESLICE_METRIC_DEFAULT_VALUES.params, indicator.params ?? {}), + }; default: assertNever(indicatorType); } diff --git a/x-pack/plugins/observability/public/pages/slo_edit/hooks/use_section_form_validation.ts b/x-pack/plugins/observability/public/pages/slo_edit/hooks/use_section_form_validation.ts index e0c2652bfc46d7..6fede4552d6f89 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/hooks/use_section_form_validation.ts +++ b/x-pack/plugins/observability/public/pages/slo_edit/hooks/use_section_form_validation.ts @@ -5,7 +5,12 @@ * 2.0. */ -import { MetricCustomIndicator } from '@kbn/slo-schema'; +import { + MetricCustomIndicator, + timesliceMetricBasicMetricWithField, + TimesliceMetricIndicator, + timesliceMetricPercentileMetric, +} from '@kbn/slo-schema'; import { FormState, UseFormGetFieldState, UseFormGetValues, UseFormWatch } from 'react-hook-form'; import { isObject } from 'lodash'; import { CreateSLOForm } from '../types'; @@ -54,6 +59,39 @@ export function useSectionFormValidation({ getFieldState, getValues, formState, isGoodParamsValid() && isTotalParamsValid(); break; + case 'sli.metric.timeslice': + const isMetricParamsValid = () => { + const data = getValues( + 'indicator.params.metric' + ) as TimesliceMetricIndicator['params']['metric']; + const isEquationValid = !getFieldState('indicator.params.metric.equation').invalid; + const areMetricsValid = + isObject(data) && + (data.metrics ?? []).every((metric) => { + if (timesliceMetricBasicMetricWithField.is(metric)) { + return Boolean(metric.field); + } + if (timesliceMetricPercentileMetric.is(metric)) { + return Boolean(metric.field) && Boolean(metric.percentile); + } + return true; + }); + return isEquationValid && areMetricsValid; + }; + + isIndicatorSectionValid = + ( + [ + 'indicator.params.index', + 'indicator.params.filter', + 'indicator.params.timestampField', + ] as const + ).every((field) => !getFieldState(field).invalid) && + (['indicator.params.index', 'indicator.params.timestampField'] as const).every( + (field) => !!getValues(field) + ) && + isMetricParamsValid(); + break; case 'sli.histogram.custom': const isRangeValid = (type: 'good' | 'total') => { const aggregation = getValues(`indicator.params.${type}.aggregation`); diff --git a/x-pack/plugins/observability/public/pages/slo_edit/hooks/use_unregister_fields.ts b/x-pack/plugins/observability/public/pages/slo_edit/hooks/use_unregister_fields.ts index c15b5cb7fbbfcf..d461c841940a42 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/hooks/use_unregister_fields.ts +++ b/x-pack/plugins/observability/public/pages/slo_edit/hooks/use_unregister_fields.ts @@ -14,10 +14,12 @@ import { useFetchApmIndex } from '../../../hooks/slo/use_fetch_apm_indices'; import { APM_AVAILABILITY_DEFAULT_VALUES, APM_LATENCY_DEFAULT_VALUES, + BUDGETING_METHOD_OPTIONS, CUSTOM_KQL_DEFAULT_VALUES, CUSTOM_METRIC_DEFAULT_VALUES, HISTOGRAM_DEFAULT_VALUES, SLO_EDIT_FORM_DEFAULT_VALUES, + TIMESLICE_METRIC_DEFAULT_VALUES, } from '../constants'; import { CreateSLOForm } from '../types'; @@ -49,6 +51,22 @@ export function useUnregisterFields({ isEditMode }: { isEditMode: boolean }) { } ); break; + case 'sli.metric.timeslice': + reset( + Object.assign({}, SLO_EDIT_FORM_DEFAULT_VALUES, { + budgetingMethod: BUDGETING_METHOD_OPTIONS[1].value, + objective: { + target: 99, + timesliceTarget: 95, + timesliceWindow: 1, + }, + indicator: TIMESLICE_METRIC_DEFAULT_VALUES, + }), + { + keepDefaultValues: true, + } + ); + break; case 'sli.kql.custom': reset( Object.assign({}, SLO_EDIT_FORM_DEFAULT_VALUES, { diff --git a/x-pack/plugins/observability/public/utils/slo/labels.ts b/x-pack/plugins/observability/public/utils/slo/labels.ts index 40c58e624bb2b9..43ed455f5a9e3a 100644 --- a/x-pack/plugins/observability/public/utils/slo/labels.ts +++ b/x-pack/plugins/observability/public/utils/slo/labels.ts @@ -21,6 +21,13 @@ export const INDICATOR_CUSTOM_METRIC = i18n.translate( } ); +export const INDICATOR_TIMESLICE_METRIC = i18n.translate( + 'xpack.observability.slo.indicators.timesliceMetric', + { + defaultMessage: 'Timeslice Metric', + } +); + export const INDICATOR_HISTOGRAM = i18n.translate('xpack.observability.slo.indicators.histogram', { defaultMessage: 'Histogram Metric', }); @@ -54,6 +61,9 @@ export function toIndicatorTypeLabel( case 'sli.histogram.custom': return INDICATOR_HISTOGRAM; + case 'sli.metric.timeslice': + return INDICATOR_TIMESLICE_METRIC; + default: assertNever(indicatorType as never); } diff --git a/x-pack/plugins/observability/server/routes/slo/route.ts b/x-pack/plugins/observability/server/routes/slo/route.ts index 2dfdcb2308ee3c..ade3f1714ddfba 100644 --- a/x-pack/plugins/observability/server/routes/slo/route.ts +++ b/x-pack/plugins/observability/server/routes/slo/route.ts @@ -49,6 +49,7 @@ import { KQLCustomTransformGenerator, MetricCustomTransformGenerator, TransformGenerator, + TimesliceMetricTransformGenerator, } from '../../services/slo/transform_generators'; import type { ObservabilityRequestHandlerContext } from '../../types'; import { createObservabilityServerRoute } from '../create_observability_server_route'; @@ -59,6 +60,7 @@ const transformGenerators: Record = { 'sli.kql.custom': new KQLCustomTransformGenerator(), 'sli.metric.custom': new MetricCustomTransformGenerator(), 'sli.histogram.custom': new HistogramTransformGenerator(), + 'sli.metric.timeslice': new TimesliceMetricTransformGenerator(), }; const assertPlatinumLicense = async (context: ObservabilityRequestHandlerContext) => { diff --git a/x-pack/plugins/observability/server/services/slo/aggregations/__snapshots__/get_timeslice_metric_indicator_aggregation.test.ts.snap b/x-pack/plugins/observability/server/services/slo/aggregations/__snapshots__/get_timeslice_metric_indicator_aggregation.test.ts.snap new file mode 100644 index 00000000000000..8288087ce33277 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/aggregations/__snapshots__/get_timeslice_metric_indicator_aggregation.test.ts.snap @@ -0,0 +1,213 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GetTimesliceMetricIndicatorAggregation should generate an aggregation for basic metrics 1`] = ` +Object { + "_A": Object { + "aggs": Object { + "metric": Object { + "avg": Object { + "field": "test.field", + }, + }, + }, + "filter": Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "test.category": "test", + }, + }, + ], + }, + }, + }, + "_B": Object { + "aggs": Object { + "metric": Object { + "max": Object { + "field": "test.field", + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_C": Object { + "aggs": Object { + "metric": Object { + "min": Object { + "field": "test.field", + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_D": Object { + "aggs": Object { + "metric": Object { + "sum": Object { + "field": "test.field", + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_E": Object { + "aggs": Object { + "metric": Object { + "cardinality": Object { + "field": "test.field", + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_metric": Object { + "bucket_script": Object { + "buckets_path": Object { + "A": "_A>metric", + "B": "_B>metric", + "C": "_C>metric", + "D": "_D>metric", + "E": "_E>metric", + }, + "script": Object { + "lang": "painless", + "source": "(params.A + params.B + params.C + params.D + params.E) / params.A", + }, + }, + }, +} +`; + +exports[`GetTimesliceMetricIndicatorAggregation should generate an aggregation for doc_count 1`] = ` +Object { + "_A": Object { + "filter": Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "test.category": "test", + }, + }, + ], + }, + }, + }, + "_metric": Object { + "bucket_script": Object { + "buckets_path": Object { + "A": "_A>_count", + }, + "script": Object { + "lang": "painless", + "source": "params.A", + }, + }, + }, +} +`; + +exports[`GetTimesliceMetricIndicatorAggregation should generate an aggregation for last_value 1`] = ` +Object { + "_A": Object { + "aggs": Object { + "metric": Object { + "top_metrics": Object { + "metrics": Object { + "field": "test.field", + }, + "sort": Object { + "@timestamp": "desc", + }, + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_metric": Object { + "bucket_script": Object { + "buckets_path": Object { + "A": "_A>metric[test.field]", + }, + "script": Object { + "lang": "painless", + "source": "params.A", + }, + }, + }, +} +`; + +exports[`GetTimesliceMetricIndicatorAggregation should generate an aggregation for percentile 1`] = ` +Object { + "_A": Object { + "aggs": Object { + "metric": Object { + "percentiles": Object { + "field": "test.field", + "keyed": true, + "percents": Array [ + 97, + ], + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_metric": Object { + "bucket_script": Object { + "buckets_path": Object { + "A": "_A>metric[97]", + }, + "script": Object { + "lang": "painless", + "source": "params.A", + }, + }, + }, +} +`; + +exports[`GetTimesliceMetricIndicatorAggregation should generate an aggregation for std_deviation 1`] = ` +Object { + "_A": Object { + "aggs": Object { + "metric": Object { + "extended_stats": Object { + "field": "test.field", + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_metric": Object { + "bucket_script": Object { + "buckets_path": Object { + "A": "_A>metric[std_deviation]", + }, + "script": Object { + "lang": "painless", + "source": "params.A", + }, + }, + }, +} +`; diff --git a/x-pack/plugins/observability/server/services/slo/aggregations/get_custom_metric_indicator_aggregation.ts b/x-pack/plugins/observability/server/services/slo/aggregations/get_custom_metric_indicator_aggregation.ts index ceb51bdfef199d..73bbb91b1041f2 100644 --- a/x-pack/plugins/observability/server/services/slo/aggregations/get_custom_metric_indicator_aggregation.ts +++ b/x-pack/plugins/observability/server/services/slo/aggregations/get_custom_metric_indicator_aggregation.ts @@ -37,7 +37,7 @@ export class GetCustomMetricIndicatorAggregation { private convertEquationToPainless(bucketsPath: Record, equation: string) { const workingEquation = equation || Object.keys(bucketsPath).join(' + '); return Object.keys(bucketsPath).reduce((acc, key) => { - return acc.replace(key, `params.${key}`); + return acc.replaceAll(key, `params.${key}`); }, workingEquation); } diff --git a/x-pack/plugins/observability/server/services/slo/aggregations/get_timeslice_metric_indicator_aggregation.test.ts b/x-pack/plugins/observability/server/services/slo/aggregations/get_timeslice_metric_indicator_aggregation.test.ts new file mode 100644 index 00000000000000..4f73f186fd3436 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/aggregations/get_timeslice_metric_indicator_aggregation.test.ts @@ -0,0 +1,108 @@ +/* + * 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 { createTimesliceMetricIndicator } from '../fixtures/slo'; +import { GetTimesliceMetricIndicatorAggregation } from './get_timeslice_metric_indicator_aggregation'; + +describe('GetTimesliceMetricIndicatorAggregation', () => { + it('should generate an aggregation for basic metrics', () => { + const indicator = createTimesliceMetricIndicator( + [ + { + name: 'A', + aggregation: 'avg' as const, + field: 'test.field', + filter: 'test.category: test', + }, + { + name: 'B', + aggregation: 'max' as const, + field: 'test.field', + }, + { + name: 'C', + aggregation: 'min' as const, + field: 'test.field', + }, + { + name: 'D', + aggregation: 'sum' as const, + field: 'test.field', + }, + { + name: 'E', + aggregation: 'cardinality' as const, + field: 'test.field', + }, + ], + '(A + B + C + D + E) / A' + ); + const getIndicatorAggregation = new GetTimesliceMetricIndicatorAggregation(indicator); + expect(getIndicatorAggregation.execute('_metric')).toMatchSnapshot(); + }); + + it('should generate an aggregation for doc_count', () => { + const indicator = createTimesliceMetricIndicator( + [ + { + name: 'A', + aggregation: 'doc_count' as const, + filter: 'test.category: test', + }, + ], + 'A' + ); + const getIndicatorAggregation = new GetTimesliceMetricIndicatorAggregation(indicator); + expect(getIndicatorAggregation.execute('_metric')).toMatchSnapshot(); + }); + + it('should generate an aggregation for std_deviation', () => { + const indicator = createTimesliceMetricIndicator( + [ + { + name: 'A', + aggregation: 'std_deviation' as const, + field: 'test.field', + }, + ], + 'A' + ); + const getIndicatorAggregation = new GetTimesliceMetricIndicatorAggregation(indicator); + expect(getIndicatorAggregation.execute('_metric')).toMatchSnapshot(); + }); + + it('should generate an aggregation for percentile', () => { + const indicator = createTimesliceMetricIndicator( + [ + { + name: 'A', + aggregation: 'percentile' as const, + field: 'test.field', + percentile: 97, + }, + ], + 'A' + ); + const getIndicatorAggregation = new GetTimesliceMetricIndicatorAggregation(indicator); + expect(getIndicatorAggregation.execute('_metric')).toMatchSnapshot(); + }); + + it('should generate an aggregation for last_value', () => { + const indicator = createTimesliceMetricIndicator( + [ + { + name: 'A', + aggregation: 'last_value' as const, + field: 'test.field', + }, + ], + 'A' + ); + const getIndicatorAggregation = new GetTimesliceMetricIndicatorAggregation(indicator); + expect(getIndicatorAggregation.execute('_metric')).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/observability/server/services/slo/aggregations/get_timeslice_metric_indicator_aggregation.ts b/x-pack/plugins/observability/server/services/slo/aggregations/get_timeslice_metric_indicator_aggregation.ts new file mode 100644 index 00000000000000..e715038e324f0b --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/aggregations/get_timeslice_metric_indicator_aggregation.ts @@ -0,0 +1,130 @@ +/* + * 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 { TimesliceMetricIndicator, timesliceMetricMetricDef } from '@kbn/slo-schema'; +import * as t from 'io-ts'; +import { assertNever } from '@kbn/std'; + +import { getElastichsearchQueryOrThrow } from '../transform_generators'; + +type TimesliceMetricDef = TimesliceMetricIndicator['params']['metric']; +type TimesliceMetricMetricDef = t.TypeOf; + +export class GetTimesliceMetricIndicatorAggregation { + constructor(private indicator: TimesliceMetricIndicator) {} + + private buildAggregation(metric: TimesliceMetricMetricDef) { + const { aggregation } = metric; + switch (aggregation) { + case 'doc_count': + return {}; + case 'std_deviation': + return { + extended_stats: { field: metric.field }, + }; + case 'percentile': + if (metric.percentile == null) { + throw new Error('You must provide a percentile value for percentile aggregations.'); + } + return { + percentiles: { + field: metric.field, + percents: [metric.percentile], + keyed: true, + }, + }; + case 'last_value': + return { + top_metrics: { + metrics: { field: metric.field }, + sort: { [this.indicator.params.timestampField]: 'desc' }, + }, + }; + case 'avg': + case 'max': + case 'min': + case 'sum': + case 'cardinality': + if (metric.field == null) { + throw new Error('You must provide a field for basic metric aggregations.'); + } + return { + [aggregation]: { field: metric.field }, + }; + default: + assertNever(aggregation); + } + } + + private buildBucketPath(prefix: string, metric: TimesliceMetricMetricDef) { + const { aggregation } = metric; + switch (aggregation) { + case 'doc_count': + return `${prefix}>_count`; + case 'std_deviation': + return `${prefix}>metric[std_deviation]`; + case 'percentile': + return `${prefix}>metric[${metric.percentile}]`; + case 'last_value': + return `${prefix}>metric[${metric.field}]`; + case 'avg': + case 'max': + case 'min': + case 'sum': + case 'cardinality': + return `${prefix}>metric`; + default: + assertNever(aggregation); + } + } + + private buildMetricAggregations(metricDef: TimesliceMetricDef) { + return metricDef.metrics.reduce((acc, metric) => { + const filter = metric.filter + ? getElastichsearchQueryOrThrow(metric.filter) + : { match_all: {} }; + const aggs = { metric: this.buildAggregation(metric) }; + return { + ...acc, + [`_${metric.name}`]: { + filter, + ...(metric.aggregation !== 'doc_count' ? { aggs } : {}), + }, + }; + }, {}); + } + + private convertEquationToPainless(bucketsPath: Record, equation: string) { + const workingEquation = equation || Object.keys(bucketsPath).join(' + '); + return Object.keys(bucketsPath).reduce((acc, key) => { + return acc.replaceAll(key, `params.${key}`); + }, workingEquation); + } + + private buildMetricEquation(definition: TimesliceMetricDef) { + const bucketsPath = definition.metrics.reduce( + (acc, metric) => ({ ...acc, [metric.name]: this.buildBucketPath(`_${metric.name}`, metric) }), + {} + ); + return { + bucket_script: { + buckets_path: bucketsPath, + script: { + source: this.convertEquationToPainless(bucketsPath, definition.equation), + lang: 'painless', + }, + }, + }; + } + + public execute(aggregationKey: string) { + return { + ...this.buildMetricAggregations(this.indicator.params.metric), + [aggregationKey]: this.buildMetricEquation(this.indicator.params.metric), + }; + } +} diff --git a/x-pack/plugins/observability/server/services/slo/aggregations/index.ts b/x-pack/plugins/observability/server/services/slo/aggregations/index.ts index b814152a4fcd50..6df05b4b2eac5a 100644 --- a/x-pack/plugins/observability/server/services/slo/aggregations/index.ts +++ b/x-pack/plugins/observability/server/services/slo/aggregations/index.ts @@ -7,3 +7,4 @@ export * from './get_histogram_indicator_aggregation'; export * from './get_custom_metric_indicator_aggregation'; +export * from './get_timeslice_metric_indicator_aggregation'; diff --git a/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts b/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts index 494c54cd657417..e423a0441f9d5d 100644 --- a/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts +++ b/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts @@ -6,7 +6,13 @@ */ import { SavedObject } from '@kbn/core-saved-objects-server'; -import { ALL_VALUE, CreateSLOParams, HistogramIndicator, sloSchema } from '@kbn/slo-schema'; +import { + ALL_VALUE, + CreateSLOParams, + HistogramIndicator, + sloSchema, + TimesliceMetricIndicator, +} from '@kbn/slo-schema'; import { cloneDeep } from 'lodash'; import { v1 as uuidv1 } from 'uuid'; import { @@ -90,6 +96,25 @@ export const createMetricCustomIndicator = ( }, }); +export const createTimesliceMetricIndicator = ( + metrics: TimesliceMetricIndicator['params']['metric']['metrics'] = [], + equation: TimesliceMetricIndicator['params']['metric']['equation'] = '', + queryFilter = '' +): TimesliceMetricIndicator => ({ + type: 'sli.metric.timeslice', + params: { + index: 'test-*', + timestampField: '@timestamp', + filter: queryFilter, + metric: { + metrics, + equation, + threshold: 100, + comparator: 'GTE', + }, + }, +}); + export const createHistogramIndicator = ( params: Partial = {} ): HistogramIndicator => ({ diff --git a/x-pack/plugins/observability/server/services/slo/get_preview_data.ts b/x-pack/plugins/observability/server/services/slo/get_preview_data.ts index 98f07e1f8ed5e9..2fd80c09d38750 100644 --- a/x-pack/plugins/observability/server/services/slo/get_preview_data.ts +++ b/x-pack/plugins/observability/server/services/slo/get_preview_data.ts @@ -15,6 +15,7 @@ import { HistogramIndicator, KQLCustomIndicator, MetricCustomIndicator, + TimesliceMetricIndicator, } from '@kbn/slo-schema'; import { assertNever } from '@kbn/std'; import { APMTransactionDurationIndicator } from '../../domain/models'; @@ -23,6 +24,7 @@ import { InvalidQueryError } from '../../errors'; import { GetCustomMetricIndicatorAggregation, GetHistogramIndicatorAggregation, + GetTimesliceMetricIndicatorAggregation, } from './aggregations'; export class GetPreviewData { @@ -55,6 +57,7 @@ export class GetPreviewData { const result = await this.esClient.search({ index: indicator.params.index, + size: 0, query: { bool: { filter: [ @@ -130,6 +133,7 @@ export class GetPreviewData { const result = await this.esClient.search({ index: indicator.params.index, + size: 0, query: { bool: { filter: [ @@ -186,6 +190,7 @@ export class GetPreviewData { const timestampField = indicator.params.timestampField; const options = { index: indicator.params.index, + size: 0, query: { bool: { filter: [{ range: { [timestampField]: { gte: 'now-60m' } } }, filterQuery], @@ -228,6 +233,7 @@ export class GetPreviewData { const getCustomMetricIndicatorAggregation = new GetCustomMetricIndicatorAggregation(indicator); const result = await this.esClient.search({ index: indicator.params.index, + size: 0, query: { bool: { filter: [{ range: { [timestampField]: { gte: 'now-60m' } } }, filterQuery], @@ -261,6 +267,42 @@ export class GetPreviewData { })); } + private async getTimesliceMetricPreviewData( + indicator: TimesliceMetricIndicator + ): Promise { + const timestampField = indicator.params.timestampField; + const filterQuery = getElastichsearchQueryOrThrow(indicator.params.filter); + const getCustomMetricIndicatorAggregation = new GetTimesliceMetricIndicatorAggregation( + indicator + ); + const result = await this.esClient.search({ + index: indicator.params.index, + size: 0, + query: { + bool: { + filter: [{ range: { [timestampField]: { gte: 'now-60m' } } }, filterQuery], + }, + }, + aggs: { + perMinute: { + date_histogram: { + field: timestampField, + fixed_interval: '1m', + }, + aggs: { + ...getCustomMetricIndicatorAggregation.execute('metric'), + }, + }, + }, + }); + + // @ts-ignore buckets is not improperly typed + return result.aggregations?.perMinute.buckets.map((bucket) => ({ + date: bucket.key_as_string, + sliValue: !!bucket.metric ? bucket.metric.value : null, + })); + } + private async getCustomKQLPreviewData( indicator: KQLCustomIndicator ): Promise { @@ -270,6 +312,7 @@ export class GetPreviewData { const timestampField = indicator.params.timestampField; const result = await this.esClient.search({ index: indicator.params.index, + size: 0, query: { bool: { filter: [{ range: { [timestampField]: { gte: 'now-60m' } } }, filterQuery], @@ -313,6 +356,8 @@ export class GetPreviewData { return this.getHistogramPreviewData(params.indicator); case 'sli.metric.custom': return this.getCustomMetricPreviewData(params.indicator); + case 'sli.metric.timeslice': + return this.getTimesliceMetricPreviewData(params.indicator); default: assertNever(type); } diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/timeslice_metric.test.ts.snap b/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/timeslice_metric.test.ts.snap new file mode 100644 index 00000000000000..e2698ba3e17936 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/timeslice_metric.test.ts.snap @@ -0,0 +1,697 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Timeslice Metric Transform Generator filters the source using the kql query 1`] = ` +Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-7d/d", + }, + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match_phrase": Object { + "test.category": "test", + }, + }, + ], + }, + }, + ], + }, +} +`; + +exports[`Timeslice Metric Transform Generator returns the expected transform params for timeslices slo 1`] = ` +Object { + "_meta": Object { + "managed": true, + "managed_by": "observability", + "version": 2, + }, + "description": "Rolled-up SLI data for SLO: irrelevant", + "dest": Object { + "index": ".slo-observability.sli-v2", + "pipeline": ".slo-observability.sli.pipeline", + }, + "frequency": "1m", + "pivot": Object { + "aggregations": Object { + "_A": Object { + "aggs": Object { + "metric": Object { + "avg": Object { + "field": "test.field", + }, + }, + }, + "filter": Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match_phrase": Object { + "test.category": "test", + }, + }, + ], + }, + }, + }, + "_B": Object { + "filter": Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match_phrase": Object { + "test.category": "test", + }, + }, + ], + }, + }, + }, + "_C": Object { + "aggs": Object { + "metric": Object { + "top_metrics": Object { + "metrics": Object { + "field": "test.field", + }, + "sort": Object { + "@timestamp": "desc", + }, + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_D": Object { + "aggs": Object { + "metric": Object { + "extended_stats": Object { + "field": "test.field", + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_E": Object { + "aggs": Object { + "metric": Object { + "percentiles": Object { + "field": "test.field", + "keyed": true, + "percents": Array [ + 97, + ], + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_metric": Object { + "bucket_script": Object { + "buckets_path": Object { + "A": "_A>metric", + "B": "_B>_count", + "C": "_C>metric[test.field]", + "D": "_D>metric[std_deviation]", + "E": "_E>metric[97]", + }, + "script": Object { + "lang": "painless", + "source": "(params.A + params.B + params.C + params.D + params.E) / params.B", + }, + }, + }, + "slo.denominator": Object { + "bucket_script": Object { + "buckets_path": Object {}, + "script": "1", + }, + }, + "slo.isGoodSlice": Object { + "bucket_script": Object { + "buckets_path": Object { + "goodEvents": "slo.numerator>value", + }, + "script": "params.goodEvents == 1 ? 1 : 0", + }, + }, + "slo.numerator": Object { + "bucket_script": Object { + "buckets_path": Object { + "value": "_metric>value", + }, + "script": Object { + "params": Object { + "threshold": 100, + }, + "source": "params.value >= params.threshold ? 1 : 0", + }, + }, + }, + }, + "group_by": Object { + "@timestamp": Object { + "date_histogram": Object { + "field": "@timestamp", + "fixed_interval": "2m", + }, + }, + "slo.budgetingMethod": Object { + "terms": Object { + "field": "slo.budgetingMethod", + }, + }, + "slo.description": Object { + "terms": Object { + "field": "slo.description", + }, + }, + "slo.groupBy": Object { + "terms": Object { + "field": "slo.groupBy", + }, + }, + "slo.id": Object { + "terms": Object { + "field": "slo.id", + }, + }, + "slo.indicator.type": Object { + "terms": Object { + "field": "slo.indicator.type", + }, + }, + "slo.instanceId": Object { + "terms": Object { + "field": "slo.instanceId", + }, + }, + "slo.name": Object { + "terms": Object { + "field": "slo.name", + }, + }, + "slo.objective.sliceDurationInSeconds": Object { + "terms": Object { + "field": "slo.objective.sliceDurationInSeconds", + }, + }, + "slo.objective.target": Object { + "terms": Object { + "field": "slo.objective.target", + }, + }, + "slo.revision": Object { + "terms": Object { + "field": "slo.revision", + }, + }, + "slo.tags": Object { + "terms": Object { + "field": "slo.tags", + }, + }, + "slo.timeWindow.duration": Object { + "terms": Object { + "field": "slo.timeWindow.duration", + }, + }, + "slo.timeWindow.type": Object { + "terms": Object { + "field": "slo.timeWindow.type", + }, + }, + }, + }, + "settings": Object { + "deduce_mappings": false, + "unattended": true, + }, + "source": Object { + "index": "test-*", + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-7d/d", + }, + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match_phrase": Object { + "test.category": "test", + }, + }, + ], + }, + }, + ], + }, + }, + "runtime_mappings": Object { + "slo.budgetingMethod": Object { + "script": Object { + "source": "emit('timeslices')", + }, + "type": "keyword", + }, + "slo.description": Object { + "script": Object { + "source": "emit('irrelevant')", + }, + "type": "keyword", + }, + "slo.groupBy": Object { + "script": Object { + "source": "emit('*')", + }, + "type": "keyword", + }, + "slo.id": Object { + "script": Object { + "source": Any, + }, + "type": "keyword", + }, + "slo.indicator.type": Object { + "script": Object { + "source": "emit('sli.metric.timeslice')", + }, + "type": "keyword", + }, + "slo.instanceId": Object { + "script": Object { + "source": "emit('*')", + }, + "type": "keyword", + }, + "slo.name": Object { + "script": Object { + "source": "emit('irrelevant')", + }, + "type": "keyword", + }, + "slo.objective.sliceDurationInSeconds": Object { + "script": Object { + "source": "emit(120)", + }, + "type": "long", + }, + "slo.objective.target": Object { + "script": Object { + "source": "emit(0.98)", + }, + "type": "double", + }, + "slo.revision": Object { + "script": Object { + "source": "emit(1)", + }, + "type": "long", + }, + "slo.tags": Object { + "script": Object { + "source": "emit('critical,k8s')", + }, + "type": "keyword", + }, + "slo.timeWindow.duration": Object { + "script": Object { + "source": "emit('7d')", + }, + "type": "keyword", + }, + "slo.timeWindow.type": Object { + "script": Object { + "source": "emit('rolling')", + }, + "type": "keyword", + }, + }, + }, + "sync": Object { + "time": Object { + "delay": "1m", + "field": "@timestamp", + }, + }, + "transform_id": Any, +} +`; + +exports[`Timeslice Metric Transform Generator returns the expected transform params with every specified indicator params 1`] = ` +Object { + "_meta": Object { + "managed": true, + "managed_by": "observability", + "version": 2, + }, + "description": "Rolled-up SLI data for SLO: irrelevant", + "dest": Object { + "index": ".slo-observability.sli-v2", + "pipeline": ".slo-observability.sli.pipeline", + }, + "frequency": "1m", + "pivot": Object { + "aggregations": Object { + "_A": Object { + "aggs": Object { + "metric": Object { + "avg": Object { + "field": "test.field", + }, + }, + }, + "filter": Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match_phrase": Object { + "test.category": "test", + }, + }, + ], + }, + }, + }, + "_B": Object { + "filter": Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match_phrase": Object { + "test.category": "test", + }, + }, + ], + }, + }, + }, + "_C": Object { + "aggs": Object { + "metric": Object { + "top_metrics": Object { + "metrics": Object { + "field": "test.field", + }, + "sort": Object { + "@timestamp": "desc", + }, + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_D": Object { + "aggs": Object { + "metric": Object { + "extended_stats": Object { + "field": "test.field", + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_E": Object { + "aggs": Object { + "metric": Object { + "percentiles": Object { + "field": "test.field", + "keyed": true, + "percents": Array [ + 97, + ], + }, + }, + }, + "filter": Object { + "match_all": Object {}, + }, + }, + "_metric": Object { + "bucket_script": Object { + "buckets_path": Object { + "A": "_A>metric", + "B": "_B>_count", + "C": "_C>metric[test.field]", + "D": "_D>metric[std_deviation]", + "E": "_E>metric[97]", + }, + "script": Object { + "lang": "painless", + "source": "(params.A + params.B + params.C + params.D + params.E) / params.B", + }, + }, + }, + "slo.denominator": Object { + "bucket_script": Object { + "buckets_path": Object {}, + "script": "1", + }, + }, + "slo.isGoodSlice": Object { + "bucket_script": Object { + "buckets_path": Object { + "goodEvents": "slo.numerator>value", + }, + "script": "params.goodEvents == 1 ? 1 : 0", + }, + }, + "slo.numerator": Object { + "bucket_script": Object { + "buckets_path": Object { + "value": "_metric>value", + }, + "script": Object { + "params": Object { + "threshold": 100, + }, + "source": "params.value >= params.threshold ? 1 : 0", + }, + }, + }, + }, + "group_by": Object { + "@timestamp": Object { + "date_histogram": Object { + "field": "@timestamp", + "fixed_interval": "2m", + }, + }, + "slo.budgetingMethod": Object { + "terms": Object { + "field": "slo.budgetingMethod", + }, + }, + "slo.description": Object { + "terms": Object { + "field": "slo.description", + }, + }, + "slo.groupBy": Object { + "terms": Object { + "field": "slo.groupBy", + }, + }, + "slo.id": Object { + "terms": Object { + "field": "slo.id", + }, + }, + "slo.indicator.type": Object { + "terms": Object { + "field": "slo.indicator.type", + }, + }, + "slo.instanceId": Object { + "terms": Object { + "field": "slo.instanceId", + }, + }, + "slo.name": Object { + "terms": Object { + "field": "slo.name", + }, + }, + "slo.objective.sliceDurationInSeconds": Object { + "terms": Object { + "field": "slo.objective.sliceDurationInSeconds", + }, + }, + "slo.objective.target": Object { + "terms": Object { + "field": "slo.objective.target", + }, + }, + "slo.revision": Object { + "terms": Object { + "field": "slo.revision", + }, + }, + "slo.tags": Object { + "terms": Object { + "field": "slo.tags", + }, + }, + "slo.timeWindow.duration": Object { + "terms": Object { + "field": "slo.timeWindow.duration", + }, + }, + "slo.timeWindow.type": Object { + "terms": Object { + "field": "slo.timeWindow.type", + }, + }, + }, + }, + "settings": Object { + "deduce_mappings": false, + "unattended": true, + }, + "source": Object { + "index": "test-*", + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-7d/d", + }, + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match_phrase": Object { + "test.category": "test", + }, + }, + ], + }, + }, + ], + }, + }, + "runtime_mappings": Object { + "slo.budgetingMethod": Object { + "script": Object { + "source": "emit('timeslices')", + }, + "type": "keyword", + }, + "slo.description": Object { + "script": Object { + "source": "emit('irrelevant')", + }, + "type": "keyword", + }, + "slo.groupBy": Object { + "script": Object { + "source": "emit('*')", + }, + "type": "keyword", + }, + "slo.id": Object { + "script": Object { + "source": Any, + }, + "type": "keyword", + }, + "slo.indicator.type": Object { + "script": Object { + "source": "emit('sli.metric.timeslice')", + }, + "type": "keyword", + }, + "slo.instanceId": Object { + "script": Object { + "source": "emit('*')", + }, + "type": "keyword", + }, + "slo.name": Object { + "script": Object { + "source": "emit('irrelevant')", + }, + "type": "keyword", + }, + "slo.objective.sliceDurationInSeconds": Object { + "script": Object { + "source": "emit(120)", + }, + "type": "long", + }, + "slo.objective.target": Object { + "script": Object { + "source": "emit(0.98)", + }, + "type": "double", + }, + "slo.revision": Object { + "script": Object { + "source": "emit(1)", + }, + "type": "long", + }, + "slo.tags": Object { + "script": Object { + "source": "emit('critical,k8s')", + }, + "type": "keyword", + }, + "slo.timeWindow.duration": Object { + "script": Object { + "source": "emit('7d')", + }, + "type": "keyword", + }, + "slo.timeWindow.type": Object { + "script": Object { + "source": "emit('rolling')", + }, + "type": "keyword", + }, + }, + }, + "sync": Object { + "time": Object { + "delay": "1m", + "field": "@timestamp", + }, + }, + "transform_id": Any, +} +`; diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/index.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/index.ts index 2b9337546d7965..8bfaf865f340c4 100644 --- a/x-pack/plugins/observability/server/services/slo/transform_generators/index.ts +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/index.ts @@ -11,4 +11,5 @@ export * from './apm_transaction_duration'; export * from './kql_custom'; export * from './metric_custom'; export * from './histogram'; +export * from './timeslice_metric'; export * from './common'; diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/timeslice_metric.test.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/timeslice_metric.test.ts new file mode 100644 index 00000000000000..aa21f7e0ceb0e4 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/timeslice_metric.test.ts @@ -0,0 +1,178 @@ +/* + * 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 { + createTimesliceMetricIndicator, + createSLOWithTimeslicesBudgetingMethod, + createSLO, +} from '../fixtures/slo'; +import { TimesliceMetricTransformGenerator } from './timeslice_metric'; + +const generator = new TimesliceMetricTransformGenerator(); +const everythingIndicator = createTimesliceMetricIndicator( + [ + { name: 'A', aggregation: 'avg', field: 'test.field', filter: 'test.category: "test"' }, + { name: 'B', aggregation: 'doc_count', filter: 'test.category: "test"' }, + { name: 'C', aggregation: 'last_value', field: 'test.field' }, + { name: 'D', aggregation: 'std_deviation', field: 'test.field' }, + { name: 'E', aggregation: 'percentile', field: 'test.field', percentile: 97 }, + ], + '(A + B + C + D + E) / B', + 'test.category: "test"' +); + +describe('Timeslice Metric Transform Generator', () => { + describe('validation', () => { + it('throws when the budgeting method is occurrences', () => { + const anSLO = createSLO({ + indicator: createTimesliceMetricIndicator( + [{ name: 'A', aggregation: 'avg', field: 'test.field' }], + '(A / 200) + A' + ), + }); + expect(() => generator.getTransformParams(anSLO)).toThrow( + 'The sli.metric.timeslice indicator MUST have a timeslice budgeting method.' + ); + }); + it('throws when the metric equation is invalid', () => { + const anSLO = createSLOWithTimeslicesBudgetingMethod({ + indicator: createTimesliceMetricIndicator( + [{ name: 'A', aggregation: 'avg', field: 'test.field' }], + '(a / 200) + A' + ), + }); + expect(() => generator.getTransformParams(anSLO)).toThrow(/Invalid equation/); + }); + it('throws when the metric filter is invalid', () => { + const anSLO = createSLOWithTimeslicesBudgetingMethod({ + indicator: createTimesliceMetricIndicator( + [{ name: 'A', aggregation: 'avg', field: 'test.field', filter: 'test:' }], + '(A / 200) + A' + ), + }); + expect(() => generator.getTransformParams(anSLO)).toThrow(/Invalid KQL: test:/); + }); + it('throws when the query_filter is invalid', () => { + const anSLO = createSLOWithTimeslicesBudgetingMethod({ + indicator: createTimesliceMetricIndicator( + [{ name: 'A', aggregation: 'avg', field: 'test.field', filter: 'test.category: "test"' }], + '(A / 200) + A', + 'test:' + ), + }); + expect(() => generator.getTransformParams(anSLO)).toThrow(/Invalid KQL/); + }); + }); + + it('returns the expected transform params with every specified indicator params', async () => { + const anSLO = createSLOWithTimeslicesBudgetingMethod({ + indicator: everythingIndicator, + }); + const transform = generator.getTransformParams(anSLO); + + expect(transform).toMatchSnapshot({ + transform_id: expect.any(String), + source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } }, + }); + expect(transform.transform_id).toEqual(`slo-${anSLO.id}-${anSLO.revision}`); + expect(transform.source.runtime_mappings!['slo.id']).toMatchObject({ + script: { source: `emit('${anSLO.id}')` }, + }); + expect(transform.source.runtime_mappings!['slo.revision']).toMatchObject({ + script: { source: `emit(${anSLO.revision})` }, + }); + }); + + it('returns the expected transform params for timeslices slo', async () => { + const anSLO = createSLOWithTimeslicesBudgetingMethod({ + indicator: everythingIndicator, + }); + const transform = generator.getTransformParams(anSLO); + + expect(transform).toMatchSnapshot({ + transform_id: expect.any(String), + source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } }, + }); + }); + + it('filters the source using the kql query', async () => { + const anSLO = createSLOWithTimeslicesBudgetingMethod({ + indicator: everythingIndicator, + }); + const transform = generator.getTransformParams(anSLO); + + expect(transform.source.query).toMatchSnapshot(); + }); + + it('uses the provided index', async () => { + const anSLO = createSLOWithTimeslicesBudgetingMethod({ + indicator: { + ...everythingIndicator, + params: { ...everythingIndicator.params, index: 'my-own-index*' }, + }, + }); + const transform = generator.getTransformParams(anSLO); + + expect(transform.source.index).toBe('my-own-index*'); + }); + + it('uses the provided timestampField', async () => { + const anSLO = createSLOWithTimeslicesBudgetingMethod({ + indicator: { + ...everythingIndicator, + params: { ...everythingIndicator.params, timestampField: 'my-date-field' }, + }, + }); + const transform = generator.getTransformParams(anSLO); + + expect(transform.sync?.time?.field).toBe('my-date-field'); + // @ts-ignore + expect(transform.pivot?.group_by['@timestamp'].date_histogram.field).toBe('my-date-field'); + }); + + it('aggregates using the _metric equation', async () => { + const anSLO = createSLOWithTimeslicesBudgetingMethod({ + indicator: everythingIndicator, + }); + const transform = generator.getTransformParams(anSLO); + + expect(transform.pivot!.aggregations!._metric).toEqual({ + bucket_script: { + buckets_path: { + A: '_A>metric', + B: '_B>_count', + C: '_C>metric[test.field]', + D: '_D>metric[std_deviation]', + E: '_E>metric[97]', + }, + script: { + lang: 'painless', + source: '(params.A + params.B + params.C + params.D + params.E) / params.B', + }, + }, + }); + expect(transform.pivot!.aggregations!['slo.numerator']).toEqual({ + bucket_script: { + buckets_path: { + value: '_metric>value', + }, + script: { + params: { + threshold: 100, + }, + source: 'params.value >= params.threshold ? 1 : 0', + }, + }, + }); + expect(transform.pivot!.aggregations!['slo.denominator']).toEqual({ + bucket_script: { + buckets_path: {}, + script: '1', + }, + }); + }); +}); diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/timeslice_metric.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/timeslice_metric.ts new file mode 100644 index 00000000000000..944b7d0622aadc --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/timeslice_metric.ts @@ -0,0 +1,116 @@ +/* + * 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 { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; +import { + timesliceMetricComparatorMapping, + TimesliceMetricIndicator, + timesliceMetricIndicatorSchema, + timeslicesBudgetingMethodSchema, +} from '@kbn/slo-schema'; + +import { InvalidTransformError } from '../../../errors'; +import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template'; +import { getElastichsearchQueryOrThrow, parseIndex, TransformGenerator } from '.'; +import { + SLO_DESTINATION_INDEX_NAME, + SLO_INGEST_PIPELINE_NAME, + getSLOTransformId, +} from '../../../assets/constants'; +import { SLO } from '../../../domain/models'; +import { GetTimesliceMetricIndicatorAggregation } from '../aggregations'; + +const INVALID_EQUATION_REGEX = /[^A-Z|+|\-|\s|\d+|\.|\(|\)|\/|\*|>|<|=|\?|\:|&|\!|\|]+/g; + +export class TimesliceMetricTransformGenerator extends TransformGenerator { + public getTransformParams(slo: SLO): TransformPutTransformRequest { + if (!timesliceMetricIndicatorSchema.is(slo.indicator)) { + throw new InvalidTransformError(`Cannot handle SLO of indicator type: ${slo.indicator.type}`); + } + + return getSLOTransformTemplate( + this.buildTransformId(slo), + this.buildDescription(slo), + this.buildSource(slo, slo.indicator), + this.buildDestination(), + this.buildCommonGroupBy(slo, slo.indicator.params.timestampField), + this.buildAggregations(slo, slo.indicator), + this.buildSettings(slo, slo.indicator.params.timestampField) + ); + } + + private buildTransformId(slo: SLO): string { + return getSLOTransformId(slo.id, slo.revision); + } + + private buildSource(slo: SLO, indicator: TimesliceMetricIndicator) { + return { + index: parseIndex(indicator.params.index), + runtime_mappings: this.buildCommonRuntimeMappings(slo), + query: { + bool: { + filter: [ + { + range: { + [indicator.params.timestampField]: { + gte: `now-${slo.timeWindow.duration.format()}/d`, + }, + }, + }, + getElastichsearchQueryOrThrow(indicator.params.filter), + ], + }, + }, + }; + } + + private buildDestination() { + return { + pipeline: SLO_INGEST_PIPELINE_NAME, + index: SLO_DESTINATION_INDEX_NAME, + }; + } + + private buildAggregations(slo: SLO, indicator: TimesliceMetricIndicator) { + if (indicator.params.metric.equation.match(INVALID_EQUATION_REGEX)) { + throw new Error(`Invalid equation: ${indicator.params.metric.equation}`); + } + + if (!timeslicesBudgetingMethodSchema.is(slo.budgetingMethod)) { + throw new Error('The sli.metric.timeslice indicator MUST have a timeslice budgeting method.'); + } + + const getIndicatorAggregation = new GetTimesliceMetricIndicatorAggregation(indicator); + const comparator = timesliceMetricComparatorMapping[indicator.params.metric.comparator]; + return { + ...getIndicatorAggregation.execute('_metric'), + 'slo.numerator': { + bucket_script: { + buckets_path: { value: '_metric>value' }, + script: { + source: `params.value ${comparator} params.threshold ? 1 : 0`, + params: { threshold: indicator.params.metric.threshold }, + }, + }, + }, + 'slo.denominator': { + bucket_script: { + buckets_path: {}, + script: '1', + }, + }, + 'slo.isGoodSlice': { + bucket_script: { + buckets_path: { + goodEvents: 'slo.numerator>value', + }, + script: `params.goodEvents == 1 ? 1 : 0`, + }, + }, + }; + } +}