From 96bc9e868de56e09c0a03e9a6d40cb2e4905b0ed Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Thu, 18 Feb 2021 13:42:40 -0500 Subject: [PATCH 1/8] [CI] Ping assignees on Github PR comments (#91871) --- vars/githubPr.groovy | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/vars/githubPr.groovy b/vars/githubPr.groovy index eead00c082ba75..d024eb7346f8f7 100644 --- a/vars/githubPr.groovy +++ b/vars/githubPr.groovy @@ -235,6 +235,13 @@ def getNextCommentMessage(previousCommentInfo = [:], isFinal = false) { messages << "To update your PR or re-run it, just comment with:\n`@elasticmachine merge upstream`" + catchErrors { + def assignees = getAssignees() + if (assignees) { + messages << "cc " + assignees.collect { "@${it}"}.join(" ") + } + } + info.builds << [ status: status, url: env.BUILD_URL, @@ -329,3 +336,19 @@ def shouldCheckCiMetricSuccess() { return true } + +def getPR() { + withGithubCredentials { + def path = "repos/elastic/kibana/pulls/${env.ghprbPullId}" + return githubApi.get(path) + } +} + +def getAssignees() { + def pr = getPR() + if (!pr) { + return [] + } + + return pr.assignees.collect { it.login } +} From 0a685dbb63ea77b82e9eb8a7e55c7a92f3ebf748 Mon Sep 17 00:00:00 2001 From: Devon Thomson Date: Thu, 18 Feb 2021 13:49:26 -0500 Subject: [PATCH 2/8] [Time to Visualize] Dashboard Save As New by Default (#91761) * changed dashboard save as to have save as new switch on by default --- .../top_nav/__snapshots__/save_modal.test.js.snap | 1 + .../dashboard/public/application/top_nav/save_modal.tsx | 1 + test/functional/page_objects/dashboard_page.ts | 5 +++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/dashboard/public/application/top_nav/__snapshots__/save_modal.test.js.snap b/src/plugins/dashboard/public/application/top_nav/__snapshots__/save_modal.test.js.snap index bc4ed477d9eea0..f8ba1b38685274 100644 --- a/src/plugins/dashboard/public/application/top_nav/__snapshots__/save_modal.test.js.snap +++ b/src/plugins/dashboard/public/application/top_nav/__snapshots__/save_modal.test.js.snap @@ -2,6 +2,7 @@ exports[`renders DashboardSaveModal 1`] = ` { onClose={this.props.onClose} title={this.props.title} showCopyOnSave={this.props.showCopyOnSave} + initialCopyOnSave={this.props.showCopyOnSave} objectType="dashboard" options={this.renderDashboardSaveOptions()} showDescription={false} diff --git a/test/functional/page_objects/dashboard_page.ts b/test/functional/page_objects/dashboard_page.ts index 9c571f0f0ef86b..465deed4d9039b 100644 --- a/test/functional/page_objects/dashboard_page.ts +++ b/test/functional/page_objects/dashboard_page.ts @@ -425,8 +425,9 @@ export function DashboardPageProvider({ getService, getPageObjects }: FtrProvide await this.setStoreTimeWithDashboard(saveOptions.storeTimeWithDashboard); } - if (saveOptions.saveAsNew !== undefined) { - await this.setSaveAsNewCheckBox(saveOptions.saveAsNew); + const saveAsNewCheckboxExists = await testSubjects.exists('saveAsNewCheckbox'); + if (saveAsNewCheckboxExists) { + await this.setSaveAsNewCheckBox(Boolean(saveOptions.saveAsNew)); } if (saveOptions.tags) { From 4ce0b6c14fbbbf6e51ff5c9f997edc80f9f0b15b Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Thu, 18 Feb 2021 13:03:50 -0600 Subject: [PATCH 3/8] [DOCS] Adds and updates Visualization advanced settings (#91904) --- docs/management/advanced-options.asciidoc | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index dc0405b22942f6..c7d5242da69de4 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -457,7 +457,7 @@ of buckets to try to represent. [horizontal] [[visualization-visualize-chartslibrary]]`visualization:visualize:legacyChartsLibrary`:: -Enables legacy charts library for area, line and bar charts in visualize. +Enables the legacy charts library for aggregation-based area, line, and bar charts in *Visualize*. [[visualization-colormapping]]`visualization:colorMapping`:: **This setting is deprecated and will not be supported as of 8.0.** @@ -465,24 +465,25 @@ Maps values to specific colors in *Visualize* charts and *TSVB*. This setting do [[visualization-dimmingopacity]]`visualization:dimmingOpacity`:: The opacity of the chart items that are dimmed when highlighting another element -of the chart. The lower this number, the more the highlighted element stands out. -This must be a number between 0 and 1. +of the chart. Use numbers between 0 and 1. The lower the number, the more the highlighted element stands out. + +[[visualization-heatmap-maxbuckets]]`visualization:heatmap:maxBuckets`:: +The maximum number of buckets a datasource can return. High numbers can have a negative impact on your browser rendering performance. [[visualization-regionmap-showwarnings]]`visualization:regionmap:showWarnings`:: Shows a warning in a region map when terms cannot be joined to a shape. [[visualization-tilemap-wmsdefaults]]`visualization:tileMap:WMSdefaults`:: -The default properties for the WMS map server support in the coordinate map. +The default properties for the WMS map server supported in the coordinate map. [[visualization-tilemap-maxprecision]]`visualization:tileMap:maxPrecision`:: -The maximum geoHash precision displayed on tile maps: 7 is high, 10 is very high, -and 12 is the maximum. See this -{ref}/search-aggregations-bucket-geohashgrid-aggregation.html#_cell_dimensions_at_the_equator[explanation of cell dimensions]. +The maximum geoHash precision displayed in tile maps. 7 is high, 10 is very high, +and 12 is the maximum. For more information, refer to +{ref}/search-aggregations-bucket-geohashgrid-aggregation.html#_cell_dimensions_at_the_equator[Cell dimensions at the equator]. [[visualize-enablelabs]]`visualize:enableLabs`:: -Enables users to create, view, and edit experimental visualizations. If disabled, -only visualizations that are considered production-ready are available to the -user. +Enables users to create, view, and edit experimental visualizations. When disabled, +only production-ready visualizations are available to users. [float] From 043848787d43ef2ae8efba77c899144291f2d14e Mon Sep 17 00:00:00 2001 From: Brandon Morelli Date: Thu, 18 Feb 2021 11:06:13 -0800 Subject: [PATCH 4/8] docs: add PHP agent info to docs (#91773) --- docs/apm/agent-configuration.asciidoc | 1 + docs/apm/filters.asciidoc | 3 ++- docs/apm/service-maps.asciidoc | 15 ++++++++------- docs/apm/troubleshooting.asciidoc | 1 + 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/docs/apm/agent-configuration.asciidoc b/docs/apm/agent-configuration.asciidoc index d911c2154ea4c5..aaaca867a5a01b 100644 --- a/docs/apm/agent-configuration.asciidoc +++ b/docs/apm/agent-configuration.asciidoc @@ -46,6 +46,7 @@ Go Agent:: {apm-go-ref}/configuration.html[Configuration reference] Java Agent:: {apm-java-ref}/configuration.html[Configuration reference] .NET Agent:: {apm-dotnet-ref}/configuration.html[Configuration reference] Node.js Agent:: {apm-node-ref}/configuration.html[Configuration reference] +PHP Agent:: _Not yet supported_ Python Agent:: {apm-py-ref}/configuration.html[Configuration reference] Ruby Agent:: {apm-ruby-ref}/configuration.html[Configuration reference] Real User Monitoring (RUM) Agent:: {apm-rum-ref}/configuration.html[Configuration reference] diff --git a/docs/apm/filters.asciidoc b/docs/apm/filters.asciidoc index c405ea10ade3d2..3fe9146658eefc 100644 --- a/docs/apm/filters.asciidoc +++ b/docs/apm/filters.asciidoc @@ -52,8 +52,9 @@ See the documentation for each agent you're using to learn how to configure serv * *Go:* {apm-go-ref}/configuration.html#config-environment[`ELASTIC_APM_ENVIRONMENT`] * *Java:* {apm-java-ref}/config-core.html#config-environment[`environment`] -* *.NET* {apm-dotnet-ref}/config-core.html#config-environment[`Environment`] +* *.NET:* {apm-dotnet-ref}/config-core.html#config-environment[`Environment`] * *Node.js:* {apm-node-ref}/configuration.html#environment[`environment`] +* *PHP:* {apm-php-ref}/configuration-reference.html#config-environment[`environment`] * *Python:* {apm-py-ref}/configuration.html#config-environment[`environment`] * *Ruby:* {apm-ruby-ref}/configuration.html#config-environment[`environment`] * *Real User Monitoring:* {apm-rum-ref}/configuration.html#environment[`environment`] diff --git a/docs/apm/service-maps.asciidoc b/docs/apm/service-maps.asciidoc index 7cc4da8a1fc1de..a3ac62a4c83436 100644 --- a/docs/apm/service-maps.asciidoc +++ b/docs/apm/service-maps.asciidoc @@ -87,10 +87,11 @@ Type and subtype are based on `span.type`, and `span.subtype`. Service maps are supported for the following Agent versions: [horizontal] -Go Agent:: ≥ v1.7.0 -Java Agent:: ≥ v1.13.0 -.NET Agent:: ≥ v1.3.0 -Node.js Agent:: ≥ v3.6.0 -Python Agent:: ≥ v5.5.0 -Ruby Agent:: ≥ v3.6.0 -Real User Monitoring (RUM) Agent:: ≥ v4.7.0 +Go agent:: ≥ v1.7.0 +Java agent:: ≥ v1.13.0 +.NET agent:: ≥ v1.3.0 +Node.js agent:: ≥ v3.6.0 +PHP agent:: _Not yet supported_ +Python agent:: ≥ v5.5.0 +Ruby agent:: ≥ v3.6.0 +Real User Monitoring (RUM) agent:: ≥ v4.7.0 diff --git a/docs/apm/troubleshooting.asciidoc b/docs/apm/troubleshooting.asciidoc index 465a3d652046db..5049321363f88e 100644 --- a/docs/apm/troubleshooting.asciidoc +++ b/docs/apm/troubleshooting.asciidoc @@ -17,6 +17,7 @@ don't forget to check our other troubleshooting guides or discussion forum: * {apm-go-ref}/troubleshooting.html[Go agent troubleshooting] * {apm-java-ref}/trouble-shooting.html[Java agent troubleshooting] * {apm-node-ref}/troubleshooting.html[Node.js agent troubleshooting] +* {apm-php-ref}/troubleshooting.html[PHP agent troubleshooting] * {apm-py-ref}/troubleshooting.html[Python agent troubleshooting] * {apm-ruby-ref}/debugging.html[Ruby agent troubleshooting] * {apm-rum-ref/troubleshooting.html[RUM troubleshooting] From 03206b688ab239ce837b469a8a690eab30a0a6ff Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Thu, 18 Feb 2021 14:13:23 -0500 Subject: [PATCH 5/8] [CI] Build and publish storybooks (#87701) --- .ci/.storybook/main.js | 28 +++++++ .eslintignore | 1 + packages/kbn-storybook/lib/default_config.ts | 7 ++ .../kbn-storybook/lib/templates/index.ejs | 10 +-- src/dev/storybook/aliases.ts | 2 + test/scripts/jenkins_storybook.sh | 23 +++++ vars/githubCommitStatus.groovy | 6 +- vars/githubPr.groovy | 9 ++ vars/kibanaPipeline.groovy | 1 + vars/storybooks.groovy | 83 +++++++++++++++++++ vars/tasks.groovy | 6 ++ .../canvas/storybook/preview-head.html | 4 +- 12 files changed, 171 insertions(+), 9 deletions(-) create mode 100644 .ci/.storybook/main.js create mode 100755 test/scripts/jenkins_storybook.sh create mode 100644 vars/storybooks.groovy diff --git a/.ci/.storybook/main.js b/.ci/.storybook/main.js new file mode 100644 index 00000000000000..e399ec087e1687 --- /dev/null +++ b/.ci/.storybook/main.js @@ -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 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. + */ + +const config = require('@kbn/storybook').defaultConfig; +const aliases = require('../../src/dev/storybook/aliases.ts').storybookAliases; + +config.refs = {}; + +for (const alias of Object.keys(aliases).filter((a) => a !== 'ci_composite')) { + // snake_case -> Title Case + const title = alias + .replace(/_/g, ' ') + .split(' ') + .map((n) => n[0].toUpperCase() + n.slice(1)) + .join(' '); + + config.refs[alias] = { + title: title, + url: `${process.env.STORYBOOK_BASE_URL}/${alias}`, + }; +} + +module.exports = config; diff --git a/.eslintignore b/.eslintignore index ea8ab55ad77269..4559711bb9dd31 100644 --- a/.eslintignore +++ b/.eslintignore @@ -15,6 +15,7 @@ node_modules target snapshots.js +!/.ci !/.eslintrc.js !.storybook diff --git a/packages/kbn-storybook/lib/default_config.ts b/packages/kbn-storybook/lib/default_config.ts index 53c51e9cf29fe6..1b049761a3a985 100644 --- a/packages/kbn-storybook/lib/default_config.ts +++ b/packages/kbn-storybook/lib/default_config.ts @@ -14,4 +14,11 @@ export const defaultConfig: StorybookConfig = { typescript: { reactDocgen: false, }, + webpackFinal: (config, options) => { + if (process.env.CI) { + config.parallelism = 4; + config.cache = true; + } + return config; + }, }; diff --git a/packages/kbn-storybook/lib/templates/index.ejs b/packages/kbn-storybook/lib/templates/index.ejs index a4f8204c95d7a2..b193c87824d40f 100644 --- a/packages/kbn-storybook/lib/templates/index.ejs +++ b/packages/kbn-storybook/lib/templates/index.ejs @@ -16,12 +16,12 @@ - - - - + + + + <% if (typeof headHtmlSnippet !== 'undefined') { %> <%= headHtmlSnippet %> <% } %> <% diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts index c72c81f489fb9d..f1a3737747573d 100644 --- a/src/dev/storybook/aliases.ts +++ b/src/dev/storybook/aliases.ts @@ -6,10 +6,12 @@ * Side Public License, v 1. */ +// Please also add new aliases to test/scripts/jenkins_storybook.sh export const storybookAliases = { apm: 'x-pack/plugins/apm/.storybook', canvas: 'x-pack/plugins/canvas/storybook', codeeditor: 'src/plugins/kibana_react/public/code_editor/.storybook', + ci_composite: '.ci/.storybook', url_template_editor: 'src/plugins/kibana_react/public/url_template_editor/.storybook', dashboard: 'src/plugins/dashboard/.storybook', dashboard_enhanced: 'x-pack/plugins/dashboard_enhanced/.storybook', diff --git a/test/scripts/jenkins_storybook.sh b/test/scripts/jenkins_storybook.sh new file mode 100755 index 00000000000000..8ebfc1035fe1f1 --- /dev/null +++ b/test/scripts/jenkins_storybook.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +source src/dev/ci_setup/setup_env.sh + +cd "$XPACK_DIR/plugins/canvas" +node scripts/storybook --dll + +cd "$KIBANA_DIR" + +# yarn storybook --site apm # TODO re-enable after being fixed +yarn storybook --site canvas +yarn storybook --site ci_composite +yarn storybook --site url_template_editor +yarn storybook --site codeeditor +yarn storybook --site dashboard +yarn storybook --site dashboard_enhanced +yarn storybook --site data_enhanced +yarn storybook --site embeddable +yarn storybook --site infra +yarn storybook --site security_solution +yarn storybook --site ui_actions_enhanced +yarn storybook --site observability +yarn storybook --site presentation diff --git a/vars/githubCommitStatus.groovy b/vars/githubCommitStatus.groovy index 248d226169a61e..175dbe0c90542f 100644 --- a/vars/githubCommitStatus.groovy +++ b/vars/githubCommitStatus.groovy @@ -41,13 +41,15 @@ def trackBuild(commit, context, Closure closure) { } // state: error|failure|pending|success -def create(sha, state, description, context) { +def create(sha, state, description, context, targetUrl = null) { + targetUrl = targetUrl ?: env.BUILD_URL + withGithubCredentials { return githubApi.post("repos/elastic/kibana/statuses/${sha}", [ state: state, description: description, context: context, - target_url: env.BUILD_URL + target_url: targetUrl.toString() ]) } } diff --git a/vars/githubPr.groovy b/vars/githubPr.groovy index d024eb7346f8f7..a2a3a81f253a02 100644 --- a/vars/githubPr.groovy +++ b/vars/githubPr.groovy @@ -169,12 +169,18 @@ def getNextCommentMessage(previousCommentInfo = [:], isFinal = false) { ? getBuildStatusIncludingMetrics() : buildUtils.getBuildStatus() + def storybooksUrl = buildState.get('storybooksUrl') + def storybooksMessage = storybooksUrl ? "* [Storybooks Preview](${storybooksUrl})" : "* Storybooks not built" + if (!isFinal) { + storybooksMessage = storybooksUrl ? storybooksMessage : "* Storybooks not built yet" + def failuresPart = status != 'SUCCESS' ? ', with failures' : '' messages << """ ## :hourglass_flowing_sand: Build in-progress${failuresPart} * [continuous-integration/kibana-ci/pull-request](${env.BUILD_URL}) * Commit: ${getCommitHash()} + ${storybooksMessage} * This comment will update when the build is complete """ } else if (status == 'SUCCESS') { @@ -182,6 +188,7 @@ def getNextCommentMessage(previousCommentInfo = [:], isFinal = false) { ## :green_heart: Build Succeeded * [continuous-integration/kibana-ci/pull-request](${env.BUILD_URL}) * Commit: ${getCommitHash()} + ${storybooksMessage} ${getDocsChangesLink()} """ } else if(status == 'UNSTABLE') { @@ -189,6 +196,7 @@ def getNextCommentMessage(previousCommentInfo = [:], isFinal = false) { ## :yellow_heart: Build succeeded, but was flaky * [continuous-integration/kibana-ci/pull-request](${env.BUILD_URL}) * Commit: ${getCommitHash()} + ${storybooksMessage} ${getDocsChangesLink()} """.stripIndent() @@ -204,6 +212,7 @@ def getNextCommentMessage(previousCommentInfo = [:], isFinal = false) { ## :broken_heart: Build Failed * [continuous-integration/kibana-ci/pull-request](${env.BUILD_URL}) * Commit: ${getCommitHash()} + ${storybooksMessage} * [Pipeline Steps](${env.BUILD_URL}flowGraphTable) (look for red circles / failed steps) * [Interpreting CI Failures](https://www.elastic.co/guide/en/kibana/current/interpreting-ci-failures.html) ${getDocsChangesLink()} diff --git a/vars/kibanaPipeline.groovy b/vars/kibanaPipeline.groovy index 7adf755bfc5834..1fe1d78658669a 100644 --- a/vars/kibanaPipeline.groovy +++ b/vars/kibanaPipeline.groovy @@ -460,6 +460,7 @@ def allCiTasks() { tasks.test() tasks.functionalOss() tasks.functionalXpack() + tasks.storybooksCi() } }, jest: { diff --git a/vars/storybooks.groovy b/vars/storybooks.groovy new file mode 100644 index 00000000000000..f3c4a97a7d4364 --- /dev/null +++ b/vars/storybooks.groovy @@ -0,0 +1,83 @@ +def getStorybooksBucket() { + return "ci-artifacts.kibana.dev/storybooks" +} + +def getDestinationDir() { + return env.ghprbPullId ? "pr-${env.ghprbPullId}" : buildState.get('checkoutInfo').branch.replace("/", "__") +} + +def getUrl() { + return "https://${getStorybooksBucket()}/${getDestinationDir()}" +} + +def getUrlLatest() { + return "${getUrl()}/latest" +} + +def getUrlForCommit() { + return "${getUrl()}/${buildState.get('checkoutInfo').commit}" +} + +def upload() { + dir("built_assets/storybook") { + sh "mv ci_composite composite" + + def storybooks = sh( + script: 'ls -1d */', + returnStdout: true + ).trim() + .split('\n') + .collect { it.replace('/', '') } + .findAll { it != 'composite' } + + def listHtml = storybooks.collect { """
  • ${it}
  • """ }.join("\n") + + def html = """ + + +

    Storybooks

    +

    Composite Storybook

    +

    All

    +
      + ${listHtml} +
    + + + """ + + writeFile(file: 'index.html', text: html) + + withGcpServiceAccount.fromVaultSecret('secret/kibana-issues/dev/ci-artifacts-key', 'value') { + kibanaPipeline.bash(""" + gsutil -q -m cp -r -z js,css,html,json,map,txt,svg '*' 'gs://${getStorybooksBucket()}/${getDestinationDir()}/${buildState.get('checkoutInfo').commit}/' + gsutil -h "Cache-Control:no-cache, max-age=0, no-transform" cp -z html 'index.html' 'gs://${getStorybooksBucket()}/${getDestinationDir()}/latest/' + """, "Upload Storybooks to GCS") + } + + buildState.set('storybooksUrl', getUrlForCommit()) + } +} + +def build() { + withEnv(["STORYBOOK_BASE_URL=${getUrlForCommit()}"]) { + kibanaPipeline.bash('test/scripts/jenkins_storybook.sh', 'Build Storybooks') + } +} + +def buildAndUpload() { + def sha = buildState.get('checkoutInfo').commit + def context = 'Build and Publish Storybooks' + + githubCommitStatus.create(sha, 'pending', 'Building Storybooks', context) + + try { + build() + upload() + githubCommitStatus.create(sha, 'success', 'Storybooks built', context, getUrlForCommit()) + } catch(ex) { + githubCommitStatus.create(sha, 'error', 'Building Storybooks failed', context) + throw ex + } +} + +return this diff --git a/vars/tasks.groovy b/vars/tasks.groovy index 7c40966ff5e04c..846eed85fb0762 100644 --- a/vars/tasks.groovy +++ b/vars/tasks.groovy @@ -124,4 +124,10 @@ def functionalXpack(Map params = [:]) { } } +def storybooksCi() { + task { + storybooks.buildAndUpload() + } +} + return this diff --git a/x-pack/plugins/canvas/storybook/preview-head.html b/x-pack/plugins/canvas/storybook/preview-head.html index bef08a5120a36b..f8a7de6ddbaf1a 100644 --- a/x-pack/plugins/canvas/storybook/preview-head.html +++ b/x-pack/plugins/canvas/storybook/preview-head.html @@ -2,5 +2,5 @@ This file is looked for by Storybook and included in the HEAD element if it exists. This is how we load the DLL content into the Storybook UI. --> - - + + From a82b13d147d9c4124266eb856bacf8cdb9e85d21 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Thu, 18 Feb 2021 14:52:50 -0500 Subject: [PATCH 6/8] [FTSR] Convert to tasks and add jest/api integration suites (#91770) --- .ci/Jenkinsfile_flaky | 137 +++++++++++++++++++++---------------- vars/kibanaPipeline.groovy | 11 +-- 2 files changed, 85 insertions(+), 63 deletions(-) diff --git a/.ci/Jenkinsfile_flaky b/.ci/Jenkinsfile_flaky index b9880c410fc686..7eafc66465bc72 100644 --- a/.ci/Jenkinsfile_flaky +++ b/.ci/Jenkinsfile_flaky @@ -3,47 +3,39 @@ library 'kibana-pipeline-library' kibanaLibrary.load() -def CI_GROUP_PARAM = params.CI_GROUP +def TASK_PARAM = params.TASK ?: params.CI_GROUP // Looks like 'oss:ciGroup:1', 'oss:firefoxSmoke' -def JOB_PARTS = CI_GROUP_PARAM.split(':') +def JOB_PARTS = TASK_PARAM.split(':') def IS_XPACK = JOB_PARTS[0] == 'xpack' -def JOB = JOB_PARTS[1] +def JOB = JOB_PARTS.size() > 1 ? JOB_PARTS[1] : JOB_PARTS[0] def CI_GROUP = JOB_PARTS.size() > 2 ? JOB_PARTS[2] : '' def EXECUTIONS = params.NUMBER_EXECUTIONS.toInteger() def AGENT_COUNT = getAgentCount(EXECUTIONS) - -def worker = getWorkerFromParams(IS_XPACK, JOB, CI_GROUP) - -def workerFailures = [] +def NEED_BUILD = JOB != 'jestIntegration' && JOB != 'apiIntegration' currentBuild.displayName += trunc(" ${params.GITHUB_OWNER}:${params.branch_specifier}", 24) currentBuild.description = "${params.CI_GROUP}
    Agents: ${AGENT_COUNT}
    Executions: ${params.NUMBER_EXECUTIONS}" kibanaPipeline(timeoutMinutes: 180) { def agents = [:] + def workerFailures = [] + + def worker = getWorkerFromParams(IS_XPACK, JOB, CI_GROUP) + for(def agentNumber = 1; agentNumber <= AGENT_COUNT; agentNumber++) { - def agentNumberInside = agentNumber def agentExecutions = floor(EXECUTIONS/AGENT_COUNT) + (agentNumber <= EXECUTIONS%AGENT_COUNT ? 1 : 0) + agents["agent-${agentNumber}"] = { - catchErrors { - print "Agent ${agentNumberInside} - ${agentExecutions} executions" - - withEnv([ - 'IGNORE_SHIP_CI_STATS_ERROR=true', - ]) { - workers.functional('flaky-test-runner', { - if (!IS_XPACK) { - kibanaPipeline.buildOss() - if (CI_GROUP == '1') { - runbld("./test/scripts/jenkins_build_kbn_sample_panel_action.sh", "Build kbn tp sample panel action for ciGroup1") - } - } else { - kibanaPipeline.buildXpack() - } - }, getWorkerMap(agentNumberInside, agentExecutions, worker, workerFailures))() - } - } + agentProcess( + agentNumber: agentNumber, + agentExecutions: agentExecutions, + worker: worker, + workerFailures: workerFailures, + needBuild: NEED_BUILD, + isXpack: IS_XPACK, + ciGroup: CI_GROUP + ) } } @@ -59,14 +51,70 @@ kibanaPipeline(timeoutMinutes: 180) { } } +def agentProcess(Map params = [:]) { + def config = [ + agentNumber: 1, + agentExecutions: 0, + worker: {}, + workerFailures: [], + needBuild: false, + isXpack: false, + ciGroup: null, + ] + params + + catchErrors { + print "Agent ${config.agentNumber} - ${config.agentExecutions} executions" + + withEnv([ + 'IGNORE_SHIP_CI_STATS_ERROR=true', + ]) { + kibanaPipeline.withTasks([ + parallel: 20, + ]) { + task { + if (config.needBuild) { + if (!config.isXpack) { + kibanaPipeline.buildOss() + } else { + kibanaPipeline.buildXpack() + } + } + + for(def i = 0; i < config.agentExecutions; i++) { + def taskNumber = i + task({ + withEnv([ + "REMOVE_KIBANA_INSTALL_DIR=1", + ]) { + catchErrors { + try { + config.worker() + } catch (ex) { + config.workerFailures << "agent-${config.agentNumber}-${taskNumber}" + throw ex + } + } + } + }) + } + } + } + } + } +} + def getWorkerFromParams(isXpack, job, ciGroup) { if (!isXpack) { if (job == 'accessibility') { return kibanaPipeline.functionalTestProcess('kibana-accessibility', './test/scripts/jenkins_accessibility.sh') } else if (job == 'firefoxSmoke') { return kibanaPipeline.functionalTestProcess('firefoxSmoke', './test/scripts/jenkins_firefox_smoke.sh') - } else if(job == 'visualRegression') { + } else if (job == 'visualRegression') { return kibanaPipeline.functionalTestProcess('visualRegression', './test/scripts/jenkins_visual_regression.sh') + } else if (job == 'jestIntegration') { + return kibanaPipeline.scriptTaskDocker('Jest Integration Tests', 'test/scripts/test/jest_integration.sh') + } else if (job == 'apiIntegration') { + return kibanaPipeline.scriptTask('API Integration Tests', 'test/scripts/test/api_integration.sh') } else { return kibanaPipeline.ossCiGroupProcess(ciGroup) } @@ -76,45 +124,16 @@ def getWorkerFromParams(isXpack, job, ciGroup) { return kibanaPipeline.functionalTestProcess('xpack-accessibility', './test/scripts/jenkins_xpack_accessibility.sh') } else if (job == 'firefoxSmoke') { return kibanaPipeline.functionalTestProcess('xpack-firefoxSmoke', './test/scripts/jenkins_xpack_firefox_smoke.sh') - } else if(job == 'visualRegression') { + } else if (job == 'visualRegression') { return kibanaPipeline.functionalTestProcess('xpack-visualRegression', './test/scripts/jenkins_xpack_visual_regression.sh') } else { return kibanaPipeline.xpackCiGroupProcess(ciGroup) } } -def getWorkerMap(agentNumber, numberOfExecutions, worker, workerFailures, maxWorkerProcesses = 12) { - def workerMap = [:] - def numberOfWorkers = Math.min(numberOfExecutions, maxWorkerProcesses) - - for(def i = 1; i <= numberOfWorkers; i++) { - def workerExecutions = floor(numberOfExecutions/numberOfWorkers + (i <= numberOfExecutions%numberOfWorkers ? 1 : 0)) - - workerMap["agent-${agentNumber}-worker-${i}"] = { workerNumber -> - for(def j = 0; j < workerExecutions; j++) { - print "Execute agent-${agentNumber} worker-${workerNumber}: ${j}" - withEnv([ - "REMOVE_KIBANA_INSTALL_DIR=1", - ]) { - catchErrors { - try { - worker(workerNumber) - } catch (ex) { - workerFailures << "agent-${agentNumber} worker-${workerNumber}-${j}" - throw ex - } - } - } - } - } - } - - return workerMap -} - def getAgentCount(executions) { - // Increase agent count every 24 worker processess, up to 3 agents maximum - return Math.min(3, 1 + floor(executions/24)) + // Increase agent count every 20 worker processess, up to 3 agents maximum + return Math.min(3, 1 + floor(executions/20)) } def trunc(str, length) { diff --git a/vars/kibanaPipeline.groovy b/vars/kibanaPipeline.groovy index 1fe1d78658669a..466a04d9b6b39f 100644 --- a/vars/kibanaPipeline.groovy +++ b/vars/kibanaPipeline.groovy @@ -425,12 +425,13 @@ def buildXpackPlugins() { runbld('./test/scripts/jenkins_xpack_build_plugins.sh', 'Build X-Pack Plugins') } -def withTasks(Map params = [worker: [:]], Closure closure) { +def withTasks(Map params = [:], Closure closure) { catchErrors { - def config = [name: 'ci-worker', size: 'xxl', ramDisk: true] + (params.worker ?: [:]) + def config = [setupWork: {}, worker: [:], parallel: 24] + params + def workerConfig = [name: 'ci-worker', size: 'xxl', ramDisk: true] + config.worker - workers.ci(config) { - withCiTaskQueue(parallel: 24) { + workers.ci(workerConfig) { + withCiTaskQueue([parallel: config.parallel]) { parallel([ docker: { retry(2) { @@ -443,6 +444,8 @@ def withTasks(Map params = [worker: [:]], Closure closure) { xpackPlugins: { buildXpackPlugins() }, ]) + config.setupWork() + catchErrors { closure() } From 863a2d06a43ff77baf6c8978925a0cd75946924d Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Thu, 18 Feb 2021 13:58:55 -0600 Subject: [PATCH 7/8] Use correct environment in anomaly detection setup link (#91877) This was still using `uiFilters.environment` instead of environment, so the warning would never show. --- .../application/action_menu/anomaly_detection_setup_link.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/apm/public/application/action_menu/anomaly_detection_setup_link.tsx b/x-pack/plugins/apm/public/application/action_menu/anomaly_detection_setup_link.tsx index 0c1eacb6e800ca..3cb31aa10c4feb 100644 --- a/x-pack/plugins/apm/public/application/action_menu/anomaly_detection_setup_link.tsx +++ b/x-pack/plugins/apm/public/application/action_menu/anomaly_detection_setup_link.tsx @@ -30,8 +30,9 @@ export type AnomalyDetectionApiResponse = APIReturnType<'GET /api/apm/settings/a const DEFAULT_DATA = { jobs: [], hasLegacyJobs: false }; export function AnomalyDetectionSetupLink() { - const { uiFilters } = useUrlParams(); - const environment = uiFilters.environment; + const { + urlParams: { environment }, + } = useUrlParams(); const { core } = useApmPluginContext(); const canGetJobs = !!core.application.capabilities.ml?.canGetJobs; const license = useLicenseContext(); From da25d2753b2ec4b608cddf8c2a80a1e7a1f3b4f0 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Thu, 18 Feb 2021 12:36:25 -0800 Subject: [PATCH 8/8] [Alerts][Docs] Added API documentation for alerts plugin (#91067) * Added API documentation for alerts plugin * Added link to user api * fixed links * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/create.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/create.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/create.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/create.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/create.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/create.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/create.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/create.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/create.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/create.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/delete.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/delete.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/disable.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/enable.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/disable.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/update.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/enable.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/find.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/find.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/find.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/find.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/find.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/find.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/get.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/get.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/health.asciidoc Co-authored-by: Gidi Meir Morris * Update docs/api/alerts/health.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/health.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/health.asciidoc Co-authored-by: Gidi Meir Morris * Update docs/api/alerts/health.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/health.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/health.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/list.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/health.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/health.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/list.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/list.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/api/alerts/list.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * fixed due to comments * fixed due to comments * fixed due to comments * fixed links * Apply suggestions from code review Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * fixed due to comments Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: Gidi Meir Morris --- docs/api/alerts.asciidoc | 42 +++++++ docs/api/alerts/create.asciidoc | 189 ++++++++++++++++++++++++++++ docs/api/alerts/delete.asciidoc | 36 ++++++ docs/api/alerts/disable.asciidoc | 34 +++++ docs/api/alerts/enable.asciidoc | 34 +++++ docs/api/alerts/find.asciidoc | 117 +++++++++++++++++ docs/api/alerts/get.asciidoc | 70 +++++++++++ docs/api/alerts/health.asciidoc | 85 +++++++++++++ docs/api/alerts/list.asciidoc | 127 +++++++++++++++++++ docs/api/alerts/mute.asciidoc | 37 ++++++ docs/api/alerts/mute_all.asciidoc | 34 +++++ docs/api/alerts/unmute.asciidoc | 37 ++++++ docs/api/alerts/unmute_all.asciidoc | 34 +++++ docs/api/alerts/update.asciidoc | 134 ++++++++++++++++++++ docs/user/api.asciidoc | 1 + 15 files changed, 1011 insertions(+) create mode 100644 docs/api/alerts.asciidoc create mode 100644 docs/api/alerts/create.asciidoc create mode 100644 docs/api/alerts/delete.asciidoc create mode 100644 docs/api/alerts/disable.asciidoc create mode 100644 docs/api/alerts/enable.asciidoc create mode 100644 docs/api/alerts/find.asciidoc create mode 100644 docs/api/alerts/get.asciidoc create mode 100644 docs/api/alerts/health.asciidoc create mode 100644 docs/api/alerts/list.asciidoc create mode 100644 docs/api/alerts/mute.asciidoc create mode 100644 docs/api/alerts/mute_all.asciidoc create mode 100644 docs/api/alerts/unmute.asciidoc create mode 100644 docs/api/alerts/unmute_all.asciidoc create mode 100644 docs/api/alerts/update.asciidoc diff --git a/docs/api/alerts.asciidoc b/docs/api/alerts.asciidoc new file mode 100644 index 00000000000000..a19c538bcb4d7b --- /dev/null +++ b/docs/api/alerts.asciidoc @@ -0,0 +1,42 @@ +[[alerts-api]] +== Alerts APIs + +The following APIs are available for managing {kib} alerts. + +* <> to create an alert + +* <> to update the attributes for existing alerts + +* <> to retrieve a single alert by ID + +* <> to permanently remove an alert + +* <> to retrieve a paginated set of alerts by condition + +* <> to retrieve a list of all alert types + +* <> to enable a single alert by ID + +* <> to disable a single alert by ID + +* <> to mute alert instances for a single alert by ID + +* <> to unmute alert instances for a single alert by ID + +* <> to unmute all alert instances for a single alert by ID + +* <> to retrieve the health of the alerts framework + +include::alerts/create.asciidoc[] +include::alerts/update.asciidoc[] +include::alerts/get.asciidoc[] +include::alerts/delete.asciidoc[] +include::alerts/find.asciidoc[] +include::alerts/list.asciidoc[] +include::alerts/enable.asciidoc[] +include::alerts/disable.asciidoc[] +include::alerts/mute_all.asciidoc[] +include::alerts/mute.asciidoc[] +include::alerts/unmute_all.asciidoc[] +include::alerts/unmute.asciidoc[] +include::alerts/health.asciidoc[] diff --git a/docs/api/alerts/create.asciidoc b/docs/api/alerts/create.asciidoc new file mode 100644 index 00000000000000..9e188b971c9b54 --- /dev/null +++ b/docs/api/alerts/create.asciidoc @@ -0,0 +1,189 @@ +[[alerts-api-create]] +=== Create alert API +++++ +Create alert +++++ + +Create {kib} alerts. + +[[alerts-api-create-request]] +==== Request + +`POST :/api/alerts/alert` + +[[alerts-api-create-request-body]] +==== Request body + +`name`:: + (Required, string) A name to reference and search. + +`tags`:: + (Optional, string array) A list of keywords to reference and search. + +`alertTypeId`:: + (Required, string) The ID of the alert type that you want to call when the alert is scheduled to run. + +`schedule`:: + (Required, object) The schedule specifying when this alert should be run, using one of the available schedule formats specified under ++ +._Schedule Formats_. +[%collapsible%open] +===== +A schedule is structured such that the key specifies the format you wish to use and its value specifies the schedule. + +We currently support the _Interval format_ which specifies the interval in seconds, minutes, hours or days at which the alert should execute. +Example: `{ interval: "10s" }`, `{ interval: "5m" }`, `{ interval: "1h" }`, `{ interval: "1d" }`. + +There are plans to support multiple other schedule formats in the near future. +===== + +`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. + +`notifyWhen`:: + (Required, string) The condition for throttling the notification: `onActionGroupChange`, `onActiveAlert`, or `onThrottleInterval`. + +`enabled`:: + (Optional, boolean) Indicates if you want to run the alert on an interval basis after it is created. + +`consumer`:: + (Required, string) The name of the application that owns the alert. This name has to match the Kibana Feature name, as that dictates the required RBAC privileges. + +`params`:: + (Required, object) The parameters to pass to the alert type executor `params` value. This will also validate against the alert type params validator, if defined. + +`actions`:: + (Optional, object array) An array of the following action objects. ++ +.Properties of the action objects: +[%collapsible%open] +===== + `group`::: + (Required, string) Grouping actions is recommended for escalations for different types of alert instances. If you don't need this, set this value to `default`. + + `id`::: + (Required, string) The ID of the action saved object to execute. + + `actionTypeId`::: + (Required, string) The ID of the <>. + + `params`::: + (Required, object) The map to the `params` that the <> will receive. ` params` are handled as Mustache templates and passed a default set of context. +===== + + +[[alerts-api-create-request-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +[[alerts-api-create-example]] +==== Example + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/alerts/alert -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d ' +{ + "params":{ + "aggType":"avg", + "termSize":6, + "thresholdComparator":">", + "timeWindowSize":5, + "timeWindowUnit":"m", + "groupBy":"top", + "threshold":[ + 1000 + ], + "index":[ + ".test-index" + ], + "timeField":"@timestamp", + "aggField":"sheet.version", + "termField":"name.keyword" + }, + "consumer":"alerts", + "alertTypeId":".index-threshold", + "schedule":{ + "interval":"1m" + }, + "actions":[ + { + "id":"dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2", + "actionTypeId":".server-log", + "group":"threshold met", + "params":{ + "level":"info", + "message":"alert '{{alertName}}' is active for group '{{context.group}}':\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{params.timeWindowSize}}{{params.timeWindowUnit}}\n- Timestamp: {{context.date}}" + } + } + ], + "tags":[ + "cpu" + ], + "notifyWhen":"onActionGroupChange", + "name":"my alert" +}' +-------------------------------------------------- +// KIBANA + +The API returns the following: + +[source,sh] +-------------------------------------------------- +{ + "id": "41893910-6bca-11eb-9e0d-85d233e3ee35", + "notifyWhen": "onActionGroupChange", + "params": { + "aggType": "avg", + "termSize": 6, + "thresholdComparator": ">", + "timeWindowSize": 5, + "timeWindowUnit": "m", + "groupBy": "top", + "threshold": [ + 1000 + ], + "index": [ + ".kibana" + ], + "timeField": "@timestamp", + "aggField": "sheet.version", + "termField": "name.keyword" + }, + "consumer": "alerts", + "alertTypeId": ".index-threshold", + "schedule": { + "interval": "1m" + }, + "actions": [ + { + "actionTypeId": ".server-log", + "group": "threshold met", + "params": { + "level": "info", + "message": "alert {{alertName}} is active for group {{context.group}}:\n\n- Value: {{context.value}}\n- Conditions Met: {{context.conditions}} over {{params.timeWindowSize}}{{params.timeWindowUnit}}\n- Timestamp: {{context.date}}" + }, + "id": "dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2" + } + ], + "tags": [ + "cpu" + ], + "name": "my alert", + "enabled": true, + "throttle": null, + "apiKeyOwner": "elastic", + "createdBy": "elastic", + "updatedBy": "elastic", + "muteAll": false, + "mutedInstanceIds": [], + "updatedAt": "2021-02-10T18:03:19.961Z", + "createdAt": "2021-02-10T18:03:19.961Z", + "scheduledTaskId": "425b0800-6bca-11eb-9e0d-85d233e3ee35", + "executionStatus": { + "lastExecutionDate": "2021-02-10T18:03:19.966Z", + "status": "pending" + } +} +-------------------------------------------------- diff --git a/docs/api/alerts/delete.asciidoc b/docs/api/alerts/delete.asciidoc new file mode 100644 index 00000000000000..b51005daae658d --- /dev/null +++ b/docs/api/alerts/delete.asciidoc @@ -0,0 +1,36 @@ +[[alerts-api-delete]] +=== Delete alert API +++++ +Delete alert +++++ + +Permanently remove an alert. + +WARNING: Once you delete an alert, you cannot recover it. + +[[alerts-api-delete-request]] +==== Request + +`DELETE :/api/alerts/alert/` + +[[alerts-api-delete-path-params]] +==== Path parameters + +`id`:: + (Required, string) The ID of the alert that you want to remove. + +[[alerts-api-delete-response-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +==== Example + +Delete an alert with ID: + +[source,sh] +-------------------------------------------------- +$ curl -X DELETE api/alerts/alert/41893910-6bca-11eb-9e0d-85d233e3ee35 +-------------------------------------------------- +// KIBANA diff --git a/docs/api/alerts/disable.asciidoc b/docs/api/alerts/disable.asciidoc new file mode 100644 index 00000000000000..5f74c333794095 --- /dev/null +++ b/docs/api/alerts/disable.asciidoc @@ -0,0 +1,34 @@ +[[alerts-api-disable]] +=== Disable alert API +++++ +Disable alert +++++ + +Disable an alert. + +[[alerts-api-disable-request]] +==== Request + +`POST :/api/alerts/alert//_disable` + +[[alerts-api-disable-path-params]] +==== Path parameters + +`id`:: + (Required, string) The ID of the alert that you want to disable. + +[[alerts-api-disable-response-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +==== Example + +Disable an alert with ID: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/alerts/alert/41893910-6bca-11eb-9e0d-85d233e3ee35/_disable +-------------------------------------------------- +// KIBANA diff --git a/docs/api/alerts/enable.asciidoc b/docs/api/alerts/enable.asciidoc new file mode 100644 index 00000000000000..a10383f2a440d1 --- /dev/null +++ b/docs/api/alerts/enable.asciidoc @@ -0,0 +1,34 @@ +[[alerts-api-enable]] +=== Enable alert API +++++ +Enable alert +++++ + +Enable an alert. + +[[alerts-api-enable-request]] +==== Request + +`POST :/api/alerts/alert//_enable` + +[[alerts-api-enable-path-params]] +==== Path parameters + +`id`:: + (Required, string) The ID of the alert that you want to enable. + +[[alerts-api-enable-response-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +==== Example + +Enable an alert with ID: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/alerts/alert/41893910-6bca-11eb-9e0d-85d233e3ee35/_enable +-------------------------------------------------- +// KIBANA diff --git a/docs/api/alerts/find.asciidoc b/docs/api/alerts/find.asciidoc new file mode 100644 index 00000000000000..97cd9f4c19ba75 --- /dev/null +++ b/docs/api/alerts/find.asciidoc @@ -0,0 +1,117 @@ +[[alerts-api-find]] +=== Find alerts API +++++ +Find alerts +++++ + +Retrieve a paginated set of alerts based on condition. + +[[alerts-api-find-request]] +==== Request + +`GET :/api/alerts/_find` + +[[alerts-api-find-query-params]] +==== Query Parameters + +`per_page`:: + (Optional, number) The number of alerts to return per page. + +`page`:: + (Optional, number) The page number. + +`search`:: + (Optional, string) An Elasticsearch {ref}/query-dsl-simple-query-string-query.html[simple_query_string] query that filters the alerts in the response. + +`default_search_operator`:: + (Optional, string) The operator to use for the `simple_query_string`. The default is 'OR'. + +`search_fields`:: + (Optional, array|string) The fields to perform the `simple_query_string` parsed query against. + +`fields`:: + (Optional, array|string) The fields to return in the `attributes` key of the response. + +`sort_field`:: + (Optional, string) Sorts the response. Could be an alert fields returned in the `attributes` key of the response. + +`sort_order`:: + (Optional, string) Sort direction, either `asc` or `desc`. + +`has_reference`:: + (Optional, object) Filters the alerts that have a relations with the reference objects with the specific "type" and "ID". + +`filter`:: + (Optional, string) A <> 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 will have to define your filter, for example, savedObjectType.updatedAt > 2018-12-22. + +NOTE: As alerts change in {kib}, 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. + +[[alerts-api-find-request-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +==== Examples + +Find alerts with names that start with `my`: + +[source,sh] +-------------------------------------------------- +$ curl -X GET api/alerts/_find?search_fields=name&search=my* +-------------------------------------------------- +// KIBANA + +The API returns the following: + +[source,sh] +-------------------------------------------------- +{ + "page": 1, + "perPage": 10, + "total": 1, + "data": [ + { + "id": "0a037d60-6b62-11eb-9e0d-85d233e3ee35", + "notifyWhen": "onActionGroupChange", + "params": { + "aggType": "avg", + }, + "consumer": "alerts", + "alertTypeId": "test.alert.type", + "schedule": { + "interval": "1m" + }, + "actions": [], + "tags": [], + "name": "test alert", + "enabled": true, + "throttle": null, + "apiKeyOwner": "elastic", + "createdBy": "elastic", + "updatedBy": "elastic", + "muteAll": false, + "mutedInstanceIds": [], + "updatedAt": "2021-02-10T05:37:19.086Z", + "createdAt": "2021-02-10T05:37:19.086Z", + "scheduledTaskId": "0b092d90-6b62-11eb-9e0d-85d233e3ee35", + "executionStatus": { + "lastExecutionDate": "2021-02-10T17:55:14.262Z", + "status": "ok" + } + }, + ] +} +-------------------------------------------------- + +For parameters that accept multiple values (e.g. `fields`), repeat the +query parameter for each value: + +[source,sh] +-------------------------------------------------- +$ curl -X GET api/alerts/_find?fields=id&fields=name +-------------------------------------------------- +// KIBANA diff --git a/docs/api/alerts/get.asciidoc b/docs/api/alerts/get.asciidoc new file mode 100644 index 00000000000000..934d7466dec3d7 --- /dev/null +++ b/docs/api/alerts/get.asciidoc @@ -0,0 +1,70 @@ +[[alerts-api-get]] +=== Get alert API +++++ +Get alert +++++ + +Retrieve an alert by ID. + +[[alerts-api-get-request]] +==== Request + +`GET :/api/alerts/alert/` + +[[alerts-api-get-params]] +==== Path parameters + +`id`:: + (Required, string) The ID of the alert to retrieve. + +[[alerts-api-get-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +[[alerts-api-get-example]] +==== Example + +Retrieve the alert object with the ID `41893910-6bca-11eb-9e0d-85d233e3ee35`: + +[source,sh] +-------------------------------------------------- +$ curl -X GET api/alerts/alert/41893910-6bca-11eb-9e0d-85d233e3ee35 +-------------------------------------------------- +// KIBANA + +The API returns the following: + +[source,sh] +-------------------------------------------------- +{ + "id": "0a037d60-6b62-11eb-9e0d-85d233e3ee35", + "notifyWhen": "onActionGroupChange", + "params": { + "aggType": "avg", + }, + "consumer": "alerts", + "alertTypeId": "test.alert.type", + "schedule": { + "interval": "1m" + }, + "actions": [], + "tags": [], + "name": "test alert", + "enabled": true, + "throttle": null, + "apiKeyOwner": "elastic", + "createdBy": "elastic", + "updatedBy": "elastic", + "muteAll": false, + "mutedInstanceIds": [], + "updatedAt": "2021-02-10T05:37:19.086Z", + "createdAt": "2021-02-10T05:37:19.086Z", + "scheduledTaskId": "0b092d90-6b62-11eb-9e0d-85d233e3ee35", + "executionStatus": { + "lastExecutionDate": "2021-02-10T17:55:14.262Z", + "status": "ok" + } +} +-------------------------------------------------- diff --git a/docs/api/alerts/health.asciidoc b/docs/api/alerts/health.asciidoc new file mode 100644 index 00000000000000..3710ccf4249454 --- /dev/null +++ b/docs/api/alerts/health.asciidoc @@ -0,0 +1,85 @@ +[[alerts-api-health]] +=== Get Alerting framework health API +++++ +Get Alerting framework health +++++ + +Retrieve the health status of the Alerting framework. + +[[alerts-api-health-request]] +==== Request + +`GET :/api/alerts/_health` + +[[alerts-api-health-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +[[alerts-api-health-example]] +==== Example + +Retrieve the health status of the Alerting framework: + +[source,sh] +-------------------------------------------------- +$ curl -X GET api/alerts/_health +-------------------------------------------------- +// KIBANA + +The API returns the following: + +[source,sh] +-------------------------------------------------- +{ + "isSufficientlySecure":true, + "hasPermanentEncryptionKey":true, + "alertingFrameworkHeath":{ + "decryptionHealth":{ + "status":"ok", + "timestamp":"2021-02-10T23:35:04.949Z" + }, + "executionHealth":{ + "status":"ok", + "timestamp":"2021-02-10T23:35:04.949Z" + }, + "readHealth":{ + "status":"ok", + "timestamp":"2021-02-10T23:35:04.949Z" + } + } +} +-------------------------------------------------- + +The health API response contains the following properties: + +[cols="2*<"] +|=== + +| `isSufficientlySecure` +| Returns `false` if security is enabled, but TLS is not. + +| `hasPermanentEncryptionKey` +| Return the state `false` if Encrypted Saved Object plugin has not a permanent encryption Key. + +| `alertingFrameworkHeath` +| This state property has three substates that identify the health of the alerting framework API: `decryptionHealth`, `executionHealth`, and `readHealth`. + +|=== + +`alertingFrameworkHeath` consists of the following properties: + +[cols="2*<"] +|=== + +| `decryptionHealth` +| Returns the timestamp and status of the alert decryption: `ok`, `warn` or `error` . + +| `executionHealth` +| Returns the timestamp and status of the alert execution: `ok`, `warn` or `error`. + +| `readHealth` +| Returns the timestamp and status of the alert reading events: `ok`, `warn` or `error`. + +|=== diff --git a/docs/api/alerts/list.asciidoc b/docs/api/alerts/list.asciidoc new file mode 100644 index 00000000000000..0bc3e158ec2634 --- /dev/null +++ b/docs/api/alerts/list.asciidoc @@ -0,0 +1,127 @@ +[[alerts-api-list]] +=== List alert types API +++++ +List all alert types API +++++ + +Retrieve a list of all alert types. + +[[alerts-api-list-request]] +==== Request + +`GET :/api/alerts/list_alert_types` + +[[alerts-api-list-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +[[alerts-api-list-example]] +==== Example + +[source,sh] +-------------------------------------------------- +$ curl -X GET api/alerts/list_alert_types +-------------------------------------------------- +// KIBANA + +The API returns the following: + +[source,sh] +-------------------------------------------------- +[ + { + "id":".index-threshold", + "name":"Index threshold", + "actionGroups":[ + { + "id":"threshold met", + "name":"Threshold met" + }, + { + "id":"recovered", + "name":"Recovered" + } + ], + "recoveryActionGroup":{ + "id":"recovered", + "name":"Recovered" + }, + "defaultActionGroupId":"threshold met", + "actionVariables":{ + "context":[ + { + "name":"message", + "description":"A pre-constructed message for the alert." + }, + ], + "state":[], + "params":[ + { + "name":"threshold", + "description":"An array of values to use as the threshold; 'between' and 'notBetween' require two values, the others require one." + }, + { + "name":"index", + "description":"index" + }, + ] + }, + "producer":"stackAlerts", + "minimumLicenseRequired":"basic", + "enabledInLicense":true, + "authorizedConsumers":{ + "alerts":{ + "read":true, + "all":true + }, + "stackAlerts":{ + "read":true, + "all":true + }, + "uptime":{ + "read":true, + "all":true + } + } + } +] +-------------------------------------------------- + +Each alert type contains the following properties: + +[cols="2*<"] +|=== + +| `name` +| The descriptive name of the alert type. + +| `id` +| The unique ID of the alert type. + +| `minimumLicenseRequired` +| The license required to use the alert type. + +| `enabledInLicense` +| Whether the alert type is enabled or disabled based on the license. + +| `actionGroups` +| 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 will use this configuration to ensure that groups are valid. Use `kbn-i18n` to translate the names of the action group when registering the alert type. + +| `recoveryActionGroup` +| An action group to use when an alert instance goes from an active state, to an inactive one. Do not specify this action group under the `actionGroups` property. If `recoveryActionGroup` is not specified, the default `recovered` action group is used. + +| `defaultActionGroupId` +| The default ID for the alert type group. + +| `actionVariables` +| An explicit 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. Use `kbn-i18n` to translate the descriptions. + +| `producer` +| The ID of the application producing this alert type. + +| `authorizedConsumers` +| The list of the plugins IDs that have access to the alert type. + +|=== diff --git a/docs/api/alerts/mute.asciidoc b/docs/api/alerts/mute.asciidoc new file mode 100644 index 00000000000000..9279786deae4cf --- /dev/null +++ b/docs/api/alerts/mute.asciidoc @@ -0,0 +1,37 @@ +[[alerts-api-mute]] +=== Mute alert instance API +++++ +Mute alert instance +++++ + +Mute an alert instance. + +[[alerts-api-mute-request]] +==== Request + +`POST :/api/alerts/alert//alert_instance//_mute` + +[[alerts-api-mute-path-params]] +==== Path parameters + +`id`:: + (Required, string) The ID of the alert whose instance you want to mute. + +`alert_instance_id`:: + (Required, string) The ID of the alert instance that you want to mute. + +[[alerts-api-mute-response-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +==== Example + +Mute alert instance with ID: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/alerts/alert/41893910-6bca-11eb-9e0d-85d233e3ee35/alert_instance/dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2/_mute +-------------------------------------------------- +// KIBANA diff --git a/docs/api/alerts/mute_all.asciidoc b/docs/api/alerts/mute_all.asciidoc new file mode 100644 index 00000000000000..f8a8c137240c6b --- /dev/null +++ b/docs/api/alerts/mute_all.asciidoc @@ -0,0 +1,34 @@ +[[alerts-api-mute-all]] +=== Mute all alert instances API +++++ +Mute all alert instances +++++ + +Mute all alert instances. + +[[alerts-api-mute-all-request]] +==== Request + +`POST :/api/alerts/alert//_mute_all` + +[[alerts-api-mute-all-path-params]] +==== Path parameters + +`id`:: + (Required, string) The ID of the alert whose instances you want to mute. + +[[alerts-api-mute-all-response-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +==== Example + +Mute all alert instances with ID: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/alerts/alert/41893910-6bca-11eb-9e0d-85d233e3ee35/_mute_all +-------------------------------------------------- +// KIBANA diff --git a/docs/api/alerts/unmute.asciidoc b/docs/api/alerts/unmute.asciidoc new file mode 100644 index 00000000000000..f091ae3f453257 --- /dev/null +++ b/docs/api/alerts/unmute.asciidoc @@ -0,0 +1,37 @@ +[[alerts-api-unmute]] +=== Unmute alert instance API +++++ +Unmute alert instance +++++ + +Unmute an alert instance. + +[[alerts-api-unmute-request]] +==== Request + +`POST :/api/alerts/alert//alert_instance//_unmute` + +[[alerts-api-unmute-path-params]] +==== Path parameters + +`id`:: + (Required, string) The ID of the alert whose instance you want to mute.. + +`alert_instance_id`:: + (Required, string) The ID of the alert instance that you want to unmute. + +[[alerts-api-unmute-response-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +==== Example + +Unmute alert instance with ID: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/alerts/alert/41893910-6bca-11eb-9e0d-85d233e3ee35/alert_instance/dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2/_unmute +-------------------------------------------------- +// KIBANA diff --git a/docs/api/alerts/unmute_all.asciidoc b/docs/api/alerts/unmute_all.asciidoc new file mode 100644 index 00000000000000..2359d120cf2602 --- /dev/null +++ b/docs/api/alerts/unmute_all.asciidoc @@ -0,0 +1,34 @@ +[[alerts-api-unmute-all]] +=== Unmute all alert instances API +++++ +Unmute all alert instances +++++ + +Unmute all alert instances. + +[[alerts-api-unmute-all-request]] +==== Request + +`POST :/api/alerts/alert//_unmute_all` + +[[alerts-api-unmute-all-path-params]] +==== Path parameters + +`id`:: + (Required, string) The ID of the alert whose instances you want to unmute. + +[[alerts-api-unmute-all-response-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +==== Example + +Unmute all alert instances with ID: + +[source,sh] +-------------------------------------------------- +$ curl -X POST api/alerts/alert/41893910-6bca-11eb-9e0d-85d233e3ee35/_unmute_all +-------------------------------------------------- +// KIBANA diff --git a/docs/api/alerts/update.asciidoc b/docs/api/alerts/update.asciidoc new file mode 100644 index 00000000000000..aee2dd049a66f7 --- /dev/null +++ b/docs/api/alerts/update.asciidoc @@ -0,0 +1,134 @@ +[[alerts-api-update]] +=== Update alert API +++++ +Update alert +++++ + +Update the attributes for an existing alert. + +[[alerts-api-update-request]] +==== Request + +`PUT :/api/alerts/alert/` + +[[alerts-api-update-path-params]] +==== Path parameters + +`id`:: + (Required, string) The ID of the alert that you want to update. + +[[alerts-api-update-request-body]] +==== Request body + +`name`:: + (Required, string) A name to reference and search. + +`tags`:: + (Optional, string array) A list of keywords to reference and search. + +`schedule`:: + (Required, object) When to run this alert. Use one of the available schedule formats. ++ +._Schedule Formats_. +[%collapsible%open] +===== +A schedule uses a key: value format. {kib} currently supports the _Interval format_ , which specifies the interval in seconds, minutes, hours, or days at which to execute the alert. + +Example: `{ interval: "10s" }`, `{ interval: "5m" }`, `{ interval: "1h" }`, `{ interval: "1d" }`. + +===== + +`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. + +`notifyWhen`:: + (Required, string) The condition for throttling the notification: `onActionGroupChange`, `onActiveAlert`, or `onThrottleInterval`. + +`params`:: + (Required, object) The parameters to pass to the alert type executor `params` value. This will also validate against the alert type params validator, if defined. + +`actions`:: + (Optional, object array) An array of the following action objects. ++ +.Properties of the action objects: +[%collapsible%open] +===== + `group`::: + (Required, string) Grouping actions is recommended for escalations for different types of alert instances. If you don't need this, set the value to `default`. + + `id`::: + (Required, string) The ID of the action that saved object executes. + + `actionTypeId`::: + (Required, string) The id of the <>. + + `params`::: + (Required, object) The map to the `params` that the <> will receive. `params` are handled as Mustache templates and passed a default set of context. +===== + + +[[alerts-api-update-errors-codes]] +==== Response code + +`200`:: + Indicates a successful call. + +[[alerts-api-update-example]] +==== Example + +Update an alert with ID `ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74` with a different name: + +[source,sh] +-------------------------------------------------- +$ curl -X PUT api/alerts/alert/ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74 + +{ + "notifyWhen": "onActionGroupChange", + "params": { + "aggType": "avg", + }, + "schedule": { + "interval": "1m" + }, + "actions": [], + "tags": [], + "name": "new name", + "throttle": null, +} +-------------------------------------------------- +// KIBANA + +The API returns the following: + +[source,sh] +-------------------------------------------------- +{ + "id": "ac4e6b90-6be7-11eb-ba0d-9b1c1f912d74", + "notifyWhen": "onActionGroupChange", + "params": { + "aggType": "avg", + }, + "consumer": "alerts", + "alertTypeId": "test.alert.type", + "schedule": { + "interval": "1m" + }, + "actions": [], + "tags": [], + "name": "new name", + "enabled": true, + "throttle": null, + "apiKeyOwner": "elastic", + "createdBy": "elastic", + "updatedBy": "elastic", + "muteAll": false, + "mutedInstanceIds": [], + "updatedAt": "2021-02-10T05:37:19.086Z", + "createdAt": "2021-02-10T05:37:19.086Z", + "scheduledTaskId": "0b092d90-6b62-11eb-9e0d-85d233e3ee35", + "executionStatus": { + "lastExecutionDate": "2021-02-10T17:55:14.262Z", + "status": "ok" + } +} +-------------------------------------------------- diff --git a/docs/user/api.asciidoc b/docs/user/api.asciidoc index 2ae83bee1e06c7..9916ab42186dc6 100644 --- a/docs/user/api.asciidoc +++ b/docs/user/api.asciidoc @@ -36,6 +36,7 @@ include::{kib-repo-dir}/api/features.asciidoc[] include::{kib-repo-dir}/api/spaces-management.asciidoc[] include::{kib-repo-dir}/api/role-management.asciidoc[] include::{kib-repo-dir}/api/saved-objects.asciidoc[] +include::{kib-repo-dir}/api/alerts.asciidoc[] include::{kib-repo-dir}/api/actions-and-connectors.asciidoc[] include::{kib-repo-dir}/api/dashboard-api.asciidoc[] include::{kib-repo-dir}/api/logstash-configuration-management.asciidoc[]