From 8e53ea5c3e9efe1e693a75104dd68a42158d6629 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Thu, 14 May 2020 12:11:46 +0200 Subject: [PATCH 1/9] [Uptime] Improve overview and details page responsiveness (#65500) --- .../__snapshots__/location_map.test.tsx.snap | 4 + .../location_status_tags.test.tsx.snap | 8 +- .../monitor/location_map/location_map.tsx | 6 +- .../location_map/location_status_tags.tsx | 2 +- .../ssl_certificate.test.tsx.snap | 5 +- .../monitor_status_bar/ssl_certificate.tsx | 6 +- .../monitor_status_details/status_details.tsx | 9 +- .../overview/filter_group/filter_group.tsx | 9 +- .../overview/kuery_bar/kuery_bar.tsx | 2 +- .../__snapshots__/page_header.test.tsx.snap | 483 +++++++++--------- .../plugins/uptime/public/pages/monitor.tsx | 20 +- .../plugins/uptime/public/pages/overview.tsx | 7 +- .../uptime/public/pages/page_header.tsx | 49 +- 13 files changed, 345 insertions(+), 265 deletions(-) diff --git a/x-pack/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_map.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_map.test.tsx.snap index d782eb565ef99f..7b847782fe1ac8 100644 --- a/x-pack/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_map.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_map.test.tsx.snap @@ -4,6 +4,7 @@ exports[`LocationMap component doesnt shows warning if geo is provided 1`] = ` @@ -79,6 +80,7 @@ exports[`LocationMap component renders correctly against snapshot 1`] = ` @@ -165,6 +167,7 @@ exports[`LocationMap component renders named locations that have missing geo dat @@ -213,6 +216,7 @@ exports[`LocationMap component shows warning if geo information is missing 1`] = diff --git a/x-pack/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap index e4fe0a2725db37..f2a390792918ae 100644 --- a/x-pack/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap @@ -98,7 +98,7 @@ exports[`LocationStatusTags component renders when all locations are down 1`] = margin-top: auto; } -@media (max-width:830px) { +@media (max-width:1042px) { .c1 { display: inline-block; margin-right: 16px; @@ -213,7 +213,7 @@ exports[`LocationStatusTags component renders when all locations are up 1`] = ` margin-top: auto; } -@media (max-width:830px) { +@media (max-width:1042px) { .c1 { display: inline-block; margin-right: 16px; @@ -329,7 +329,7 @@ Array [ margin-top: auto; } -@media (max-width:830px) { +@media (max-width:1042px) { .c1 { display: inline-block; margin-right: 16px; @@ -659,7 +659,7 @@ Array [ padding-left: 18px; } -@media (max-width:830px) { +@media (max-width:1042px) { } diff --git a/x-pack/plugins/uptime/public/components/monitor/location_map/location_map.tsx b/x-pack/plugins/uptime/public/components/monitor/location_map/location_map.tsx index 27fe3a22742702..916f1cbb63e534 100644 --- a/x-pack/plugins/uptime/public/components/monitor/location_map/location_map.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/location_map/location_map.tsx @@ -30,7 +30,9 @@ const MapPanel = styled.div` const EuiFlexItemTags = styled(EuiFlexItem)` padding-top: 5px; - @media (max-width: 850px) { + @media (max-width: 1042px) { + flex-basis: 80% !important; + flex-grow: 0 !important; order: 1; } `; @@ -75,7 +77,7 @@ export const LocationMap = ({ monitorLocations }: LocationMapProps) => { return ( - + diff --git a/x-pack/plugins/uptime/public/components/monitor/location_map/location_status_tags.tsx b/x-pack/plugins/uptime/public/components/monitor/location_map/location_status_tags.tsx index 7f5f1d5c3b3236..db84fd5e2ca425 100644 --- a/x-pack/plugins/uptime/public/components/monitor/location_map/location_status_tags.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/location_map/location_status_tags.tsx @@ -25,7 +25,7 @@ const TextStyle = styled.div` const BadgeItem = styled.div` margin-bottom: 5px; white-space: nowrap; - @media (max-width: 830px) { + @media (max-width: 1042px) { display: inline-block; margin-right: 16px; } diff --git a/x-pack/plugins/uptime/public/components/monitor/monitor_status_details/__test__/__snapshots__/ssl_certificate.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/monitor_status_details/__test__/__snapshots__/ssl_certificate.test.tsx.snap index 2f4473ba54cf9f..628e1d576181eb 100644 --- a/x-pack/plugins/uptime/public/components/monitor/monitor_status_details/__test__/__snapshots__/ssl_certificate.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/monitor_status_details/__test__/__snapshots__/ssl_certificate.test.tsx.snap @@ -5,13 +5,13 @@ Array [
- Certificate + Certificate:
,
,
Certificate overview
diff --git a/x-pack/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/ssl_certificate.tsx b/x-pack/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/ssl_certificate.tsx index 734a68f00f7de6..73b58e8a33f6ba 100644 --- a/x-pack/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/ssl_certificate.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/ssl_certificate.tsx @@ -34,11 +34,11 @@ export const MonitorSSLCertificate = ({ tls }: Props) => { <> {i18n.translate('xpack.uptime.monitorStatusBar.sslCertificate.title', { - defaultMessage: 'Certificate', + defaultMessage: 'Certificate:', })} - + { - + {i18n.translate('xpack.uptime.monitorStatusBar.sslCertificate.overview', { defaultMessage: 'Certificate overview', })} diff --git a/x-pack/plugins/uptime/public/components/monitor/monitor_status_details/status_details.tsx b/x-pack/plugins/uptime/public/components/monitor/monitor_status_details/status_details.tsx index ebd16b05ecb4af..3766ac86785f71 100644 --- a/x-pack/plugins/uptime/public/components/monitor/monitor_status_details/status_details.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/monitor_status_details/status_details.tsx @@ -18,8 +18,13 @@ interface MonitorStatusDetailsProps { } const WrapFlexItem = styled(EuiFlexItem)` - @media (max-width: 1150px) { - width: 100%; + &&& { + @media (max-width: 768px) { + width: 100%; + } + @media (max-width: 1042px) { + flex-basis: 520px; + } } `; diff --git a/x-pack/plugins/uptime/public/components/overview/filter_group/filter_group.tsx b/x-pack/plugins/uptime/public/components/overview/filter_group/filter_group.tsx index f5527a17b0cda4..673f5bd08cb345 100644 --- a/x-pack/plugins/uptime/public/components/overview/filter_group/filter_group.tsx +++ b/x-pack/plugins/uptime/public/components/overview/filter_group/filter_group.tsx @@ -6,6 +6,7 @@ import React, { useState } from 'react'; import { EuiFilterGroup } from '@elastic/eui'; +import styled from 'styled-components'; import { FilterPopoverProps, FilterPopover } from './filter_popover'; import { OverviewFilters } from '../../../../common/runtime_types/overview_filters'; import { filterLabels } from './translations'; @@ -16,6 +17,10 @@ interface PresentationalComponentProps { overviewFilters: OverviewFilters; } +const Container = styled(EuiFilterGroup)` + margin-bottom: 10px; +`; + export const FilterGroupComponent: React.FC = ({ overviewFilters, loading, @@ -79,10 +84,10 @@ export const FilterGroupComponent: React.FC = ({ ]; return ( - + {filterPopoverProps.map(item => ( ))} - + ); }; diff --git a/x-pack/plugins/uptime/public/components/overview/kuery_bar/kuery_bar.tsx b/x-pack/plugins/uptime/public/components/overview/kuery_bar/kuery_bar.tsx index 792fff4c7cdca2..1ff823750a3468 100644 --- a/x-pack/plugins/uptime/public/components/overview/kuery_bar/kuery_bar.tsx +++ b/x-pack/plugins/uptime/public/components/overview/kuery_bar/kuery_bar.tsx @@ -19,7 +19,7 @@ import { } from '../../../../../../../src/plugins/data/public'; const Container = styled.div` - margin-bottom: 10px; + margin-bottom: 4px; `; interface State { diff --git a/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/page_header.test.tsx.snap b/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/page_header.test.tsx.snap index 646bfeba951dda..ec0ee120b6283a 100644 --- a/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/page_header.test.tsx.snap +++ b/x-pack/plugins/uptime/public/pages/__tests__/__snapshots__/page_header.test.tsx.snap @@ -2,11 +2,30 @@ exports[`PageHeader shallow renders extra links: page_header_with_extra_links 1`] = ` Array [ -

-
-
- -
-
+ Alerts + + +
+
+
+ +
+

+
+
+ -
-
-
-
-
-
- -
-
-
-
- -
-
-
+ Show dates + +
-
+
+
+
+ + + Refresh -
-
-
+ + +
, -
, ] @@ -199,11 +215,30 @@ Array [ exports[`PageHeader shallow renders with the date picker: page_header_with_date_picker 1`] = ` Array [ -

+
-
-
-
-
- -
-
-
-
-
+
+ + +
+
+
- - - + Show dates + +
+
+ + + +
, -
, ] @@ -331,10 +363,10 @@ Array [ exports[`PageHeader shallow renders without the date picker: page_header_no_date_picker 1`] = ` Array [

-
-
-
-
-
+ />
,
{ + const autoGeneratedId = /^auto-(icmp|http|tcp)-OX[A-F0-9]{16}-[a-f0-9]{16}/; + return autoGeneratedId.test(id); +}; + +// For monitors with no explicit ID, we display the URL instead of the +// auto-generated ID because it is difficult to derive meaning from a +// generated id like `auto-http-0X8D6082B94BBE3B8A`. +// We may deprecate this behavior in the next major release, because +// the heartbeat config will require an explicit ID. +const getPageTitle = (monId: string, selectedMonitor: Ping | null) => { + if (isAutogeneratedId(monId)) { + return selectedMonitor?.url?.full || monId; + } + return monId; +}; export const MonitorPage: React.FC = () => { const dispatch = useDispatch(); @@ -30,7 +48,7 @@ export const MonitorPage: React.FC = () => { useTrackPageview({ app: 'uptime', path: 'monitor' }); useTrackPageview({ app: 'uptime', path: 'monitor', delay: 15000 }); - const nameOrId = selectedMonitor?.monitor?.name || monitorId || ''; + const nameOrId = selectedMonitor?.monitor?.name || getPageTitle(monitorId, selectedMonitor); useBreadcrumbs([{ text: nameOrId }]); return ( <> diff --git a/x-pack/plugins/uptime/public/pages/overview.tsx b/x-pack/plugins/uptime/public/pages/overview.tsx index 639f363e6f9b13..f31edc588ff7b5 100644 --- a/x-pack/plugins/uptime/public/pages/overview.tsx +++ b/x-pack/plugins/uptime/public/pages/overview.tsx @@ -28,6 +28,9 @@ interface Props { const EuiFlexItemStyled = styled(EuiFlexItem)` && { min-width: 598px; + @media only screen and (max-width: 1128px) { + min-width: 500px; + } @media only screen and (max-width: 630px) { min-width: initial; } @@ -66,8 +69,8 @@ export const OverviewPageComponent = React.memo(({ indexPattern, setEsKueryFilte <> - - + + { - const datePickerComponent = datePicker ? ( - - - - ) : null; + const DatePickerComponent = () => + datePicker ? ( + + + + ) : null; const extraLinkComponents = !extraLinks ? null : ( - + @@ -45,18 +64,20 @@ export const PageHeader = React.memo( return ( <> - - + +

{headingText}

- - - {extraLinkComponents} - {datePickerComponent} - - + {extraLinkComponents} +
From b56070515a0777c1c9b7063370b102f232983443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Thu, 14 May 2020 11:47:46 +0100 Subject: [PATCH 2/9] [skip-ci] Remove legacy dirs from the CODEOWNERS in telemetry (#66401) --- .github/CODEOWNERS | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6f9050246a1ab1..19116977756f48 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -164,7 +164,6 @@ # Pulse /packages/kbn-analytics/ @elastic/pulse -/src/legacy/core_plugins/ui_metric/ @elastic/pulse /src/plugins/kibana_usage_collection/ @elastic/pulse /src/plugins/newsfeed/ @elastic/pulse /src/plugins/telemetry/ @elastic/pulse From 0d78b6cba6eea47548748c93ce0936aef6331094 Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Thu, 14 May 2020 13:41:25 +0200 Subject: [PATCH 3/9] [Ingest Manager] Add support for datastream to each template (#66367) All templates loaded by the Ingest Manager are now based on data streams. To test this, start the agent and ingest data and check with `GET _data_streams` that datstreams and not normal indices were created. Closes https://github.com/elastic/kibana/issues/66364 --- x-pack/plugins/ingest_manager/common/types/models/epm.ts | 3 +++ .../template/__snapshots__/template.test.ts.snap | 9 +++++++++ .../services/epm/elasticsearch/template/template.ts | 3 +++ 3 files changed, 15 insertions(+) diff --git a/x-pack/plugins/ingest_manager/common/types/models/epm.ts b/x-pack/plugins/ingest_manager/common/types/models/epm.ts index 82de90e4735f26..cc9e23dc9388f6 100644 --- a/x-pack/plugins/ingest_manager/common/types/models/epm.ts +++ b/x-pack/plugins/ingest_manager/common/types/models/epm.ts @@ -276,6 +276,9 @@ export interface IndexTemplate { mappings: object; aliases: object; }; + data_stream: { + timestamp_field: string; + }; } export interface TemplateRef { diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap index 440060aff96169..b1212cf3a6535b 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/__snapshots__/template.test.ts.snap @@ -90,6 +90,9 @@ exports[`tests loading base.yml: base.yml 1`] = ` } }, "aliases": {} + }, + "data_stream": { + "timestamp_field": "@timestamp" } } `; @@ -184,6 +187,9 @@ exports[`tests loading coredns.logs.yml: coredns.logs.yml 1`] = ` } }, "aliases": {} + }, + "data_stream": { + "timestamp_field": "@timestamp" } } `; @@ -1662,6 +1668,9 @@ exports[`tests loading system.yml: system.yml 1`] = ` } }, "aliases": {} + }, + "data_stream": { + "timestamp_field": "@timestamp" } } `; diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts index c45c7e706be588..65b5ae636612cf 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/template/template.ts @@ -294,6 +294,9 @@ function getBaseTemplate( // To be filled with the aliases that we need aliases: {}, }, + data_stream: { + timestamp_field: '@timestamp', + }, }; } From ee22fd710d616713c0e35493c831d95898cf1efd Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Thu, 14 May 2020 13:54:35 +0200 Subject: [PATCH 4/9] [APM] Reset hash history when app is mounted (#66175) --- x-pack/plugins/apm/public/application/index.tsx | 7 +++++-- x-pack/plugins/apm/public/utils/history.ts | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx index 314bd722274deb..6c1c3d3262a0ef 100644 --- a/x-pack/plugins/apm/public/application/index.tsx +++ b/x-pack/plugins/apm/public/application/index.tsx @@ -24,7 +24,7 @@ import { UpdateBreadcrumbs } from '../components/app/Main/UpdateBreadcrumbs'; import { APMIndicesPermission } from '../components/app/APMIndicesPermission'; import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPathChange'; import { routes } from '../components/app/Main/route_config'; -import { history } from '../utils/history'; +import { history, resetHistory } from '../utils/history'; import { ConfigSchema } from '..'; import 'react-vis/dist/style.css'; @@ -111,6 +111,7 @@ export const renderApp = ( { element }: AppMountParameters, config: ConfigSchema ) => { + resetHistory(); ReactDOM.render( , element ); - return () => ReactDOM.unmountComponentAtNode(element); + return () => { + ReactDOM.unmountComponentAtNode(element); + }; }; diff --git a/x-pack/plugins/apm/public/utils/history.ts b/x-pack/plugins/apm/public/utils/history.ts index 1fd62341393c97..bd2203fe920668 100644 --- a/x-pack/plugins/apm/public/utils/history.ts +++ b/x-pack/plugins/apm/public/utils/history.ts @@ -8,6 +8,10 @@ import { createHashHistory } from 'history'; // Make history singleton available across APM project // TODO: Explore using React context or hook instead? -const history = createHashHistory(); +let history = createHashHistory(); + +export const resetHistory = () => { + history = createHashHistory(); +}; export { history }; From 9981ef6f0725c178adf4e9c686abe36ecaed44af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Thu, 14 May 2020 14:19:51 +0200 Subject: [PATCH 5/9] [APM] Show `trace.id` in metadata table (#66376) Co-authored-by: Elastic Machine --- .../shared/MetadataTable/ErrorMetadata/sections.ts | 6 +++++- .../shared/MetadataTable/SpanMetadata/sections.ts | 4 ++-- .../shared/MetadataTable/TransactionMetadata/sections.ts | 4 +++- .../apm/public/components/shared/MetadataTable/sections.ts | 3 ++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts index 1eeebc8543d72f..2c0d73f68760de 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts @@ -16,11 +16,15 @@ import { AGENT, URL, USER, - CUSTOM_ERROR + CUSTOM_ERROR, + TRACE, + TRANSACTION } from '../sections'; export const ERROR_METADATA_SECTIONS: Section[] = [ { ...LABELS, required: true }, + TRACE, + TRANSACTION, ERROR, HTTP, HOST, diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts index 5a83a9bf4ef9e1..f8d14707f164df 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/SpanMetadata/sections.ts @@ -17,9 +17,9 @@ import { export const SPAN_METADATA_SECTIONS: Section[] = [ LABELS, - SPAN, - TRANSACTION, TRACE, + TRANSACTION, + SPAN, SERVICE, MESSAGE_SPAN, AGENT diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts index 3a9a21356ba35a..69d934e588e9d4 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts @@ -20,11 +20,13 @@ import { USER, USER_AGENT, CUSTOM_TRANSACTION, - MESSAGE_TRANSACTION + MESSAGE_TRANSACTION, + TRACE } from '../sections'; export const TRANSACTION_METADATA_SECTIONS: Section[] = [ { ...LABELS, required: true }, + TRACE, TRANSACTION, HTTP, HOST, diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/sections.ts index d6c0a72b8bb084..a41651a454b350 100644 --- a/x-pack/plugins/apm/public/components/shared/MetadataTable/sections.ts +++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/sections.ts @@ -118,7 +118,8 @@ export const TRACE: Section = { key: 'trace', label: i18n.translate('xpack.apm.metadataTable.section.traceLabel', { defaultMessage: 'Trace' - }) + }), + properties: ['id'] }; export const ERROR: Section = { From e2c471b9e501db9d15b9c739a0f3fe3095619ee1 Mon Sep 17 00:00:00 2001 From: Lee Drengenberg Date: Thu, 14 May 2020 08:22:59 -0500 Subject: [PATCH 6/9] Await forceLogout before deleting user and role (#66492) --- .../feature_controls/advanced_settings_security.ts | 2 +- .../apps/canvas/feature_controls/canvas_security.ts | 2 +- .../feature_controls/index_patterns_security.ts | 2 +- .../apps/infra/feature_controls/infrastructure_security.ts | 4 ++-- .../functional/apps/infra/feature_controls/logs_security.ts | 6 +++--- .../functional/apps/maps/feature_controls/maps_security.ts | 2 +- .../feature_controls/saved_objects_management_security.ts | 6 +++--- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts index b5946dcf22610b..f36f26f6151251 100644 --- a/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts +++ b/x-pack/test/functional/apps/advanced_settings/feature_controls/advanced_settings_security.ts @@ -60,10 +60,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await PageObjects.security.forceLogout(); await Promise.all([ security.role.delete('global_advanced_settings_all_role'), security.user.delete('global_advanced_settings_all_user'), - PageObjects.security.forceLogout(), ]); }); diff --git a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts index 71c10bd8248be8..57f198d204764a 100644 --- a/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts +++ b/x-pack/test/functional/apps/canvas/feature_controls/canvas_security.ts @@ -57,10 +57,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await PageObjects.security.forceLogout(); await Promise.all([ security.role.delete('global_canvas_all_role'), security.user.delete('global_canvas_all_user'), - PageObjects.security.forceLogout(), ]); }); diff --git a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts index 25ef24f6bfd393..008590c9c8dc1f 100644 --- a/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts +++ b/x-pack/test/functional/apps/index_patterns/feature_controls/index_patterns_security.ts @@ -62,10 +62,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await PageObjects.security.forceLogout(); await Promise.all([ security.role.delete('global_index_patterns_all_role'), security.user.delete('global_index_patterns_all_user'), - PageObjects.security.forceLogout(), ]); }); diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts index ede77b7d9afa7f..1520621312b08f 100644 --- a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts +++ b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts @@ -52,10 +52,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await PageObjects.security.forceLogout(); await Promise.all([ security.role.delete('global_infrastructure_all_role'), security.user.delete('global_infrastructure_all_user'), - PageObjects.security.forceLogout(), ]); }); @@ -168,10 +168,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await PageObjects.security.forceLogout(); await Promise.all([ security.role.delete('global_infrastructure_read_role'), security.user.delete('global_infrastructure_read_user'), - PageObjects.security.forceLogout(), ]); }); diff --git a/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts b/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts index 48ad4e90fd413f..f53f60e5c7ea7a 100644 --- a/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts +++ b/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts @@ -49,10 +49,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await PageObjects.security.forceLogout(); await Promise.all([ security.role.delete('global_logs_all_role'), security.user.delete('global_logs_all_user'), - PageObjects.security.forceLogout(), ]); }); @@ -112,10 +112,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await PageObjects.security.forceLogout(); await Promise.all([ security.role.delete('global_logs_read_role'), security.user.delete('global_logs_read_user'), - PageObjects.security.forceLogout(), ]); }); @@ -175,10 +175,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await PageObjects.security.forceLogout(); await Promise.all([ security.role.delete('global_logs_no_privileges_role'), security.user.delete('global_logs_no_privileges_user'), - PageObjects.security.forceLogout(), ]); }); diff --git a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts index ece162cbd96cc7..1651b118ea88ce 100644 --- a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts +++ b/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts @@ -57,10 +57,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await PageObjects.security.forceLogout(); await Promise.all([ security.role.delete('global_maps_all_role'), security.user.delete('global_maps_all_user'), - PageObjects.security.forceLogout(), ]); }); diff --git a/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts b/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts index d75540ae0b4a98..9fafaa6aae16b9 100644 --- a/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts +++ b/x-pack/test/functional/apps/saved_objects_management/feature_controls/saved_objects_management_security.ts @@ -52,10 +52,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await PageObjects.security.forceLogout(); await Promise.all([ security.role.delete('global_all_role'), security.user.delete('global_all_user'), - PageObjects.security.forceLogout(), ]); }); @@ -170,10 +170,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await PageObjects.security.forceLogout(); await Promise.all([ security.role.delete('global_som_read_role'), security.user.delete('global_som_read_user'), - PageObjects.security.forceLogout(), ]); }); @@ -293,10 +293,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); after(async () => { + await PageObjects.security.forceLogout(); await Promise.all([ security.role.delete('global_visualize_all_role'), security.user.delete('global_visualize_all_user'), - PageObjects.security.forceLogout(), ]); }); From 9e6ebc50a00fd7b66d4c11d2e98cd550a543b72d Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Thu, 14 May 2020 16:23:38 +0200 Subject: [PATCH 7/9] [APM] Add license guard for annotations (#65995) --- x-pack/plugins/apm/server/routes/services.ts | 13 ++-- x-pack/plugins/observability/kibana.json | 3 + .../lib/annotations/bootstrap_annotations.ts | 10 ++- .../annotations/create_annotations_client.ts | 74 +++++++++++-------- .../annotations/register_annotation_apis.ts | 26 +++++-- x-pack/scripts/functional_tests.js | 4 + x-pack/test/api_integration/apis/index.js | 2 - .../test/apm_api_integration/basic/config.ts | 14 ++++ .../basic/tests}/agent_configuration.ts | 3 +- .../basic/tests/annotations.ts | 52 +++++++++++++ .../basic/tests}/custom_link.ts | 5 +- .../basic/tests}/feature_controls.ts | 3 +- .../basic/tests}/index.ts | 8 +- .../test/apm_api_integration/common/config.ts | 38 ++++++++++ .../common/ftr_provider_context.ts | 7 ++ .../test/apm_api_integration/trial/config.ts | 14 ++++ .../trial/tests}/annotations.ts | 5 +- .../apm_api_integration/trial/tests/index.ts | 15 ++++ .../basic/config.ts | 14 ++++ .../basic/tests/annotations.ts | 51 +++++++++++++ .../basic/tests/index.ts | 15 ++++ .../common/config.ts | 38 ++++++++++ .../common/ftr_provider_context.ts | 7 ++ .../trial/config.ts | 14 ++++ .../trial/tests}/annotations.ts | 3 +- .../trial/tests/index.ts | 15 ++++ 26 files changed, 392 insertions(+), 61 deletions(-) create mode 100644 x-pack/test/apm_api_integration/basic/config.ts rename x-pack/test/{api_integration/apis/apm => apm_api_integration/basic/tests}/agent_configuration.ts (98%) create mode 100644 x-pack/test/apm_api_integration/basic/tests/annotations.ts rename x-pack/test/{api_integration/apis/apm => apm_api_integration/basic/tests}/custom_link.ts (96%) rename x-pack/test/{api_integration/apis/apm => apm_api_integration/basic/tests}/feature_controls.ts (98%) rename x-pack/test/{api_integration/apis/apm => apm_api_integration/basic/tests}/index.ts (73%) create mode 100644 x-pack/test/apm_api_integration/common/config.ts create mode 100644 x-pack/test/apm_api_integration/common/ftr_provider_context.ts create mode 100644 x-pack/test/apm_api_integration/trial/config.ts rename x-pack/test/{api_integration/apis/apm => apm_api_integration/trial/tests}/annotations.ts (98%) create mode 100644 x-pack/test/apm_api_integration/trial/tests/index.ts create mode 100644 x-pack/test/observability_api_integration/basic/config.ts create mode 100644 x-pack/test/observability_api_integration/basic/tests/annotations.ts create mode 100644 x-pack/test/observability_api_integration/basic/tests/index.ts create mode 100644 x-pack/test/observability_api_integration/common/config.ts create mode 100644 x-pack/test/observability_api_integration/common/ftr_provider_context.ts create mode 100644 x-pack/test/observability_api_integration/trial/config.ts rename x-pack/test/{api_integration/apis/observability => observability_api_integration/trial/tests}/annotations.ts (98%) create mode 100644 x-pack/test/observability_api_integration/trial/tests/index.ts diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services.ts index 474ab1c6082a44..782f8957cf188b 100644 --- a/x-pack/plugins/apm/server/routes/services.ts +++ b/x-pack/plugins/apm/server/routes/services.ts @@ -7,7 +7,6 @@ import * as t from 'io-ts'; import Boom from 'boom'; import { unique } from 'lodash'; -import { ScopedAnnotationsClient } from '../../../observability/server'; import { setupRequest } from '../lib/helpers/setup_request'; import { getServiceAgentName } from '../lib/services/get_service_agent_name'; import { getServices } from '../lib/services/get_services'; @@ -95,13 +94,10 @@ export const serviceAnnotationsRoute = createRoute(() => ({ const { serviceName } = context.params.path; const { environment } = context.params.query; - let annotationsClient: ScopedAnnotationsClient | undefined; - - if (context.plugins.observability) { - annotationsClient = await context.plugins.observability.getScopedAnnotationsClient( - request - ); - } + const annotationsClient = await context.plugins.observability?.getScopedAnnotationsClient( + context, + request + ); return getServiceAnnotations({ setup, @@ -143,6 +139,7 @@ export const serviceAnnotationsCreateRoute = createRoute(() => ({ }, handler: async ({ request, context }) => { const annotationsClient = await context.plugins.observability?.getScopedAnnotationsClient( + context, request ); diff --git a/x-pack/plugins/observability/kibana.json b/x-pack/plugins/observability/kibana.json index 8e2cfe980039ce..712a46f76bb747 100644 --- a/x-pack/plugins/observability/kibana.json +++ b/x-pack/plugins/observability/kibana.json @@ -6,6 +6,9 @@ "xpack", "observability" ], + "optionalPlugins": [ + "licensing" + ], "ui": true, "server": true } diff --git a/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts b/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts index 58639ef084ce65..6ea9f82d11ab91 100644 --- a/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts +++ b/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts @@ -3,7 +3,12 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { CoreSetup, PluginInitializerContext, KibanaRequest } from 'kibana/server'; +import { + CoreSetup, + PluginInitializerContext, + KibanaRequest, + RequestHandlerContext, +} from 'kibana/server'; import { PromiseReturnType } from '../../../typings/common'; import { createAnnotationsClient } from './create_annotations_client'; import { registerAnnotationAPIs } from './register_annotation_apis'; @@ -31,11 +36,12 @@ export async function bootstrapAnnotations({ index, core, context }: Params) { }); return { - getScopedAnnotationsClient: (request: KibanaRequest) => { + getScopedAnnotationsClient: (requestContext: RequestHandlerContext, request: KibanaRequest) => { return createAnnotationsClient({ index, apiCaller: core.elasticsearch.dataClient.asScoped(request).callAsCurrentUser, logger, + license: requestContext.licensing?.license, }); }, }; diff --git a/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts b/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts index 3f2604468e17c5..71b1a42b2000d9 100644 --- a/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts +++ b/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts @@ -7,6 +7,8 @@ import { APICaller, Logger } from 'kibana/server'; import * as t from 'io-ts'; import { Client } from 'elasticsearch'; +import Boom from 'boom'; +import { ILicense } from '../../../../licensing/server'; import { createAnnotationRt, deleteAnnotationRt, @@ -40,8 +42,9 @@ export function createAnnotationsClient(params: { index: string; apiCaller: APICaller; logger: Logger; + license?: ILicense; }) { - const { index, apiCaller, logger } = params; + const { index, apiCaller, logger, license } = params; const initIndex = () => createOrUpdateIndex({ @@ -51,48 +54,59 @@ export function createAnnotationsClient(params: { logger, }); + function ensureGoldLicense any>(fn: T): T { + return ((...args) => { + if (!license?.hasAtLeast('gold')) { + throw Boom.forbidden('Annotations require at least a gold license or a trial license.'); + } + return fn(...args); + }) as T; + } + return { get index() { return index; }, - create: async ( - createParams: CreateParams - ): Promise<{ _id: string; _index: string; _source: Annotation }> => { - const indexExists = await apiCaller('indices.exists', { - index, - }); + create: ensureGoldLicense( + async ( + createParams: CreateParams + ): Promise<{ _id: string; _index: string; _source: Annotation }> => { + const indexExists = await apiCaller('indices.exists', { + index, + }); - if (!indexExists) { - await initIndex(); - } + if (!indexExists) { + await initIndex(); + } - const annotation = { - ...createParams, - event: { - created: new Date().toISOString(), - }, - }; + const annotation = { + ...createParams, + event: { + created: new Date().toISOString(), + }, + }; - const response = (await apiCaller('index', { - index, - body: annotation, - refresh: 'wait_for', - })) as IndexDocumentResponse; + const response = (await apiCaller('index', { + index, + body: annotation, + refresh: 'wait_for', + })) as IndexDocumentResponse; - return apiCaller('get', { - index, - id: response._id, - }); - }, - getById: async (getByIdParams: GetByIdParams) => { + return apiCaller('get', { + index, + id: response._id, + }); + } + ), + getById: ensureGoldLicense(async (getByIdParams: GetByIdParams) => { const { id } = getByIdParams; return apiCaller('get', { id, index, }); - }, - delete: async (deleteParams: DeleteParams) => { + }), + delete: ensureGoldLicense(async (deleteParams: DeleteParams) => { const { id } = deleteParams; const response = (await apiCaller('delete', { @@ -101,6 +115,6 @@ export function createAnnotationsClient(params: { refresh: 'wait_for', })) as PromiseReturnType; return response; - }, + }), }; } diff --git a/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts b/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts index 3c29822acd6dd0..21ebfcd6205e72 100644 --- a/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts +++ b/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts @@ -32,7 +32,7 @@ export function registerAnnotationAPIs({ handler: (params: { data: t.TypeOf; client: ScopedAnnotationsClient }) => Promise ): RequestHandler { return async (...args: Parameters) => { - const [, request, response] = args; + const [context, request, response] = args; const rt = types; @@ -56,16 +56,26 @@ export function registerAnnotationAPIs({ index, apiCaller, logger, + license: context.licensing?.license, }); - const res = await handler({ - data: validation.right, - client, - }); + try { + const res = await handler({ + data: validation.right, + client, + }); - return response.ok({ - body: res, - }); + return response.ok({ + body: res, + }); + } catch (err) { + return response.custom({ + statusCode: err.output?.statusCode ?? 500, + body: { + message: err.output?.payload?.message ?? 'An internal server error occured', + }, + }); + } }; } diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js index 3ec7776f848afd..8ea554c42d6e0d 100644 --- a/x-pack/scripts/functional_tests.js +++ b/x-pack/scripts/functional_tests.js @@ -20,6 +20,8 @@ const onlyNotInCoverageTests = [ require.resolve('../test/alerting_api_integration/basic/config.ts'), require.resolve('../test/alerting_api_integration/spaces_only/config.ts'), require.resolve('../test/alerting_api_integration/security_and_spaces/config.ts'), + require.resolve('../test/apm_api_integration/basic/config.ts'), + require.resolve('../test/apm_api_integration/trial/config.ts'), require.resolve('../test/detection_engine_api_integration/security_and_spaces/config.ts'), require.resolve('../test/detection_engine_api_integration/basic/config.ts'), require.resolve('../test/plugin_api_integration/config.ts'), @@ -29,6 +31,8 @@ const onlyNotInCoverageTests = [ require.resolve('../test/token_api_integration/config.js'), require.resolve('../test/oidc_api_integration/config.ts'), require.resolve('../test/oidc_api_integration/implicit_flow.config.ts'), + require.resolve('../test/observability_api_integration/basic/config.ts'), + require.resolve('../test/observability_api_integration/trial/config.ts'), require.resolve('../test/pki_api_integration/config.ts'), require.resolve('../test/login_selector_api_integration/config.ts'), require.resolve('../test/encrypted_saved_objects_api_integration/config.ts'), diff --git a/x-pack/test/api_integration/apis/index.js b/x-pack/test/api_integration/apis/index.js index 75fa90bb4c3fe8..321fbce52a75a5 100644 --- a/x-pack/test/api_integration/apis/index.js +++ b/x-pack/test/api_integration/apis/index.js @@ -23,7 +23,6 @@ export default function({ loadTestFile }) { loadTestFile(require.resolve('./management')); loadTestFile(require.resolve('./uptime')); loadTestFile(require.resolve('./maps')); - loadTestFile(require.resolve('./apm')); loadTestFile(require.resolve('./siem')); loadTestFile(require.resolve('./short_urls')); loadTestFile(require.resolve('./lens')); @@ -31,6 +30,5 @@ export default function({ loadTestFile }) { loadTestFile(require.resolve('./ingest')); loadTestFile(require.resolve('./endpoint')); loadTestFile(require.resolve('./ml')); - loadTestFile(require.resolve('./observability')); }); } diff --git a/x-pack/test/apm_api_integration/basic/config.ts b/x-pack/test/apm_api_integration/basic/config.ts new file mode 100644 index 00000000000000..541fe9ec023bcf --- /dev/null +++ b/x-pack/test/apm_api_integration/basic/config.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { createTestConfig } from '../common/config'; + +// eslint-disable-next-line import/no-default-export +export default createTestConfig({ + license: 'basic', + name: 'X-Pack APM API integration tests (basic)', + testFiles: [require.resolve('./tests')], +}); diff --git a/x-pack/test/api_integration/apis/apm/agent_configuration.ts b/x-pack/test/apm_api_integration/basic/tests/agent_configuration.ts similarity index 98% rename from x-pack/test/api_integration/apis/apm/agent_configuration.ts rename to x-pack/test/apm_api_integration/basic/tests/agent_configuration.ts index 8af648e062cf44..04974d57074a56 100644 --- a/x-pack/test/api_integration/apis/apm/agent_configuration.ts +++ b/x-pack/test/apm_api_integration/basic/tests/agent_configuration.ts @@ -6,8 +6,9 @@ import expect from '@kbn/expect'; import { AgentConfigurationIntake } from '../../../../plugins/apm/common/agent_configuration/configuration_types'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +// eslint-disable-next-line import/no-default-export export default function agentConfigurationTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const log = getService('log'); diff --git a/x-pack/test/apm_api_integration/basic/tests/annotations.ts b/x-pack/test/apm_api_integration/basic/tests/annotations.ts new file mode 100644 index 00000000000000..a939ef06273569 --- /dev/null +++ b/x-pack/test/apm_api_integration/basic/tests/annotations.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { JsonObject } from 'src/plugins/kibana_utils/common'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function annotationApiTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + function request({ method, url, data }: { method: string; url: string; data?: JsonObject }) { + switch (method.toLowerCase()) { + case 'post': + return supertest + .post(url) + .send(data) + .set('kbn-xsrf', 'foo'); + + default: + throw new Error(`Unsupported methoed ${method}`); + } + } + + describe('APM annotations with a basic license', () => { + describe('when creating an annotation', () => { + it('fails with a 403 forbidden', async () => { + const response = await request({ + url: '/api/apm/services/opbeans-java/annotation', + method: 'POST', + data: { + '@timestamp': new Date().toISOString(), + message: 'New deployment', + tags: ['foo'], + service: { + version: '1.1', + environment: 'production', + }, + }, + }); + + expect(response.status).to.be(403); + expect(response.body.message).to.be( + 'Annotations require at least a gold license or a trial license.' + ); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/apm/custom_link.ts b/x-pack/test/apm_api_integration/basic/tests/custom_link.ts similarity index 96% rename from x-pack/test/api_integration/apis/apm/custom_link.ts rename to x-pack/test/apm_api_integration/basic/tests/custom_link.ts index 8aefadd8117753..910c4797f39b76 100644 --- a/x-pack/test/api_integration/apis/apm/custom_link.ts +++ b/x-pack/test/apm_api_integration/basic/tests/custom_link.ts @@ -3,13 +3,12 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -// import querystring from 'querystring'; -// import {isEmpty} from 'lodash' import URL from 'url'; import expect from '@kbn/expect'; import { CustomLink } from '../../../../plugins/apm/common/custom_link/custom_link_types'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +// eslint-disable-next-line import/no-default-export export default function customLinksTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const log = getService('log'); diff --git a/x-pack/test/api_integration/apis/apm/feature_controls.ts b/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts similarity index 98% rename from x-pack/test/api_integration/apis/apm/feature_controls.ts rename to x-pack/test/apm_api_integration/basic/tests/feature_controls.ts index 5f61c963a69aa0..f3647c65106c92 100644 --- a/x-pack/test/api_integration/apis/apm/feature_controls.ts +++ b/x-pack/test/apm_api_integration/basic/tests/feature_controls.ts @@ -5,8 +5,9 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +// eslint-disable-next-line import/no-default-export export default function featureControlsTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); diff --git a/x-pack/test/api_integration/apis/apm/index.ts b/x-pack/test/apm_api_integration/basic/tests/index.ts similarity index 73% rename from x-pack/test/api_integration/apis/apm/index.ts rename to x-pack/test/apm_api_integration/basic/tests/index.ts index de076e8c46729e..f3c1a3c3f63d56 100644 --- a/x-pack/test/api_integration/apis/apm/index.ts +++ b/x-pack/test/apm_api_integration/basic/tests/index.ts @@ -3,11 +3,13 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { FtrProviderContext } from '../../ftr_provider_context'; - +// eslint-disable-next-line import/no-default-export export default function apmApiIntegrationTests({ loadTestFile }: FtrProviderContext) { - describe('APM specs', () => { + describe('APM specs (basic)', function() { + this.tags('ciGroup1'); + loadTestFile(require.resolve('./annotations')); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./agent_configuration')); diff --git a/x-pack/test/apm_api_integration/common/config.ts b/x-pack/test/apm_api_integration/common/config.ts new file mode 100644 index 00000000000000..9e011a98bbfcd4 --- /dev/null +++ b/x-pack/test/apm_api_integration/common/config.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; + +interface Settings { + license: 'basic' | 'trial'; + testFiles: string[]; + name: string; +} + +export function createTestConfig(settings: Settings) { + const { testFiles, license, name } = settings; + + return async ({ readConfigFile }: FtrConfigProviderContext) => { + const xPackAPITestsConfig = await readConfigFile( + require.resolve('../../api_integration/config.js') + ); + + return { + testFiles, + servers: xPackAPITestsConfig.get('servers'), + services: xPackAPITestsConfig.get('services'), + junit: { + reportName: name, + }, + + esTestCluster: { + ...xPackAPITestsConfig.get('esTestCluster'), + license, + }, + kbnTestServer: xPackAPITestsConfig.get('kbnTestServer'), + }; + }; +} diff --git a/x-pack/test/apm_api_integration/common/ftr_provider_context.ts b/x-pack/test/apm_api_integration/common/ftr_provider_context.ts new file mode 100644 index 00000000000000..90600816d17114 --- /dev/null +++ b/x-pack/test/apm_api_integration/common/ftr_provider_context.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { FtrProviderContext } from '../../api_integration/ftr_provider_context'; diff --git a/x-pack/test/apm_api_integration/trial/config.ts b/x-pack/test/apm_api_integration/trial/config.ts new file mode 100644 index 00000000000000..ca5b11d469c470 --- /dev/null +++ b/x-pack/test/apm_api_integration/trial/config.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { createTestConfig } from '../common/config'; + +// eslint-disable-next-line import/no-default-export +export default createTestConfig({ + license: 'trial', + name: 'X-Pack APM API integration tests (trial)', + testFiles: [require.resolve('./tests')], +}); diff --git a/x-pack/test/api_integration/apis/apm/annotations.ts b/x-pack/test/apm_api_integration/trial/tests/annotations.ts similarity index 98% rename from x-pack/test/api_integration/apis/apm/annotations.ts rename to x-pack/test/apm_api_integration/trial/tests/annotations.ts index 4746a7713f34b3..9beea6a53dd4d4 100644 --- a/x-pack/test/api_integration/apis/apm/annotations.ts +++ b/x-pack/test/apm_api_integration/trial/tests/annotations.ts @@ -7,10 +7,11 @@ import expect from '@kbn/expect'; import { merge, cloneDeep, isPlainObject } from 'lodash'; import { JsonObject } from 'src/plugins/kibana_utils/common'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; const DEFAULT_INDEX_NAME = 'observability-annotations'; +// eslint-disable-next-line import/no-default-export export default function annotationApiTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const es = getService('es'); @@ -42,7 +43,7 @@ export default function annotationApiTests({ getService }: FtrProviderContext) { } } - describe('APM annotations', () => { + describe('APM annotations with a trial license', () => { describe('when creating an annotation', () => { afterEach(async () => { const indexExists = (await es.indices.exists({ index: DEFAULT_INDEX_NAME })).body; diff --git a/x-pack/test/apm_api_integration/trial/tests/index.ts b/x-pack/test/apm_api_integration/trial/tests/index.ts new file mode 100644 index 00000000000000..3a4571afb3d4a7 --- /dev/null +++ b/x-pack/test/apm_api_integration/trial/tests/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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function observabilityApiIntegrationTests({ loadTestFile }: FtrProviderContext) { + describe('APM specs (trial)', function() { + this.tags('ciGroup1'); + loadTestFile(require.resolve('./annotations')); + }); +} diff --git a/x-pack/test/observability_api_integration/basic/config.ts b/x-pack/test/observability_api_integration/basic/config.ts new file mode 100644 index 00000000000000..0e8bf1daaf9e61 --- /dev/null +++ b/x-pack/test/observability_api_integration/basic/config.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { createTestConfig } from '../common/config'; + +// eslint-disable-next-line import/no-default-export +export default createTestConfig({ + license: 'basic', + name: 'X-Pack Observability API integration tests (basic)', + testFiles: [require.resolve('./tests')], +}); diff --git a/x-pack/test/observability_api_integration/basic/tests/annotations.ts b/x-pack/test/observability_api_integration/basic/tests/annotations.ts new file mode 100644 index 00000000000000..cd86c8a0f2cda7 --- /dev/null +++ b/x-pack/test/observability_api_integration/basic/tests/annotations.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { JsonObject } from 'src/plugins/kibana_utils/common'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function annotationApiTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + function request({ method, url, data }: { method: string; url: string; data?: JsonObject }) { + switch (method.toLowerCase()) { + case 'post': + return supertest + .post(url) + .send(data) + .set('kbn-xsrf', 'foo'); + + default: + throw new Error(`Unsupported methoed ${method}`); + } + } + + describe('Observability annotations with a basic license', () => { + describe('when creating an annotation', () => { + it('fails with a 403 forbidden', async () => { + const response = await request({ + url: '/api/observability/annotation', + method: 'POST', + data: { + annotation: { + type: 'deployment', + }, + '@timestamp': new Date().toISOString(), + message: 'test message', + tags: ['apm'], + }, + }); + + expect(response.status).to.be(403); + expect(response.body.message).to.be( + 'Annotations require at least a gold license or a trial license.' + ); + }); + }); + }); +} diff --git a/x-pack/test/observability_api_integration/basic/tests/index.ts b/x-pack/test/observability_api_integration/basic/tests/index.ts new file mode 100644 index 00000000000000..a4c04a9229fa94 --- /dev/null +++ b/x-pack/test/observability_api_integration/basic/tests/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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function observabilityApiIntegrationTests({ loadTestFile }: FtrProviderContext) { + describe('Observability specs (basic)', function() { + this.tags('ciGroup1'); + loadTestFile(require.resolve('./annotations')); + }); +} diff --git a/x-pack/test/observability_api_integration/common/config.ts b/x-pack/test/observability_api_integration/common/config.ts new file mode 100644 index 00000000000000..9e011a98bbfcd4 --- /dev/null +++ b/x-pack/test/observability_api_integration/common/config.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; + +interface Settings { + license: 'basic' | 'trial'; + testFiles: string[]; + name: string; +} + +export function createTestConfig(settings: Settings) { + const { testFiles, license, name } = settings; + + return async ({ readConfigFile }: FtrConfigProviderContext) => { + const xPackAPITestsConfig = await readConfigFile( + require.resolve('../../api_integration/config.js') + ); + + return { + testFiles, + servers: xPackAPITestsConfig.get('servers'), + services: xPackAPITestsConfig.get('services'), + junit: { + reportName: name, + }, + + esTestCluster: { + ...xPackAPITestsConfig.get('esTestCluster'), + license, + }, + kbnTestServer: xPackAPITestsConfig.get('kbnTestServer'), + }; + }; +} diff --git a/x-pack/test/observability_api_integration/common/ftr_provider_context.ts b/x-pack/test/observability_api_integration/common/ftr_provider_context.ts new file mode 100644 index 00000000000000..90600816d17114 --- /dev/null +++ b/x-pack/test/observability_api_integration/common/ftr_provider_context.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { FtrProviderContext } from '../../api_integration/ftr_provider_context'; diff --git a/x-pack/test/observability_api_integration/trial/config.ts b/x-pack/test/observability_api_integration/trial/config.ts new file mode 100644 index 00000000000000..c073e2e6af7fed --- /dev/null +++ b/x-pack/test/observability_api_integration/trial/config.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { createTestConfig } from '../common/config'; + +// eslint-disable-next-line import/no-default-export +export default createTestConfig({ + license: 'trial', + name: 'X-Pack Observability API integration tests (trial)', + testFiles: [require.resolve('./tests')], +}); diff --git a/x-pack/test/api_integration/apis/observability/annotations.ts b/x-pack/test/observability_api_integration/trial/tests/annotations.ts similarity index 98% rename from x-pack/test/api_integration/apis/observability/annotations.ts rename to x-pack/test/observability_api_integration/trial/tests/annotations.ts index 6d32162bfcc658..ad3bcdbfabd8b3 100644 --- a/x-pack/test/api_integration/apis/observability/annotations.ts +++ b/x-pack/test/observability_api_integration/trial/tests/annotations.ts @@ -8,10 +8,11 @@ import expect from '@kbn/expect'; import { JsonObject } from 'src/plugins/kibana_utils/common'; import { Annotation } from '../../../../plugins/observability/common/annotations'; import { ESSearchHit } from '../../../../plugins/apm/typings/elasticsearch'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; const DEFAULT_INDEX_NAME = 'observability-annotations'; +// eslint-disable-next-line import/no-default-export export default function annotationApiTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const es = getService('es'); diff --git a/x-pack/test/observability_api_integration/trial/tests/index.ts b/x-pack/test/observability_api_integration/trial/tests/index.ts new file mode 100644 index 00000000000000..d1acf4d98f7f97 --- /dev/null +++ b/x-pack/test/observability_api_integration/trial/tests/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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function apmApiIntegrationTests({ loadTestFile }: FtrProviderContext) { + describe('Observability specs (trial)', function() { + this.tags('ciGroup1'); + loadTestFile(require.resolve('./annotations')); + }); +} From d2381eb8d29c7ce8a3a8c18271b83f22da58cf6d Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Thu, 14 May 2020 10:17:38 -0500 Subject: [PATCH 8/9] [Uptime] Only show ~latest checks on certs page/alert (#66349) * [Uptime] Only show ~latest checks on certs page/alert Fixes https://github.com/elastic/uptime/issues/199 Also fixes some duplicate constants used in the queries here. For default index we just use a literal `0` now since there's no way that'd ever change. * Change window to 5m * Fix dependency issues in FTR suite for certs page. * Ensures tests can run independently, and always navigate to the certs page * Ensures that the not_after field is consistent * Ensures that timespan field is always present in checked documents --- .../plugins/uptime/server/lib/alerts/tls.ts | 6 +- .../lib/requests/__tests__/get_certs.test.ts | 2 +- .../uptime/server/lib/requests/get_certs.ts | 2 +- .../uptime/server/rest_api/certs/certs.ts | 8 +-- .../apis/uptime/rest/helper/make_ping.ts | 7 ++- .../apis/uptime/rest/helper/make_tls.ts | 2 +- .../functional/apps/uptime/certificates.ts | 58 ++++++++++--------- 7 files changed, 45 insertions(+), 40 deletions(-) diff --git a/x-pack/plugins/uptime/server/lib/alerts/tls.ts b/x-pack/plugins/uptime/server/lib/alerts/tls.ts index c4464ff5752180..6aa9d1aa3c6457 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/tls.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/tls.ts @@ -12,12 +12,10 @@ import { updateState } from './common'; import { ACTION_GROUP_DEFINITIONS, DYNAMIC_SETTINGS_DEFAULTS } from '../../../common/constants'; import { Cert, CertResult } from '../../../common/runtime_types'; import { commonStateTranslations, tlsTranslations } from './translations'; +import { DEFAULT_FROM, DEFAULT_TO } from '../../rest_api/certs/certs'; const { TLS } = ACTION_GROUP_DEFINITIONS; -const DEFAULT_FROM = 'now-1d'; -const DEFAULT_TO = 'now'; -const DEFAULT_INDEX = 0; const DEFAULT_SIZE = 20; interface TlsAlertState { @@ -113,7 +111,7 @@ export const tlsAlertFactory: UptimeAlertTypeFactory = (_server, libs) => ({ dynamicSettings, from: DEFAULT_FROM, to: DEFAULT_TO, - index: DEFAULT_INDEX, + index: 0, size: DEFAULT_SIZE, notValidAfter: `now+${dynamicSettings?.certExpirationThreshold ?? DYNAMIC_SETTINGS_DEFAULTS.certExpirationThreshold}d`, diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts index 689dce98859e15..5fa5c331d398e8 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts @@ -180,7 +180,7 @@ describe('getCerts', () => { }, Object { "range": Object { - "@timestamp": Object { + "monitor.timespan": Object { "gte": "now-2d", "lte": "now+1h", }, diff --git a/x-pack/plugins/uptime/server/lib/requests/get_certs.ts b/x-pack/plugins/uptime/server/lib/requests/get_certs.ts index 57a59936ddf7c6..4793d420cbfd83 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_certs.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_certs.ts @@ -51,7 +51,7 @@ export const getCerts: UMElasticsearchQueryFn = asyn }, { range: { - '@timestamp': { + 'monitor.timespan': { gte: from, lte: to, }, diff --git a/x-pack/plugins/uptime/server/rest_api/certs/certs.ts b/x-pack/plugins/uptime/server/rest_api/certs/certs.ts index a5ca6e264d299f..fb22d603a2d56e 100644 --- a/x-pack/plugins/uptime/server/rest_api/certs/certs.ts +++ b/x-pack/plugins/uptime/server/rest_api/certs/certs.ts @@ -9,10 +9,10 @@ import { API_URLS } from '../../../common/constants'; import { UMServerLibs } from '../../lib/lib'; import { UMRestApiRouteFactory } from '../types'; -const DEFAULT_INDEX = 0; +export const DEFAULT_FROM = 'now-5m'; +export const DEFAULT_TO = 'now'; + const DEFAULT_SIZE = 25; -const DEFAULT_FROM = 'now-1d'; -const DEFAULT_TO = 'now'; const DEFAULT_SORT = 'not_after'; const DEFAULT_DIRECTION = 'asc'; @@ -31,7 +31,7 @@ export const createGetCertsRoute: UMRestApiRouteFactory = (libs: UMServerLibs) = }), }, handler: async ({ callES, dynamicSettings }, _context, request, response): Promise => { - const index = request.query?.index ?? DEFAULT_INDEX; + const index = request.query?.index ?? 0; const size = request.query?.size ?? DEFAULT_SIZE; const from = request.query?.from ?? DEFAULT_FROM; const to = request.query?.to ?? DEFAULT_TO; diff --git a/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts b/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts index 908c571e07e067..f9bea050293fc3 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts @@ -18,6 +18,7 @@ export const makePing = async ( refresh: boolean = true, tls: boolean | TlsProps = false ) => { + const timestamp = new Date(); const baseDoc: any = { tcp: { rtt: { @@ -40,7 +41,7 @@ export const makePing = async ( ephemeral_id: '0d9a8dc6-f604-49e3-86a0-d8f9d6f2cbad', version: '8.0.0', }, - '@timestamp': new Date().toISOString(), + '@timestamp': timestamp.toISOString(), resolve: { rtt: { us: 350, @@ -88,6 +89,10 @@ export const makePing = async ( check_group: uuid.v4(), type: 'http', status: 'up', + timespan: { + gte: timestamp.toISOString(), + lt: new Date(timestamp.getTime() + 5000).toISOString, + }, }, event: { dataset: 'uptime', diff --git a/x-pack/test/api_integration/apis/uptime/rest/helper/make_tls.ts b/x-pack/test/api_integration/apis/uptime/rest/helper/make_tls.ts index 36064625220245..477c9857ca3637 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/helper/make_tls.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/helper/make_tls.ts @@ -39,7 +39,7 @@ export const makeTls = ({ valid = true, commonName = '*.elastic.co', expiry, sha server: { x509: { not_before: '2020-03-01T00:00:00.000Z', - not_after: '2020-05-30T12:00:00.000Z', + not_after: expiryDate, issuer: { distinguished_name: 'CN=DigiCert SHA2 High Assurance Server CA,OU=www.digicert.com,O=DigiCert Inc,C=US', diff --git a/x-pack/test/functional/apps/uptime/certificates.ts b/x-pack/test/functional/apps/uptime/certificates.ts index 93a8a852294b23..4a10955637844a 100644 --- a/x-pack/test/functional/apps/uptime/certificates.ts +++ b/x-pack/test/functional/apps/uptime/certificates.ts @@ -14,13 +14,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const es = getService('es'); - // FLAKY: https://github.com/elastic/kibana/issues/65010 - describe.skip('certificate page', function() { - before(async () => { - await uptime.goToRoot(true); - }); - + describe('certificates', function() { beforeEach(async () => { + await uptime.goToRoot(true); await makeCheck({ es, tls: true }); await uptimeService.navigation.refreshApp(); }); @@ -30,33 +26,39 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await uptimeService.navigation.goToCertificates(); }); - it('displays certificates', async () => { - await uptimeService.cert.hasCertificates(); - }); + describe('page', () => { + beforeEach(async () => { + await uptimeService.navigation.goToCertificates(); + }); - it('displays specific certificates', async () => { - const certId = getSha256(); - const { monitorId } = await makeCheck({ - es, - tls: { - sha256: certId, - }, + it('displays certificates', async () => { + await uptimeService.cert.hasCertificates(); }); - await uptimeService.navigation.refreshApp(); - await uptimeService.cert.certificateExists({ certId, monitorId }); - }); + it('displays specific certificates', async () => { + const certId = getSha256(); + const { monitorId } = await makeCheck({ + es, + tls: { + sha256: certId, + }, + }); - it('performs search against monitor id', async () => { - const certId = getSha256(); - const { monitorId } = await makeCheck({ - es, - tls: { - sha256: certId, - }, + await uptimeService.navigation.refreshApp(); + await uptimeService.cert.certificateExists({ certId, monitorId }); + }); + + it('performs search against monitor id', async () => { + const certId = getSha256(); + const { monitorId } = await makeCheck({ + es, + tls: { + sha256: certId, + }, + }); + await uptimeService.navigation.refreshApp(); + await uptimeService.cert.searchIsWorking(monitorId); }); - await uptimeService.navigation.refreshApp(); - await uptimeService.cert.searchIsWorking(monitorId); }); }); }; From 02a2d075afce96e5ee0b3ddfba3fb0bca3cdff36 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Thu, 14 May 2020 17:46:33 +0200 Subject: [PATCH 9/9] [Discover] Catch error when popularizeField fails (#62402) * Refactor index_patterns popularize function, so no message is displayed to the user --- .../index_patterns/index_pattern.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts index 98ec4495cef29a..f3297f21c572a5 100644 --- a/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts +++ b/src/plugins/data/public/index_patterns/index_patterns/index_pattern.ts @@ -299,6 +299,13 @@ export class IndexPattern implements IIndexPattern { } async popularizeField(fieldName: string, unit = 1) { + /** + * This function is just used by Discover and it's high likely to be removed in the near future + * It doesn't use the save function to skip the error message that's displayed when + * a user adds several columns in a higher frequency that the changes can be persisted to ES + * resulting in 409 errors + */ + if (!this.id) return; const field = this.fields.getByName(fieldName); if (!field) { return; @@ -308,7 +315,15 @@ export class IndexPattern implements IIndexPattern { return; } field.count = count; - await this.save(); + + try { + const res = await this.savedObjectsClient.update(type, this.id, this.prepBody(), { + version: this.version, + }); + this.version = res._version; + } catch (e) { + // no need for an error message here + } } getNonScriptedFields() {