From f56550160663271f1c10055161d8bd25a248beac Mon Sep 17 00:00:00 2001 From: Patrick Mueller Date: Wed, 7 Apr 2021 17:30:13 -0400 Subject: [PATCH 01/49] [actions] adds proxyBypassHosts and proxyOnlyHosts Kibana config keys (#95365) (#96491) resolves https://github.com/elastic/kibana/issues/92949 This PR adds two new Kibana config keys to further customize when the proxy is used when making HTTP requests. Prior to this PR, if a proxy was set via the `xpack.actions.proxyUrl` config key, all requests would be proxied. Now, there's a further refinement in that hostnames can be added to the `xpack.actions.proxyBypassHosts` and `xpack.actions.proxyOnlyHosts` config keys. Only one of these config keys can be used at a time. If the target URL hostname of the HTTP request is listed in the `proxyBypassHosts` list, the proxy won't be used. If the target URL hostname of the HTTP request is **NOT** listed in the `proxyOnlyHosts` list, the proxy won't be used. Depending on the customer's environment, it may be easier to list the hosts to bypass, or easier to list the hosts that should only be proxied, so they can choose either method. --- docs/settings/alert-action-settings.asciidoc | 6 + .../resources/base/bin/kibana-docker | 2 + .../actions/server/actions_client.test.ts | 2 + .../actions/server/actions_config.test.ts | 79 +++++++++++ .../plugins/actions/server/actions_config.ts | 17 +-- .../lib/axios_utils.test.ts | 98 ++++++++++++- .../builtin_action_types/lib/axios_utils.ts | 2 +- .../lib/get_custom_agents.test.ts | 70 ++++++++- .../lib/get_custom_agents.ts | 25 +++- .../lib/send_email.test.ts | 134 ++++++++++++++++++ .../builtin_action_types/lib/send_email.ts | 13 +- .../server/builtin_action_types/slack.test.ts | 102 +++++++++++++ .../server/builtin_action_types/slack.ts | 8 +- x-pack/plugins/actions/server/config.test.ts | 60 +++++++- x-pack/plugins/actions/server/config.ts | 31 +++- x-pack/plugins/actions/server/plugin.ts | 4 +- x-pack/plugins/actions/server/types.ts | 2 + .../alerting_api_integration/common/config.ts | 14 +- 18 files changed, 645 insertions(+), 24 deletions(-) diff --git a/docs/settings/alert-action-settings.asciidoc b/docs/settings/alert-action-settings.asciidoc index 3645499d5f9f..08cbee8851b9 100644 --- a/docs/settings/alert-action-settings.asciidoc +++ b/docs/settings/alert-action-settings.asciidoc @@ -59,6 +59,12 @@ You can configure the following settings in the `kibana.yml` file. | `xpack.actions.proxyUrl` {ess-icon} | Specifies the proxy URL to use, if using a proxy for actions. By default, no proxy is used. +| `xpack.actions.proxyBypassHosts` {ess-icon} + | Specifies hostnames which should not use the proxy, if using a proxy for actions. The value is an array of hostnames as strings. By default, all hosts will use the proxy, but if an action's hostname is in this list, the proxy will not be used. The settings `xpack.actions.proxyBypassHosts` and `xpack.actions.proxyOnlyHosts` cannot be used at the same time. + +| `xpack.actions.proxyOnlyHosts` {ess-icon} + | Specifies hostnames which should only use the proxy, if using a proxy for actions. The value is an array of hostnames as strings. By default, no hosts will use the proxy, but if an action's hostname is in this list, the proxy will be used. The settings `xpack.actions.proxyBypassHosts` and `xpack.actions.proxyOnlyHosts` cannot be used at the same time. + | `xpack.actions.proxyHeaders` {ess-icon} | Specifies HTTP headers for the proxy, if using a proxy for actions. Defaults to {}. diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker index 503119f95f06..2c8cc185323a 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker @@ -163,6 +163,8 @@ kibana_vars=( xpack.actions.proxyHeaders xpack.actions.proxyRejectUnauthorizedCertificates xpack.actions.proxyUrl + xpack.actions.proxyBypassHosts + xpack.actions.proxyOnlyHosts xpack.actions.rejectUnauthorized xpack.alerts.healthCheck.interval xpack.alerts.invalidateApiKeysTask.interval diff --git a/x-pack/plugins/actions/server/actions_client.test.ts b/x-pack/plugins/actions/server/actions_client.test.ts index a333d86b2712..92d3b4f29d96 100644 --- a/x-pack/plugins/actions/server/actions_client.test.ts +++ b/x-pack/plugins/actions/server/actions_client.test.ts @@ -406,6 +406,8 @@ describe('create()', () => { preconfigured: {}, proxyRejectUnauthorizedCertificates: true, rejectUnauthorized: true, + proxyBypassHosts: undefined, + proxyOnlyHosts: undefined, }); const localActionTypeRegistryParams = { diff --git a/x-pack/plugins/actions/server/actions_config.test.ts b/x-pack/plugins/actions/server/actions_config.test.ts index cae6777a8244..36899f7661ba 100644 --- a/x-pack/plugins/actions/server/actions_config.test.ts +++ b/x-pack/plugins/actions/server/actions_config.test.ts @@ -253,3 +253,82 @@ describe('ensureActionTypeEnabled', () => { expect(getActionsConfigurationUtilities(config).ensureActionTypeEnabled('foo')).toBeUndefined(); }); }); + +describe('getProxySettings', () => { + test('returns undefined when no proxy URL set', () => { + const config: ActionsConfig = { + ...defaultActionsConfig, + proxyHeaders: { someHeaderName: 'some header value' }, + proxyBypassHosts: ['avoid-proxy.co'], + }; + + const proxySettings = getActionsConfigurationUtilities(config).getProxySettings(); + expect(proxySettings).toBeUndefined(); + }); + + test('returns proxy url', () => { + const config: ActionsConfig = { + ...defaultActionsConfig, + proxyUrl: 'https://proxy.elastic.co', + }; + const proxySettings = getActionsConfigurationUtilities(config).getProxySettings(); + expect(proxySettings?.proxyUrl).toBe(config.proxyUrl); + }); + + test('returns proxyRejectUnauthorizedCertificates', () => { + const configTrue: ActionsConfig = { + ...defaultActionsConfig, + proxyUrl: 'https://proxy.elastic.co', + proxyRejectUnauthorizedCertificates: true, + }; + let proxySettings = getActionsConfigurationUtilities(configTrue).getProxySettings(); + expect(proxySettings?.proxyRejectUnauthorizedCertificates).toBe(true); + + const configFalse: ActionsConfig = { + ...defaultActionsConfig, + proxyUrl: 'https://proxy.elastic.co', + proxyRejectUnauthorizedCertificates: false, + }; + proxySettings = getActionsConfigurationUtilities(configFalse).getProxySettings(); + expect(proxySettings?.proxyRejectUnauthorizedCertificates).toBe(false); + }); + + test('returns proxy headers', () => { + const proxyHeaders = { + someHeaderName: 'some header value', + someOtherHeader: 'some other header', + }; + const config: ActionsConfig = { + ...defaultActionsConfig, + proxyUrl: 'https://proxy.elastic.co', + proxyHeaders, + }; + + const proxySettings = getActionsConfigurationUtilities(config).getProxySettings(); + expect(proxySettings?.proxyHeaders).toEqual(config.proxyHeaders); + }); + + test('returns proxy bypass hosts', () => { + const proxyBypassHosts = ['proxy-bypass-1.elastic.co', 'proxy-bypass-2.elastic.co']; + const config: ActionsConfig = { + ...defaultActionsConfig, + proxyUrl: 'https://proxy.elastic.co', + proxyBypassHosts, + }; + + const proxySettings = getActionsConfigurationUtilities(config).getProxySettings(); + expect(proxySettings?.proxyBypassHosts).toEqual(new Set(proxyBypassHosts)); + }); + + test('returns proxy only hosts', () => { + const proxyOnlyHosts = ['proxy-only-1.elastic.co', 'proxy-only-2.elastic.co']; + const config: ActionsConfig = { + ...defaultActionsConfig, + proxyUrl: 'https://proxy.elastic.co', + proxyOnlyHosts, + }; + + const proxySettings = getActionsConfigurationUtilities(config).getProxySettings(); + expect(proxySettings?.proxyOnlyHosts).toEqual(new Set(proxyOnlyHosts)); + }); +}); diff --git a/x-pack/plugins/actions/server/actions_config.ts b/x-pack/plugins/actions/server/actions_config.ts index 2787f8f97110..b35a4a0d7b6c 100644 --- a/x-pack/plugins/actions/server/actions_config.ts +++ b/x-pack/plugins/actions/server/actions_config.ts @@ -11,17 +11,11 @@ import url from 'url'; import { curry } from 'lodash'; import { pipe } from 'fp-ts/lib/pipeable'; -import { ActionsConfig } from './config'; +import { ActionsConfig, AllowedHosts, EnabledActionTypes } from './config'; import { ActionTypeDisabledError } from './lib'; import { ProxySettings } from './types'; -export enum AllowedHosts { - Any = '*', -} - -export enum EnabledActionTypes { - Any = '*', -} +export { AllowedHosts, EnabledActionTypes } from './config'; enum AllowListingField { URL = 'url', @@ -93,11 +87,18 @@ function getProxySettingsFromConfig(config: ActionsConfig): undefined | ProxySet return { proxyUrl: config.proxyUrl, + proxyBypassHosts: arrayAsSet(config.proxyBypassHosts), + proxyOnlyHosts: arrayAsSet(config.proxyOnlyHosts), proxyHeaders: config.proxyHeaders, proxyRejectUnauthorizedCertificates: config.proxyRejectUnauthorizedCertificates, }; } +function arrayAsSet(arr: T[] | undefined): Set | undefined { + if (!arr) return; + return new Set(arr); +} + export function getActionsConfigurationUtilities( config: ActionsConfig ): ActionsConfigurationUtilities { diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts index 6a67f4f6752c..a932b38ede2b 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts @@ -7,12 +7,16 @@ import axios from 'axios'; import { Agent as HttpsAgent } from 'https'; +import HttpProxyAgent from 'http-proxy-agent'; +import { HttpsProxyAgent } from 'https-proxy-agent'; import { Logger } from '../../../../../../src/core/server'; import { addTimeZoneToDate, request, patch, getErrorMessage } from './axios_utils'; import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; import { actionsConfigMock } from '../../actions_config.mock'; import { getCustomAgents } from './get_custom_agents'; +const TestUrl = 'https://elastic.co/foo/bar/baz'; + const logger = loggingSystemMock.create().get() as jest.Mocked; const configurationUtilities = actionsConfigMock.create(); jest.mock('axios'); @@ -66,17 +70,19 @@ describe('request', () => { configurationUtilities.getProxySettings.mockReturnValue({ proxyRejectUnauthorizedCertificates: true, proxyUrl: 'https://localhost:1212', + proxyBypassHosts: undefined, + proxyOnlyHosts: undefined, }); - const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger); + const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger, TestUrl); const res = await request({ axios, - url: 'http://testProxy', + url: TestUrl, logger, configurationUtilities, }); - expect(axiosMock).toHaveBeenCalledWith('http://testProxy', { + expect(axiosMock).toHaveBeenCalledWith(TestUrl, { method: 'get', data: {}, httpAgent, @@ -94,6 +100,8 @@ describe('request', () => { configurationUtilities.getProxySettings.mockReturnValue({ proxyUrl: ':nope:', proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: undefined, + proxyOnlyHosts: undefined, }); const res = await request({ axios, @@ -116,6 +124,90 @@ describe('request', () => { }); }); + test('it bypasses with proxyBypassHosts when expected', async () => { + configurationUtilities.getProxySettings.mockReturnValue({ + proxyRejectUnauthorizedCertificates: true, + proxyUrl: 'https://elastic.proxy.co', + proxyBypassHosts: new Set(['elastic.co']), + proxyOnlyHosts: undefined, + }); + + await request({ + axios, + url: TestUrl, + logger, + configurationUtilities, + }); + + expect(axiosMock.mock.calls.length).toBe(1); + const { httpAgent, httpsAgent } = axiosMock.mock.calls[0][1]; + expect(httpAgent instanceof HttpProxyAgent).toBe(false); + expect(httpsAgent instanceof HttpsProxyAgent).toBe(false); + }); + + test('it does not bypass with proxyBypassHosts when expected', async () => { + configurationUtilities.getProxySettings.mockReturnValue({ + proxyRejectUnauthorizedCertificates: true, + proxyUrl: 'https://elastic.proxy.co', + proxyBypassHosts: new Set(['not-elastic.co']), + proxyOnlyHosts: undefined, + }); + + await request({ + axios, + url: TestUrl, + logger, + configurationUtilities, + }); + + expect(axiosMock.mock.calls.length).toBe(1); + const { httpAgent, httpsAgent } = axiosMock.mock.calls[0][1]; + expect(httpAgent instanceof HttpProxyAgent).toBe(true); + expect(httpsAgent instanceof HttpsProxyAgent).toBe(true); + }); + + test('it proxies with proxyOnlyHosts when expected', async () => { + configurationUtilities.getProxySettings.mockReturnValue({ + proxyRejectUnauthorizedCertificates: true, + proxyUrl: 'https://elastic.proxy.co', + proxyBypassHosts: undefined, + proxyOnlyHosts: new Set(['elastic.co']), + }); + + await request({ + axios, + url: TestUrl, + logger, + configurationUtilities, + }); + + expect(axiosMock.mock.calls.length).toBe(1); + const { httpAgent, httpsAgent } = axiosMock.mock.calls[0][1]; + expect(httpAgent instanceof HttpProxyAgent).toBe(true); + expect(httpsAgent instanceof HttpsProxyAgent).toBe(true); + }); + + test('it does not proxy with proxyOnlyHosts when expected', async () => { + configurationUtilities.getProxySettings.mockReturnValue({ + proxyRejectUnauthorizedCertificates: true, + proxyUrl: 'https://elastic.proxy.co', + proxyBypassHosts: undefined, + proxyOnlyHosts: new Set(['not-elastic.co']), + }); + + await request({ + axios, + url: TestUrl, + logger, + configurationUtilities, + }); + + expect(axiosMock.mock.calls.length).toBe(1); + const { httpAgent, httpsAgent } = axiosMock.mock.calls[0][1]; + expect(httpAgent instanceof HttpProxyAgent).toBe(false); + expect(httpsAgent instanceof HttpsProxyAgent).toBe(false); + }); + test('it fetch correctly', async () => { const res = await request({ axios, diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts index f86f3b86c506..edce36909614 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts @@ -30,7 +30,7 @@ export const request = async ({ validateStatus?: (status: number) => boolean; auth?: AxiosBasicCredentials; }): Promise => { - const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger); + const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger, url); return await axios(url, { ...rest, diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/get_custom_agents.test.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/get_custom_agents.test.ts index 340ac0f6dda3..f6d1be9bffc6 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/get_custom_agents.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/get_custom_agents.test.ts @@ -14,6 +14,10 @@ import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; import { actionsConfigMock } from '../../actions_config.mock'; const logger = loggingSystemMock.create().get() as jest.Mocked; +const targetHost = 'elastic.co'; +const targetUrl = `https://${targetHost}/foo/bar/baz`; +const nonMatchingUrl = `https://${targetHost}m/foo/bar/baz`; + describe('getCustomAgents', () => { const configurationUtilities = actionsConfigMock.create(); @@ -21,8 +25,10 @@ describe('getCustomAgents', () => { configurationUtilities.getProxySettings.mockReturnValue({ proxyUrl: 'https://someproxyhost', proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: undefined, + proxyOnlyHosts: undefined, }); - const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger); + const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger, targetUrl); expect(httpAgent instanceof HttpProxyAgent).toBeTruthy(); expect(httpsAgent instanceof HttpsProxyAgent).toBeTruthy(); }); @@ -31,15 +37,73 @@ describe('getCustomAgents', () => { configurationUtilities.getProxySettings.mockReturnValue({ proxyUrl: ':nope: not a valid URL', proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: undefined, + proxyOnlyHosts: undefined, }); - const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger); + const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger, targetUrl); expect(httpAgent).toBe(undefined); expect(httpsAgent instanceof HttpsAgent).toBeTruthy(); }); test('return default agents for undefined proxy options', () => { - const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger); + const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger, targetUrl); expect(httpAgent).toBe(undefined); expect(httpsAgent instanceof HttpsAgent).toBeTruthy(); }); + + test('returns non-proxy agents for matching proxyBypassHosts', () => { + configurationUtilities.getProxySettings.mockReturnValue({ + proxyUrl: 'https://someproxyhost', + proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: new Set([targetHost]), + proxyOnlyHosts: undefined, + }); + const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger, targetUrl); + expect(httpAgent instanceof HttpProxyAgent).toBeFalsy(); + expect(httpsAgent instanceof HttpsProxyAgent).toBeFalsy(); + }); + + test('returns proxy agents for non-matching proxyBypassHosts', () => { + configurationUtilities.getProxySettings.mockReturnValue({ + proxyUrl: 'https://someproxyhost', + proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: new Set([targetHost]), + proxyOnlyHosts: undefined, + }); + const { httpAgent, httpsAgent } = getCustomAgents( + configurationUtilities, + logger, + nonMatchingUrl + ); + expect(httpAgent instanceof HttpProxyAgent).toBeTruthy(); + expect(httpsAgent instanceof HttpsProxyAgent).toBeTruthy(); + }); + + test('returns proxy agents for matching proxyOnlyHosts', () => { + configurationUtilities.getProxySettings.mockReturnValue({ + proxyUrl: 'https://someproxyhost', + proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: undefined, + proxyOnlyHosts: new Set([targetHost]), + }); + const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger, targetUrl); + expect(httpAgent instanceof HttpProxyAgent).toBeTruthy(); + expect(httpsAgent instanceof HttpsProxyAgent).toBeTruthy(); + }); + + test('returns non-proxy agents for non-matching proxyOnlyHosts', () => { + configurationUtilities.getProxySettings.mockReturnValue({ + proxyUrl: 'https://someproxyhost', + proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: undefined, + proxyOnlyHosts: new Set([targetHost]), + }); + const { httpAgent, httpsAgent } = getCustomAgents( + configurationUtilities, + logger, + nonMatchingUrl + ); + expect(httpAgent instanceof HttpProxyAgent).toBeFalsy(); + expect(httpsAgent instanceof HttpsProxyAgent).toBeFalsy(); + }); }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/get_custom_agents.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/get_custom_agents.ts index 92ababf830aa..ff2d005f4d84 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/get_custom_agents.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/get_custom_agents.ts @@ -19,7 +19,8 @@ interface GetCustomAgentsResponse { export function getCustomAgents( configurationUtilities: ActionsConfigurationUtilities, - logger: Logger + logger: Logger, + url: string ): GetCustomAgentsResponse { const proxySettings = configurationUtilities.getProxySettings(); const defaultAgents = { @@ -33,6 +34,28 @@ export function getCustomAgents( return defaultAgents; } + let targetUrl: URL; + try { + targetUrl = new URL(url); + } catch (err) { + logger.warn(`error determining proxy state for invalid url "${url}", using default agents`); + return defaultAgents; + } + + // filter out hostnames in the proxy bypass or only lists + const { hostname } = targetUrl; + + if (proxySettings.proxyBypassHosts) { + if (proxySettings.proxyBypassHosts.has(hostname)) { + return defaultAgents; + } + } + + if (proxySettings.proxyOnlyHosts) { + if (!proxySettings.proxyOnlyHosts.has(hostname)) { + return defaultAgents; + } + } logger.debug(`Creating proxy agents for proxy: ${proxySettings.proxyUrl}`); let proxyUrl: URL; try { diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.test.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.test.ts index cc3f03f50c36..4b45c6d787cd 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.test.ts @@ -76,6 +76,8 @@ describe('send_email module', () => { { proxyUrl: 'https://example.com', proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: undefined, + proxyOnlyHosts: undefined, } ); @@ -222,6 +224,138 @@ describe('send_email module', () => { await expect(sendEmail(mockLogger, sendEmailOptions)).rejects.toThrow('wops'); }); + + test('it bypasses with proxyBypassHosts when expected', async () => { + const sendEmailOptions = getSendEmailOptionsNoAuth( + { + transport: { + host: 'example.com', + port: 1025, + }, + }, + { + proxyUrl: 'https://proxy.com', + proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: new Set(['example.com']), + proxyOnlyHosts: undefined, + } + ); + + const result = await sendEmail(mockLogger, sendEmailOptions); + expect(result).toBe(sendMailMockResult); + expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "host": "example.com", + "port": 1025, + "secure": false, + "tls": Object { + "rejectUnauthorized": false, + }, + }, + ] + `); + }); + + test('it does not bypass with proxyBypassHosts when expected', async () => { + const sendEmailOptions = getSendEmailOptionsNoAuth( + { + transport: { + host: 'example.com', + port: 1025, + }, + }, + { + proxyUrl: 'https://proxy.com', + proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: new Set(['not-example.com']), + proxyOnlyHosts: undefined, + } + ); + + const result = await sendEmail(mockLogger, sendEmailOptions); + expect(result).toBe(sendMailMockResult); + expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "headers": undefined, + "host": "example.com", + "port": 1025, + "proxy": "https://proxy.com", + "secure": false, + "tls": Object { + "rejectUnauthorized": false, + }, + }, + ] + `); + }); + + test('it proxies with proxyOnlyHosts when expected', async () => { + const sendEmailOptions = getSendEmailOptionsNoAuth( + { + transport: { + host: 'example.com', + port: 1025, + }, + }, + { + proxyUrl: 'https://proxy.com', + proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: undefined, + proxyOnlyHosts: new Set(['example.com']), + } + ); + + const result = await sendEmail(mockLogger, sendEmailOptions); + expect(result).toBe(sendMailMockResult); + expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "headers": undefined, + "host": "example.com", + "port": 1025, + "proxy": "https://proxy.com", + "secure": false, + "tls": Object { + "rejectUnauthorized": false, + }, + }, + ] + `); + }); + + test('it does not proxy with proxyOnlyHosts when expected', async () => { + const sendEmailOptions = getSendEmailOptionsNoAuth( + { + transport: { + host: 'example.com', + port: 1025, + }, + }, + { + proxyUrl: 'https://proxy.com', + proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: undefined, + proxyOnlyHosts: new Set(['not-example.com']), + } + ); + + const result = await sendEmail(mockLogger, sendEmailOptions); + expect(result).toBe(sendMailMockResult); + expect(createTransportMock.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + Object { + "host": "example.com", + "port": 1025, + "secure": false, + "tls": Object { + "rejectUnauthorized": false, + }, + }, + ] + `); + }); }); function getSendEmailOptions( diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.ts index d4905015f766..c0a254967b4f 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/send_email.ts @@ -63,6 +63,17 @@ export async function sendEmail(logger: Logger, options: SendEmailOptions): Prom }; } + let useProxy = !!proxySettings; + + if (host) { + if (proxySettings?.proxyBypassHosts && proxySettings?.proxyBypassHosts?.has(host)) { + useProxy = false; + } + if (proxySettings?.proxyOnlyHosts && !proxySettings?.proxyOnlyHosts?.has(host)) { + useProxy = false; + } + } + if (service === JSON_TRANSPORT_SERVICE) { transportConfig.jsonTransport = true; delete transportConfig.auth; @@ -73,7 +84,7 @@ export async function sendEmail(logger: Logger, options: SendEmailOptions): Prom transportConfig.port = port; transportConfig.secure = !!secure; - if (proxySettings) { + if (proxySettings && useProxy) { transportConfig.tls = { // do not fail on invalid certs if value is false rejectUnauthorized: proxySettings?.proxyRejectUnauthorizedCertificates, diff --git a/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts b/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts index 6479e29b5a76..76612696e8e5 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts @@ -195,6 +195,8 @@ describe('execute()', () => { configurationUtilities.getProxySettings.mockReturnValue({ proxyUrl: 'https://someproxyhost', proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: undefined, + proxyOnlyHosts: undefined, }); const actionTypeProxy = getActionType({ logger: mockedLogger, @@ -212,6 +214,106 @@ describe('execute()', () => { ); }); + test('ensure proxy bypass will bypass when expected', async () => { + mockedLogger.debug.mockReset(); + const configurationUtilities = actionsConfigMock.create(); + configurationUtilities.getProxySettings.mockReturnValue({ + proxyUrl: 'https://someproxyhost', + proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: new Set(['example.com']), + proxyOnlyHosts: undefined, + }); + const actionTypeProxy = getActionType({ + logger: mockedLogger, + configurationUtilities, + }); + await actionTypeProxy.executor({ + actionId: 'some-id', + services, + config: {}, + secrets: { webhookUrl: 'http://example.com' }, + params: { message: 'this invocation should succeed' }, + }); + expect(mockedLogger.debug).not.toHaveBeenCalledWith( + 'IncomingWebhook was called with proxyUrl https://someproxyhost' + ); + }); + + test('ensure proxy bypass will not bypass when expected', async () => { + mockedLogger.debug.mockReset(); + const configurationUtilities = actionsConfigMock.create(); + configurationUtilities.getProxySettings.mockReturnValue({ + proxyUrl: 'https://someproxyhost', + proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: new Set(['not-example.com']), + proxyOnlyHosts: undefined, + }); + const actionTypeProxy = getActionType({ + logger: mockedLogger, + configurationUtilities, + }); + await actionTypeProxy.executor({ + actionId: 'some-id', + services, + config: {}, + secrets: { webhookUrl: 'http://example.com' }, + params: { message: 'this invocation should succeed' }, + }); + expect(mockedLogger.debug).toHaveBeenCalledWith( + 'IncomingWebhook was called with proxyUrl https://someproxyhost' + ); + }); + + test('ensure proxy only will proxy when expected', async () => { + mockedLogger.debug.mockReset(); + const configurationUtilities = actionsConfigMock.create(); + configurationUtilities.getProxySettings.mockReturnValue({ + proxyUrl: 'https://someproxyhost', + proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: undefined, + proxyOnlyHosts: new Set(['example.com']), + }); + const actionTypeProxy = getActionType({ + logger: mockedLogger, + configurationUtilities, + }); + await actionTypeProxy.executor({ + actionId: 'some-id', + services, + config: {}, + secrets: { webhookUrl: 'http://example.com' }, + params: { message: 'this invocation should succeed' }, + }); + expect(mockedLogger.debug).toHaveBeenCalledWith( + 'IncomingWebhook was called with proxyUrl https://someproxyhost' + ); + }); + + test('ensure proxy only will not proxy when expected', async () => { + mockedLogger.debug.mockReset(); + const configurationUtilities = actionsConfigMock.create(); + configurationUtilities.getProxySettings.mockReturnValue({ + proxyUrl: 'https://someproxyhost', + proxyRejectUnauthorizedCertificates: false, + proxyBypassHosts: undefined, + proxyOnlyHosts: new Set(['not-example.com']), + }); + const actionTypeProxy = getActionType({ + logger: mockedLogger, + configurationUtilities, + }); + await actionTypeProxy.executor({ + actionId: 'some-id', + services, + config: {}, + secrets: { webhookUrl: 'http://example.com' }, + params: { message: 'this invocation should succeed' }, + }); + expect(mockedLogger.debug).not.toHaveBeenCalledWith( + 'IncomingWebhook was called with proxyUrl https://someproxyhost' + ); + }); + test('renders parameter templates as expected', async () => { expect(actionType.renderParameterTemplates).toBeTruthy(); const paramsWithTemplates = { diff --git a/x-pack/plugins/actions/server/builtin_action_types/slack.ts b/x-pack/plugins/actions/server/builtin_action_types/slack.ts index a6173229e326..d0fb4a8c4b93 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/slack.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/slack.ts @@ -7,6 +7,8 @@ import { URL } from 'url'; import { curry } from 'lodash'; +import HttpProxyAgent from 'http-proxy-agent'; +import { HttpsProxyAgent } from 'https-proxy-agent'; import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; import { IncomingWebhook, IncomingWebhookResult } from '@slack/webhook'; @@ -131,13 +133,15 @@ async function slackExecutor( const { message } = params; const proxySettings = configurationUtilities.getProxySettings(); - const customAgents = getCustomAgents(configurationUtilities, logger); + const customAgents = getCustomAgents(configurationUtilities, logger, webhookUrl); const agent = webhookUrl.toLowerCase().startsWith('https') ? customAgents.httpsAgent : customAgents.httpAgent; if (proxySettings) { - logger.debug(`IncomingWebhook was called with proxyUrl ${proxySettings.proxyUrl}`); + if (agent instanceof HttpProxyAgent || agent instanceof HttpsProxyAgent) { + logger.debug(`IncomingWebhook was called with proxyUrl ${proxySettings.proxyUrl}`); + } } try { diff --git a/x-pack/plugins/actions/server/config.test.ts b/x-pack/plugins/actions/server/config.test.ts index c90a5b2fb976..0d270512d1de 100644 --- a/x-pack/plugins/actions/server/config.test.ts +++ b/x-pack/plugins/actions/server/config.test.ts @@ -5,9 +5,17 @@ * 2.0. */ -import { configSchema } from './config'; +import { configSchema, ActionsConfig, getValidatedConfig } from './config'; +import { Logger } from '../../../..//src/core/server'; +import { loggingSystemMock } from '../../../..//src/core/server/mocks'; + +const mockLogger = loggingSystemMock.create().get() as jest.Mocked; describe('config validation', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + test('action defaults', () => { const config: Record = {}; expect(configSchema.validate(config)).toMatchInlineSnapshot(` @@ -84,6 +92,56 @@ describe('config validation', () => { `"[preconfigured]: invalid preconfigured action id \\"__proto__\\""` ); }); + + test('validates proxyBypassHosts and proxyOnlyHosts', () => { + const bypassHosts = ['bypass.elastic.co']; + const onlyHosts = ['only.elastic.co']; + let validated: ActionsConfig; + + validated = configSchema.validate({}); + expect(validated.proxyBypassHosts).toEqual(undefined); + expect(validated.proxyOnlyHosts).toEqual(undefined); + + validated = configSchema.validate({ + proxyBypassHosts: bypassHosts, + }); + expect(validated.proxyBypassHosts).toEqual(bypassHosts); + expect(validated.proxyOnlyHosts).toEqual(undefined); + + validated = configSchema.validate({ + proxyOnlyHosts: onlyHosts, + }); + expect(validated.proxyBypassHosts).toEqual(undefined); + expect(validated.proxyOnlyHosts).toEqual(onlyHosts); + }); + + test('validates proxyBypassHosts and proxyOnlyHosts used at the same time', () => { + const bypassHosts = ['bypass.elastic.co']; + const onlyHosts = ['only.elastic.co']; + const config: Record = { + proxyBypassHosts: bypassHosts, + proxyOnlyHosts: onlyHosts, + }; + + let validated: ActionsConfig; + + // the config schema validation validates with both set + validated = configSchema.validate(config); + expect(validated.proxyBypassHosts).toEqual(bypassHosts); + expect(validated.proxyOnlyHosts).toEqual(onlyHosts); + + // getValidatedConfig will warn and set onlyHosts to undefined with both set + validated = getValidatedConfig(mockLogger, validated); + expect(validated.proxyBypassHosts).toEqual(bypassHosts); + expect(validated.proxyOnlyHosts).toEqual(undefined); + expect(mockLogger.warn.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "The confgurations xpack.actions.proxyBypassHosts and xpack.actions.proxyOnlyHosts can not be used at the same time. The configuration xpack.actions.proxyOnlyHosts will be ignored.", + ], + ] + `); + }); }); // object creator that ensures we can create a property named __proto__ on an diff --git a/x-pack/plugins/actions/server/config.ts b/x-pack/plugins/actions/server/config.ts index b4f29b752957..450f03308ab0 100644 --- a/x-pack/plugins/actions/server/config.ts +++ b/x-pack/plugins/actions/server/config.ts @@ -6,7 +6,15 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; -import { AllowedHosts, EnabledActionTypes } from './actions_config'; +import { Logger } from '../../../../src/core/server'; + +export enum AllowedHosts { + Any = '*', +} + +export enum EnabledActionTypes { + Any = '*', +} const preconfiguredActionSchema = schema.object({ name: schema.string({ minLength: 1 }), @@ -36,11 +44,32 @@ export const configSchema = schema.object({ proxyUrl: schema.maybe(schema.string()), proxyHeaders: schema.maybe(schema.recordOf(schema.string(), schema.string())), proxyRejectUnauthorizedCertificates: schema.boolean({ defaultValue: true }), + proxyBypassHosts: schema.maybe(schema.arrayOf(schema.string({ hostname: true }))), + proxyOnlyHosts: schema.maybe(schema.arrayOf(schema.string({ hostname: true }))), rejectUnauthorized: schema.boolean({ defaultValue: true }), }); export type ActionsConfig = TypeOf; +// It would be nicer to add the proxyBypassHosts / proxyOnlyHosts restriction on +// simultaneous usage in the config validator directly, but there's no good way to express +// this relationship in the cloud config constraints, so we're doing it "live". +export function getValidatedConfig(logger: Logger, originalConfig: ActionsConfig): ActionsConfig { + const proxyBypassHosts = originalConfig.proxyBypassHosts; + const proxyOnlyHosts = originalConfig.proxyOnlyHosts; + + if (proxyBypassHosts && proxyOnlyHosts) { + logger.warn( + 'The confgurations xpack.actions.proxyBypassHosts and xpack.actions.proxyOnlyHosts can not be used at the same time. The configuration xpack.actions.proxyOnlyHosts will be ignored.' + ); + const tmp: Record = originalConfig; + delete tmp.proxyOnlyHosts; + return tmp as ActionsConfig; + } + + return originalConfig; +} + const invalidActionIds = new Set(['', '__proto__', 'constructor']); function validatePreconfigured(preconfigured: Record): string | undefined { diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index 5ec9241533b3..bfe3b0a09ff2 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -30,7 +30,7 @@ import { SpacesPluginStart } from '../../spaces/server'; import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; import { SecurityPluginSetup } from '../../security/server'; -import { ActionsConfig } from './config'; +import { ActionsConfig, getValidatedConfig } from './config'; import { ActionExecutor, TaskRunnerFactory, LicenseState, ILicenseState } from './lib'; import { ActionsClient } from './actions_client'; import { ActionTypeRegistry } from './action_type_registry'; @@ -141,8 +141,8 @@ export class ActionsPlugin implements Plugin(); this.logger = initContext.logger.get('actions'); + this.actionsConfig = getValidatedConfig(this.logger, initContext.config.get()); this.telemetryLogger = initContext.logger.get('usage'); this.preconfiguredActions = []; this.kibanaIndexConfig = initContext.config.legacy.get(); diff --git a/x-pack/plugins/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts index 4e3916f5d6e2..6830f013ade5 100644 --- a/x-pack/plugins/actions/server/types.ts +++ b/x-pack/plugins/actions/server/types.ts @@ -133,6 +133,8 @@ export interface ActionTaskExecutorParams { export interface ProxySettings { proxyUrl: string; + proxyBypassHosts: Set | undefined; + proxyOnlyHosts: Set | undefined; proxyHeaders?: Record; proxyRejectUnauthorizedCertificates: boolean; } diff --git a/x-pack/test/alerting_api_integration/common/config.ts b/x-pack/test/alerting_api_integration/common/config.ts index 560ff6c0b317..beb639eb4633 100644 --- a/x-pack/test/alerting_api_integration/common/config.ts +++ b/x-pack/test/alerting_api_integration/common/config.ts @@ -68,12 +68,24 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) const proxyPort = process.env.ALERTING_PROXY_PORT ?? (await getPort({ port: getPort.makeRange(6200, 6300) })); + + // If testing with proxy, also test proxyOnlyHosts for this proxy; + // all the actions are assumed to be acccessing localhost anyway. + // If not testing with proxy, set a bogus proxy up, and set the bypass + // flag for all our localhost actions to bypass it. Currently, + // security_and_spaces uses enableActionsProxy: true, and spaces_only + // uses enableActionsProxy: false. + const proxyHosts = ['localhost', 'some.non.existent.com']; const actionsProxyUrl = options.enableActionsProxy ? [ `--xpack.actions.proxyUrl=http://localhost:${proxyPort}`, + `--xpack.actions.proxyOnlyHosts=${JSON.stringify(proxyHosts)}`, '--xpack.actions.proxyRejectUnauthorizedCertificates=false', ] - : []; + : [ + `--xpack.actions.proxyUrl=http://elastic.co`, + `--xpack.actions.proxyBypassHosts=${JSON.stringify(proxyHosts)}`, + ]; return { testFiles: [require.resolve(`../${name}/tests/`)], From 199933271361525601201d6a2dccff04e4eca036 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 31 Mar 2021 18:18:22 -0700 Subject: [PATCH 02/49] skip suite failing es promotion (#96000) (cherry picked from commit 5a9cff2644208a5f7436e99104adf6304556a52b) --- .../reporting_and_security/csv_searchsource_immediate.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/reporting_api_integration/reporting_and_security/csv_searchsource_immediate.ts b/x-pack/test/reporting_api_integration/reporting_and_security/csv_searchsource_immediate.ts index 27c6a05f740b..ebc7badd88f4 100644 --- a/x-pack/test/reporting_api_integration/reporting_and_security/csv_searchsource_immediate.ts +++ b/x-pack/test/reporting_api_integration/reporting_and_security/csv_searchsource_immediate.ts @@ -31,7 +31,8 @@ export default function ({ getService }: FtrProviderContext) { }, }; - describe('CSV Generation from SearchSource', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/96000 + describe.skip('CSV Generation from SearchSource', () => { before(async () => { await kibanaServer.uiSettings.update({ 'csv:quoteValues': false, From 21e8ac241dd2f8cc66b541264d16b6e4e2ff2245 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Wed, 7 Apr 2021 17:54:31 -0400 Subject: [PATCH 03/49] handle runtime fields in validation step (#96340) (#96494) --- .../ml/common/types/data_frame_analytics.ts | 3 +- .../models/data_frame_analytics/validation.ts | 38 ++++++++++--------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/ml/common/types/data_frame_analytics.ts b/x-pack/plugins/ml/common/types/data_frame_analytics.ts index d9632f4d4a83..ff5069e7d59a 100644 --- a/x-pack/plugins/ml/common/types/data_frame_analytics.ts +++ b/x-pack/plugins/ml/common/types/data_frame_analytics.ts @@ -6,6 +6,7 @@ */ import Boom from '@hapi/boom'; +import type { estypes } from '@elastic/elasticsearch'; import { RuntimeMappings } from './fields'; import { EsErrorBody } from '../util/errors'; @@ -75,7 +76,7 @@ export interface DataFrameAnalyticsConfig { }; source: { index: IndexName | IndexName[]; - query?: any; + query?: estypes.QueryContainer; runtime_mappings?: RuntimeMappings; }; analysis: AnalysisConfig; diff --git a/x-pack/plugins/ml/server/models/data_frame_analytics/validation.ts b/x-pack/plugins/ml/server/models/data_frame_analytics/validation.ts index 3f0a02f5eaad..bbfc304958f9 100644 --- a/x-pack/plugins/ml/server/models/data_frame_analytics/validation.ts +++ b/x-pack/plugins/ml/server/models/data_frame_analytics/validation.ts @@ -195,12 +195,13 @@ function getTrainingPercentMessage(trainingDocs: number) { async function getValidationCheckMessages( asCurrentUser: IScopedClusterClient['asCurrentUser'], analyzedFields: string[], - index: string | string[], analysisConfig: AnalysisConfig, - query: estypes.QueryContainer = defaultQuery + source: DataFrameAnalyticsConfig['source'] ) { const analysisType = getAnalysisType(analysisConfig); const depVar = getDependentVar(analysisConfig); + const index = source.index; + const query = source.query || defaultQuery; const messages = []; const emptyFields: string[] = []; const percentEmptyLimit = FRACTION_EMPTY_LIMIT * 100; @@ -236,6 +237,7 @@ async function getValidationCheckMessages( size: 0, track_total_hits: true, body: { + ...(source.runtime_mappings ? { runtime_mappings: source.runtime_mappings } : {}), query, aggs, }, @@ -247,21 +249,22 @@ async function getValidationCheckMessages( if (body.aggregations) { // @ts-expect-error Object.entries(body.aggregations).forEach(([aggName, { doc_count: docCount, value }]) => { - const empty = docCount / totalDocs; + if (docCount !== undefined) { + const empty = docCount / totalDocs; + if (docCount > 0 && empty > FRACTION_EMPTY_LIMIT) { + emptyFields.push(aggName); - if (docCount > 0 && empty > FRACTION_EMPTY_LIMIT) { - emptyFields.push(aggName); - - if (aggName === depVar) { - depVarValid = false; - dependentVarWarningMessage.text = i18n.translate( - 'xpack.ml.models.dfaValidation.messages.depVarEmptyWarning', - { - defaultMessage: - 'The dependent variable has at least {percentEmpty}% empty values. It may be unsuitable for analysis.', - values: { percentEmpty: percentEmptyLimit }, - } - ); + if (aggName === depVar) { + depVarValid = false; + dependentVarWarningMessage.text = i18n.translate( + 'xpack.ml.models.dfaValidation.messages.depVarEmptyWarning', + { + defaultMessage: + 'The dependent variable has at least {percentEmpty}% empty values. It may be unsuitable for analysis.', + values: { percentEmpty: percentEmptyLimit }, + } + ); + } } } @@ -374,9 +377,8 @@ export async function validateAnalyticsJob( const messages = await getValidationCheckMessages( client.asCurrentUser, job.analyzed_fields.includes, - job.source.index, job.analysis, - job.source.query + job.source ); return messages; } From 7fdf7e1d7913c3f5ab5af1388d02a8a880702999 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 7 Apr 2021 16:04:13 -0700 Subject: [PATCH 04/49] skip suites failing es promotion (#96515) --- x-pack/test/fleet_api_integration/apis/epm/list.ts | 3 ++- .../security_solution_endpoint_api_int/apis/artifacts/index.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/x-pack/test/fleet_api_integration/apis/epm/list.ts b/x-pack/test/fleet_api_integration/apis/epm/list.ts index 5a991e52bdba..0a7002764a54 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/list.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/list.ts @@ -19,7 +19,8 @@ export default function (providerContext: FtrProviderContext) { // because `this` has to point to the Mocha context // see https://mochajs.org/#arrow-functions - describe('EPM - list', async function () { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/96515 + describe.skip('EPM - list', async function () { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('fleet/empty_fleet_server'); diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts b/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts index e1edeb780869..8ee028ae3f56 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts @@ -19,7 +19,8 @@ export default function (providerContext: FtrProviderContext) { const supertestWithoutAuth = getSupertestWithoutAuth(providerContext); let agentAccessAPIKey: string; - describe('artifact download', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/96515 + describe.skip('artifact download', () => { const esArchiverSnapshots = [ 'endpoint/artifacts/fleet_artifacts', 'endpoint/artifacts/api_feature', From 46db2d8cb74914f3dc33007ece042a9fcb53afa9 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 7 Apr 2021 19:11:21 -0400 Subject: [PATCH 05/49] [globby] normalize paths for windows support (#96476) (#96506) Co-authored-by: spalger Co-authored-by: Spencer Co-authored-by: spalger --- .../simple_kibana_platform_plugin_discovery.ts | 3 ++- .../run_failed_tests_reporter_cli.ts | 5 ++++- .../package_json/find_used_dependencies.ts | 18 ++++++++++-------- .../integration_tests/ref_output_cache.test.ts | 6 +++++- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/packages/kbn-dev-utils/src/plugins/simple_kibana_platform_plugin_discovery.ts b/packages/kbn-dev-utils/src/plugins/simple_kibana_platform_plugin_discovery.ts index 26b1a6fa2e80..2381faefbff2 100644 --- a/packages/kbn-dev-utils/src/plugins/simple_kibana_platform_plugin_discovery.ts +++ b/packages/kbn-dev-utils/src/plugins/simple_kibana_platform_plugin_discovery.ts @@ -9,6 +9,7 @@ import Path from 'path'; import globby from 'globby'; +import normalize from 'normalize-path'; import { parseKibanaPlatformPlugin } from './parse_kibana_platform_plugin'; @@ -32,7 +33,7 @@ export function simpleKibanaPlatformPluginDiscovery(scanDirs: string[], pluginPa ), ...pluginPaths.map((path) => Path.resolve(path, `kibana.json`)), ]) - ); + ).map((path) => normalize(path)); const manifestPaths = globby.sync(patterns, { absolute: true }).map((path) => // absolute paths returned from globby are using normalize or diff --git a/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts b/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts index 8ef11e2dba46..63eca93def64 100644 --- a/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts +++ b/packages/kbn-test/src/failed_tests_reporter/run_failed_tests_reporter_cli.ts @@ -11,6 +11,7 @@ import Path from 'path'; import { REPO_ROOT } from '@kbn/utils'; import { run, createFailError, createFlagError } from '@kbn/dev-utils'; import globby from 'globby'; +import normalize from 'normalize-path'; import { getFailures, TestFailure } from './get_failures'; import { GithubApi, GithubIssueMini } from './github_api'; @@ -61,7 +62,9 @@ export function runFailedTestsReporterCli() { throw createFlagError('Missing --build-url or process.env.BUILD_URL'); } - const patterns = flags._.length ? flags._ : DEFAULT_PATTERNS; + const patterns = (flags._.length ? flags._ : DEFAULT_PATTERNS).map((p) => + normalize(Path.resolve(p)) + ); log.info('Searching for reports at', patterns); const reportPaths = await globby(patterns, { absolute: true, diff --git a/src/dev/build/tasks/package_json/find_used_dependencies.ts b/src/dev/build/tasks/package_json/find_used_dependencies.ts index 3a296ec76f3e..004e17b87ac8 100644 --- a/src/dev/build/tasks/package_json/find_used_dependencies.ts +++ b/src/dev/build/tasks/package_json/find_used_dependencies.ts @@ -6,7 +6,9 @@ * Side Public License, v 1. */ +import Path from 'path'; import globby from 'globby'; +import normalize from 'normalize-path'; // @ts-ignore import { parseEntries, dependenciesParseStrategy } from '@kbn/babel-code-parser'; @@ -21,16 +23,16 @@ export async function findUsedDependencies(listedPkgDependencies: any, baseDir: // Define the entry points for the server code in order to // start here later looking for the server side dependencies const mainCodeEntries = [ - `${baseDir}/src/cli/dist.js`, - `${baseDir}/src/cli_keystore/dist.js`, - `${baseDir}/src/cli_plugin/dist.js`, + Path.resolve(baseDir, `src/cli/dist.js`), + Path.resolve(baseDir, `src/cli_keystore/dist.js`), + Path.resolve(baseDir, `src/cli_plugin/dist.js`), ]; const discoveredPluginEntries = await globby([ - `${baseDir}/src/plugins/*/server/index.js`, - `!${baseDir}/src/plugins/**/public`, - `${baseDir}/x-pack/plugins/*/server/index.js`, - `!${baseDir}/x-pack/plugins/**/public`, + normalize(Path.resolve(baseDir, `src/plugins/*/server/index.js`)), + `!${normalize(Path.resolve(baseDir, `/src/plugins/**/public`))}`, + normalize(Path.resolve(baseDir, `x-pack/plugins/*/server/index.js`)), + `!${normalize(Path.resolve(baseDir, `/x-pack/plugins/**/public`))}`, ]); // It will include entries that cannot be discovered @@ -40,7 +42,7 @@ export async function findUsedDependencies(listedPkgDependencies: any, baseDir: // Another way would be to include an index file and import all the functions // using named imports const dynamicRequiredEntries = await globby([ - `${baseDir}/src/plugins/vis_type_timelion/server/**/*.js`, + normalize(Path.resolve(baseDir, 'src/plugins/vis_type_timelion/server/**/*.js')), ]); // Compose all the needed entries diff --git a/src/dev/typescript/ref_output_cache/integration_tests/ref_output_cache.test.ts b/src/dev/typescript/ref_output_cache/integration_tests/ref_output_cache.test.ts index 2bc75785ee6a..734752923917 100644 --- a/src/dev/typescript/ref_output_cache/integration_tests/ref_output_cache.test.ts +++ b/src/dev/typescript/ref_output_cache/integration_tests/ref_output_cache.test.ts @@ -12,6 +12,7 @@ import Fs from 'fs'; import del from 'del'; import cpy from 'cpy'; import globby from 'globby'; +import normalize from 'normalize-path'; import { ToolingLog, createAbsolutePathSerializer, @@ -98,7 +99,10 @@ it('creates and extracts caches, ingoring dirs with matching merge-base file and const files = Object.fromEntries( globby - .sync(outDirs, { dot: true }) + .sync( + outDirs.map((p) => normalize(p)), + { dot: true } + ) .map((path) => [Path.relative(TMP, path), Fs.readFileSync(path, 'utf-8')]) ); From b321a557b01a543b555276dd57797aea1be506fb Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 7 Apr 2021 19:27:57 -0400 Subject: [PATCH 06/49] [Enterprise Search] Change last breadcrumb to inactive/non-linked breadcrumb (#96489) (#96509) * Update our EUI breadcrumb helper to skip generating links for the last breadcrumb in the list * Fix useEuiBreadcrumbs tests - add a describe block to make it clear we're testing link behavior in non-last breadcrumbs - add a helper that automatically adds a last breadcrumb so that link generation still works * Add comment/note as to why I didn't add last-breadcrumb-specific logic to useGenerateBreadcrumbs Co-authored-by: Constance --- .../generate_breadcrumbs.test.ts | 75 +++++++++---------- .../kibana_chrome/generate_breadcrumbs.ts | 10 ++- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts index 0bf7d618c33b..c05c4dcbdddc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts @@ -14,6 +14,7 @@ jest.mock('../react_router_helpers', () => ({ import { letBrowserHandleEvent } from '../react_router_helpers'; import { + Breadcrumb, useGenerateBreadcrumbs, useEuiBreadcrumbs, useEnterpriseSearchBreadcrumbs, @@ -40,6 +41,9 @@ describe('useGenerateBreadcrumbs', () => { { text: 'Groups', path: '/groups' }, { text: 'Example Group Name', path: '/groups/{id}' }, { text: 'Source Prioritization', path: '/groups/{id}/source_prioritization' }, + // Note: We're still generating a path for the last breadcrumb even though useEuiBreadcrumbs + // will not render a link for it. This is because it's easier to keep our last-breadcrumb-specific + // logic in one place, & this way we still have a current path if (for some reason) we need it later. ]); }); @@ -89,48 +93,51 @@ describe('useEuiBreadcrumbs', () => { }, { text: 'World', - href: '/app/enterprise_search/world', - onClick: expect.any(Function), + // Per EUI best practices, the last breadcrumb is inactive/is not a link }, ]); }); - it('prevents default navigation and uses React Router history on click', () => { - const breadcrumb = useEuiBreadcrumbs([{ text: '', path: '/test' }])[0] as any; + describe('link behavior for non-last breadcrumbs', () => { + // Test helper - adds a 2nd dummy breadcrumb so that paths from the first breadcrumb are generated + const useEuiBreadcrumb = (breadcrumb: Breadcrumb) => + useEuiBreadcrumbs([breadcrumb, { text: '' }])[0] as any; - expect(breadcrumb.href).toEqual('/app/enterprise_search/test'); - expect(mockHistory.createHref).toHaveBeenCalled(); + it('prevents default navigation and uses React Router history on click', () => { + const breadcrumb = useEuiBreadcrumb({ text: '', path: '/test' }); - const event = { preventDefault: jest.fn() }; - breadcrumb.onClick(event); + expect(breadcrumb.href).toEqual('/app/enterprise_search/test'); + expect(mockHistory.createHref).toHaveBeenCalled(); - expect(event.preventDefault).toHaveBeenCalled(); - expect(mockKibanaValues.navigateToUrl).toHaveBeenCalled(); - }); + const event = { preventDefault: jest.fn() }; + breadcrumb.onClick(event); - it('does not call createHref if shouldNotCreateHref is passed', () => { - const breadcrumb = useEuiBreadcrumbs([ - { text: '', path: '/test', shouldNotCreateHref: true }, - ])[0] as any; + expect(event.preventDefault).toHaveBeenCalled(); + expect(mockKibanaValues.navigateToUrl).toHaveBeenCalled(); + }); - expect(breadcrumb.href).toEqual('/test'); - expect(mockHistory.createHref).not.toHaveBeenCalled(); - }); + it('does not call createHref if shouldNotCreateHref is passed', () => { + const breadcrumb = useEuiBreadcrumb({ text: '', path: '/test', shouldNotCreateHref: true }); - it('does not prevent default browser behavior on new tab/window clicks', () => { - const breadcrumb = useEuiBreadcrumbs([{ text: '', path: '/' }])[0] as any; + expect(breadcrumb.href).toEqual('/test'); + expect(mockHistory.createHref).not.toHaveBeenCalled(); + }); - (letBrowserHandleEvent as jest.Mock).mockImplementationOnce(() => true); - breadcrumb.onClick(); + it('does not prevent default browser behavior on new tab/window clicks', () => { + const breadcrumb = useEuiBreadcrumb({ text: '', path: '/' }); - expect(mockKibanaValues.navigateToUrl).not.toHaveBeenCalled(); - }); + (letBrowserHandleEvent as jest.Mock).mockImplementationOnce(() => true); + breadcrumb.onClick(); + + expect(mockKibanaValues.navigateToUrl).not.toHaveBeenCalled(); + }); - it('does not generate link behavior if path is excluded', () => { - const breadcrumb = useEuiBreadcrumbs([{ text: 'Unclickable breadcrumb' }])[0]; + it('does not generate link behavior if path is excluded', () => { + const breadcrumb = useEuiBreadcrumb({ text: 'Unclickable breadcrumb' }); - expect(breadcrumb.href).toBeUndefined(); - expect(breadcrumb.onClick).toBeUndefined(); + expect(breadcrumb.href).toBeUndefined(); + expect(breadcrumb.onClick).toBeUndefined(); + }); }); }); @@ -164,8 +171,6 @@ describe('useEnterpriseSearchBreadcrumbs', () => { }, { text: 'Page 2', - href: '/app/enterprise_search/page2', - onClick: expect.any(Function), }, ]); }); @@ -174,8 +179,6 @@ describe('useEnterpriseSearchBreadcrumbs', () => { expect(useEnterpriseSearchBreadcrumbs()).toEqual([ { text: 'Enterprise Search', - href: '/app/enterprise_search/overview', - onClick: expect.any(Function), }, ]); }); @@ -219,8 +222,6 @@ describe('useAppSearchBreadcrumbs', () => { }, { text: 'Page 2', - href: '/app/enterprise_search/app_search/page2', - onClick: expect.any(Function), }, ]); }); @@ -234,8 +235,6 @@ describe('useAppSearchBreadcrumbs', () => { }, { text: 'App Search', - href: '/app/enterprise_search/app_search/', - onClick: expect.any(Function), }, ]); }); @@ -279,8 +278,6 @@ describe('useWorkplaceSearchBreadcrumbs', () => { }, { text: 'Page 2', - href: '/app/enterprise_search/workplace_search/page2', - onClick: expect.any(Function), }, ]); }); @@ -294,8 +291,6 @@ describe('useWorkplaceSearchBreadcrumbs', () => { }, { text: 'Workplace Search', - href: '/app/enterprise_search/workplace_search/', - onClick: expect.any(Function), }, ]); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts index 908cc0601ab9..5855dc6990f6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts @@ -24,7 +24,7 @@ import { letBrowserHandleEvent, createHref } from '../react_router_helpers'; * Types */ -interface Breadcrumb { +export interface Breadcrumb { text: string; path?: string; // Used to navigate outside of the React Router basename, @@ -64,16 +64,20 @@ export const useGenerateBreadcrumbs = (trail: BreadcrumbTrail): Breadcrumbs => { /** * Convert IBreadcrumb objects to React-Router-friendly EUI breadcrumb objects * https://elastic.github.io/eui/#/navigation/breadcrumbs + * + * NOTE: Per EUI best practices, we remove the link behavior and + * generate an inactive breadcrumb for the last breadcrumb in the list. */ export const useEuiBreadcrumbs = (breadcrumbs: Breadcrumbs): EuiBreadcrumb[] => { const { navigateToUrl, history } = useValues(KibanaLogic); const { http } = useValues(HttpLogic); - return breadcrumbs.map(({ text, path, shouldNotCreateHref }) => { + return breadcrumbs.map(({ text, path, shouldNotCreateHref }, i) => { const breadcrumb: EuiBreadcrumb = { text }; + const isLastBreadcrumb = i === breadcrumbs.length - 1; - if (path) { + if (path && !isLastBreadcrumb) { breadcrumb.href = createHref(path, { history, http }, { shouldNotCreateHref }); breadcrumb.onClick = (event) => { if (letBrowserHandleEvent(event)) return; From 9033df28a49396b096b8b71bfcd676f916995408 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 7 Apr 2021 20:01:11 -0400 Subject: [PATCH 07/49] Replace `EuiPanel` with `EuiCard` when using beta badges (#96147) (#96512) In elastic/eui#4649 the `betaBadgeLabel` and related props have been removed from `EuiPanel` and it's now recommended to use an `EuiCard` instead. Replace these in APM and Observability plugins and update stories so examples can be viewed. Co-authored-by: Nathan L Smith --- .../components/app/ServiceMap/index.tsx | 2 +- .../LinkPreview.tsx | 133 ---------------- .../CreateEditCustomLinkFlyout/index.tsx | 2 +- .../link_preview.stories.tsx | 39 +++++ .../link_preview.test.tsx | 2 +- .../link_preview.tsx | 147 ++++++++++++++++++ .../Settings/CustomizeUI/CustomLink/index.tsx | 2 +- .../app/Settings/anomaly_detection/index.tsx | 2 +- .../components/app/correlations/index.tsx | 2 +- .../components/shared/LicensePrompt/index.tsx | 63 -------- .../shared/license_prompt/index.tsx | 59 +++++++ .../license_prompt.stories.tsx} | 20 ++- .../components/app/fleet_panel/index.tsx | 59 +++---- .../public/pages/landing/landing.stories.tsx | 41 +++++ 14 files changed, 327 insertions(+), 246 deletions(-) delete mode 100644 x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/LinkPreview.tsx create mode 100644 x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.stories.tsx create mode 100644 x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.tsx delete mode 100644 x-pack/plugins/apm/public/components/shared/LicensePrompt/index.tsx create mode 100644 x-pack/plugins/apm/public/components/shared/license_prompt/index.tsx rename x-pack/plugins/apm/public/components/shared/{LicensePrompt/LicensePrompt.stories.tsx => license_prompt/license_prompt.stories.tsx} (61%) create mode 100644 x-pack/plugins/observability/public/pages/landing/landing.stories.tsx diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/index.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/index.tsx index 7ef3cbca3ad2..b338d1e4ab03 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/index.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/index.tsx @@ -19,7 +19,7 @@ import { useLicenseContext } from '../../../context/license/use_license_context' import { useTheme } from '../../../hooks/use_theme'; import { useUrlParams } from '../../../context/url_params_context/use_url_params'; import { DatePicker } from '../../shared/DatePicker'; -import { LicensePrompt } from '../../shared/LicensePrompt'; +import { LicensePrompt } from '../../shared/license_prompt'; import { Controls } from './Controls'; import { Cytoscape } from './Cytoscape'; import { getCytoscapeDivStyle } from './cytoscape_options'; diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/LinkPreview.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/LinkPreview.tsx deleted file mode 100644 index 0312b802df17..000000000000 --- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/LinkPreview.tsx +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useEffect, useState } from 'react'; -import { - EuiPanel, - EuiText, - EuiSpacer, - EuiLink, - EuiToolTip, - EuiIcon, - EuiFlexGroup, - EuiFlexItem, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { debounce } from 'lodash'; -import { Filter } from '../../../../../../../common/custom_link/custom_link_types'; -import { Transaction } from '../../../../../../../typings/es_schemas/ui/transaction'; -import { callApmApi } from '../../../../../../services/rest/createCallApmApi'; -import { replaceTemplateVariables, convertFiltersToQuery } from './helper'; - -interface Props { - label: string; - url: string; - filters: Filter[]; -} - -const fetchTransaction = debounce( - async (filters: Filter[], callback: (transaction: Transaction) => void) => { - const transaction = await callApmApi({ - signal: null, - endpoint: 'GET /api/apm/settings/custom_links/transaction', - params: { query: convertFiltersToQuery(filters) }, - }); - callback(transaction); - }, - 1000 -); - -const getTextColor = (value?: string) => (value ? 'default' : 'subdued'); - -export function LinkPreview({ label, url, filters }: Props) { - const [transaction, setTransaction] = useState(); - - useEffect(() => { - /* - React throwns "Can't perform a React state update on an unmounted component" - It happens when the Custom Link flyout is closed before the return of the api request. - To avoid such case, sets the isUnmounted to true when component unmount and check its value before update the transaction. - */ - let isUnmounted = false; - fetchTransaction(filters, (_transaction: Transaction) => { - if (!isUnmounted) { - setTransaction(_transaction); - } - }); - return () => { - isUnmounted = true; - }; - }, [filters]); - - const { formattedUrl, error } = replaceTemplateVariables(url, transaction); - - return ( - - - {label - ? label - : i18n.translate( - 'xpack.apm.settings.customizeUI.customLink.default.label', - { defaultMessage: 'Elastic.co' } - )} - - - - {url ? ( - - {formattedUrl} - - ) : ( - i18n.translate( - 'xpack.apm.settings.customizeUI.customLink.default.url', - { defaultMessage: 'https://www.elastic.co' } - ) - )} - - - - - - {i18n.translate( - 'xpack.apm.settings.customizeUI.customLink.linkPreview.descrition', - { - defaultMessage: - 'Test your link with values from an example transaction document based on the filters above.', - } - )} - - - - - {error && ( - - - - )} - - - - ); -} diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/index.tsx index ccd2b0d42574..dfe768735d19 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/index.tsx @@ -22,7 +22,7 @@ import { FiltersSection } from './FiltersSection'; import { FlyoutFooter } from './FlyoutFooter'; import { LinkSection } from './LinkSection'; import { saveCustomLink } from './saveCustomLink'; -import { LinkPreview } from './LinkPreview'; +import { LinkPreview } from './link_preview'; import { Documentation } from './Documentation'; interface Props { diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.stories.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.stories.tsx new file mode 100644 index 000000000000..3bf17a733bf8 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.stories.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { ComponentProps } from 'react'; +import { CoreStart } from 'kibana/public'; +import { createCallApmApi } from '../../../../../../services/rest/createCallApmApi'; +import { LinkPreview } from './link_preview'; + +export default { + title: + 'app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/LinkPreview', + component: LinkPreview, +}; + +export function Example({ + filters, + label, + url, +}: ComponentProps) { + const coreMock = ({ + http: { + get: async () => ({ transaction: { id: '0' } }), + }, + uiSettings: { get: () => false }, + } as unknown) as CoreStart; + + createCallApmApi(coreMock); + + return ; +} +Example.args = { + filters: [], + label: 'Example label', + url: 'https://example.com', +} as ComponentProps; diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.test.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.test.tsx index 634815710428..6a6db40892e1 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.test.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { LinkPreview } from '../CreateEditCustomLinkFlyout/LinkPreview'; +import { LinkPreview } from '../CreateEditCustomLinkFlyout/link_preview'; import { render, getNodeText, diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.tsx new file mode 100644 index 000000000000..726d4ba0d65e --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.tsx @@ -0,0 +1,147 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect, useState } from 'react'; +import { + EuiPanel, + EuiText, + EuiSpacer, + EuiLink, + EuiToolTip, + EuiIcon, + EuiFlexGroup, + EuiFlexItem, + EuiTitle, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { debounce } from 'lodash'; +import { Filter } from '../../../../../../../common/custom_link/custom_link_types'; +import { Transaction } from '../../../../../../../typings/es_schemas/ui/transaction'; +import { callApmApi } from '../../../../../../services/rest/createCallApmApi'; +import { replaceTemplateVariables, convertFiltersToQuery } from './helper'; + +export interface LinkPreviewProps { + label: string; + url: string; + filters: Filter[]; +} + +const fetchTransaction = debounce( + async (filters: Filter[], callback: (transaction: Transaction) => void) => { + const transaction = await callApmApi({ + signal: null, + endpoint: 'GET /api/apm/settings/custom_links/transaction', + params: { query: convertFiltersToQuery(filters) }, + }); + callback(transaction); + }, + 1000 +); + +const getTextColor = (value?: string) => (value ? 'default' : 'subdued'); + +export function LinkPreview({ label, url, filters }: LinkPreviewProps) { + const [transaction, setTransaction] = useState(); + + useEffect(() => { + /* + React throwns "Can't perform a React state update on an unmounted component" + It happens when the Custom Link flyout is closed before the return of the api request. + To avoid such case, sets the isUnmounted to true when component unmount and check its value before update the transaction. + */ + let isUnmounted = false; + fetchTransaction(filters, (_transaction: Transaction) => { + if (!isUnmounted) { + setTransaction(_transaction); + } + }); + return () => { + isUnmounted = true; + }; + }, [filters]); + + const { formattedUrl, error } = replaceTemplateVariables(url, transaction); + + return ( + <> + +

+ {i18n.translate( + 'xpack.apm.settings.customizeUI.customLink.previewSectionTitle', + { + defaultMessage: 'Preview', + } + )} +

+
+ + + + {label + ? label + : i18n.translate( + 'xpack.apm.settings.customizeUI.customLink.default.label', + { defaultMessage: 'Elastic.co' } + )} + + + + {url ? ( + + {formattedUrl} + + ) : ( + i18n.translate( + 'xpack.apm.settings.customizeUI.customLink.default.url', + { defaultMessage: 'https://www.elastic.co' } + ) + )} + + + + + + {i18n.translate( + 'xpack.apm.settings.customizeUI.customLink.linkPreview.descrition', + { + defaultMessage: + 'Test your link with values from an example transaction document based on the filters above.', + } + )} + + + + + {error && ( + + + + )} + + + + + ); +} diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.tsx index 49fa3eab4786..ab18a31e7691 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.tsx @@ -20,7 +20,7 @@ import { INVALID_LICENSE } from '../../../../../../common/custom_link'; import { CustomLink } from '../../../../../../common/custom_link/custom_link_types'; import { FETCH_STATUS, useFetcher } from '../../../../../hooks/use_fetcher'; import { useLicenseContext } from '../../../../../context/license/use_license_context'; -import { LicensePrompt } from '../../../../shared/LicensePrompt'; +import { LicensePrompt } from '../../../../shared/license_prompt'; import { CreateCustomLinkButton } from './CreateCustomLinkButton'; import { CreateEditCustomLinkFlyout } from './CreateEditCustomLinkFlyout'; import { CustomLinkTable } from './CustomLinkTable'; diff --git a/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/index.tsx index 72f0249f07bf..62b39664cf63 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/index.tsx @@ -14,7 +14,7 @@ import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plug import { JobsList } from './jobs_list'; import { AddEnvironments } from './add_environments'; import { useFetcher } from '../../../../hooks/use_fetcher'; -import { LicensePrompt } from '../../../shared/LicensePrompt'; +import { LicensePrompt } from '../../../shared/license_prompt'; import { useLicenseContext } from '../../../../context/license/use_license_context'; import { APIReturnType } from '../../../../services/rest/createCallApmApi'; diff --git a/x-pack/plugins/apm/public/components/app/correlations/index.tsx b/x-pack/plugins/apm/public/components/app/correlations/index.tsx index e0651edbeb79..62c547aa69e0 100644 --- a/x-pack/plugins/apm/public/components/app/correlations/index.tsx +++ b/x-pack/plugins/apm/public/components/app/correlations/index.tsx @@ -34,7 +34,7 @@ import { } from '../../../../../observability/public'; import { isActivePlatinumLicense } from '../../../../common/license_check'; import { useLicenseContext } from '../../../context/license/use_license_context'; -import { LicensePrompt } from '../../shared/LicensePrompt'; +import { LicensePrompt } from '../../shared/license_prompt'; import { IUrlParams } from '../../../context/url_params_context/types'; const latencyTab = { diff --git a/x-pack/plugins/apm/public/components/shared/LicensePrompt/index.tsx b/x-pack/plugins/apm/public/components/shared/LicensePrompt/index.tsx deleted file mode 100644 index 97a48a61e47c..000000000000 --- a/x-pack/plugins/apm/public/components/shared/LicensePrompt/index.tsx +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { EuiButton, EuiEmptyPrompt, EuiPanel } from '@elastic/eui'; -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { useKibanaUrl } from '../../../hooks/useKibanaUrl'; - -interface Props { - text: string; - showBetaBadge?: boolean; -} - -export function LicensePrompt({ text, showBetaBadge = false }: Props) { - const licensePageUrl = useKibanaUrl( - '/app/management/stack/license_management' - ); - - const renderLicenseBody = ( - - {i18n.translate('xpack.apm.license.title', { - defaultMessage: 'Start free 30-day trial', - })} - - } - body={

{text}

} - actions={ - - {i18n.translate('xpack.apm.license.button', { - defaultMessage: 'Start trial', - })} - - } - /> - ); - - const renderWithBetaBadge = ( - - {renderLicenseBody} - - ); - - return <>{showBetaBadge ? renderWithBetaBadge : renderLicenseBody}; -} diff --git a/x-pack/plugins/apm/public/components/shared/license_prompt/index.tsx b/x-pack/plugins/apm/public/components/shared/license_prompt/index.tsx new file mode 100644 index 000000000000..0950cff5127f --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/license_prompt/index.tsx @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiButton, EuiCard, EuiTextColor } from '@elastic/eui'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { useKibanaUrl } from '../../../hooks/useKibanaUrl'; + +export interface LicensePromptProps { + text: string; + showBetaBadge?: boolean; +} + +export function LicensePrompt({ + text, + showBetaBadge = false, +}: LicensePromptProps) { + const licensePageUrl = useKibanaUrl( + '/app/management/stack/license_management' + ); + + return ( + {text}} + footer={ + + {i18n.translate('xpack.apm.license.button', { + defaultMessage: 'Start trial', + })} + + } + /> + ); +} diff --git a/x-pack/plugins/apm/public/components/shared/LicensePrompt/LicensePrompt.stories.tsx b/x-pack/plugins/apm/public/components/shared/license_prompt/license_prompt.stories.tsx similarity index 61% rename from x-pack/plugins/apm/public/components/shared/LicensePrompt/LicensePrompt.stories.tsx rename to x-pack/plugins/apm/public/components/shared/license_prompt/license_prompt.stories.tsx index 57f782a02008..35e22b50306d 100644 --- a/x-pack/plugins/apm/public/components/shared/LicensePrompt/LicensePrompt.stories.tsx +++ b/x-pack/plugins/apm/public/components/shared/license_prompt/license_prompt.stories.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { ComponentType } from 'react'; +import React, { ComponentProps, ComponentType } from 'react'; import { LicensePrompt } from '.'; import { ApmPluginContext, @@ -17,19 +17,25 @@ const contextMock = ({ } as unknown) as ApmPluginContextValue; export default { - title: 'app/LicensePrompt', + title: 'shared/LicensePrompt', component: LicensePrompt, decorators: [ (Story: ComponentType) => ( - {' '} + ), ], }; -export function Example() { - return ( - - ); +export function Example({ + showBetaBadge, + text, +}: ComponentProps) { + return ; } +Example.args = { + showBetaBadge: false, + text: + 'To create Feature name, you must be subscribed to an Elastic X license or above.', +} as ComponentProps; diff --git a/x-pack/plugins/observability/public/components/app/fleet_panel/index.tsx b/x-pack/plugins/observability/public/components/app/fleet_panel/index.tsx index b1ca3c614fc7..fce1cde38f58 100644 --- a/x-pack/plugins/observability/public/components/app/fleet_panel/index.tsx +++ b/x-pack/plugins/observability/public/components/app/fleet_panel/index.tsx @@ -5,53 +5,38 @@ * 2.0. */ -import React from 'react'; -import { EuiPanel } from '@elastic/eui'; -import { EuiFlexGroup } from '@elastic/eui'; -import { EuiFlexItem } from '@elastic/eui'; -import { EuiTitle } from '@elastic/eui'; +import { EuiCard, EuiLink, EuiTextColor } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { EuiText } from '@elastic/eui'; -import { EuiLink } from '@elastic/eui'; +import React from 'react'; import { usePluginContext } from '../../../hooks/use_plugin_context'; export function FleetPanel() { const { core } = usePluginContext(); return ( - - - - -

- {i18n.translate('xpack.observability.fleet.title', { - defaultMessage: 'Have you seen our new Fleet?', - })} -

-
-
- - - {i18n.translate('xpack.observability.fleet.text', { - defaultMessage: - 'The Elastic Agent provides a simple, unified way to add monitoring for logs, metrics, and other types of data to your hosts. You no longer need to install multiple Beats and other agents, making it easier and faster to deploy configurations across your infrastructure.', - })} - - - - - {i18n.translate('xpack.observability.fleet.button', { - defaultMessage: 'Try Fleet Beta', - })} - - -
-
+ description={ + + {i18n.translate('xpack.observability.fleet.text', { + defaultMessage: + 'The Elastic Agent provides a simple, unified way to add monitoring for logs, metrics, and other types of data to your hosts. You no longer need to install multiple Beats and other agents, making it easier and faster to deploy configurations across your infrastructure.', + })} + + } + footer={ + + {i18n.translate('xpack.observability.fleet.button', { + defaultMessage: 'Try Fleet Beta', + })} + + } + title={i18n.translate('xpack.observability.fleet.title', { + defaultMessage: 'Have you seen our new Fleet?', + })} + /> ); } diff --git a/x-pack/plugins/observability/public/pages/landing/landing.stories.tsx b/x-pack/plugins/observability/public/pages/landing/landing.stories.tsx new file mode 100644 index 000000000000..86922b045c74 --- /dev/null +++ b/x-pack/plugins/observability/public/pages/landing/landing.stories.tsx @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { ComponentType } from 'react'; +import { EuiThemeProvider } from '../../../../../../src/plugins/kibana_react/common'; +import { PluginContext, PluginContextValue } from '../../context/plugin_context'; +import { LandingPage } from './'; + +export default { + title: 'app/Landing', + component: LandingPage, + decorators: [ + (Story: ComponentType) => { + const pluginContextValue = ({ + appMountParameters: { setHeaderActionMenu: () => {} }, + core: { + http: { + basePath: { + prepend: () => '', + }, + }, + }, + } as unknown) as PluginContextValue; + return ( + + + + + + ); + }, + ], +}; + +export function Example() { + return ; +} From 6f0d093915d937453c617a63cff5aee00a12a4c6 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Wed, 7 Apr 2021 17:07:59 -0700 Subject: [PATCH 08/49] [Actions] Added action configuration settings `maxResponseContentLength` and `responseTimeout`. (#96355) (#96514) * [Actions] Added action configuration settings `maxResponseContentLength` and `responseTimeout` which define max response content size (in bytes) and awaiting timeout for action executions based on axios requests. * replaced pasceDuration with moment * fixed due to comments * renamed internal options --- docs/settings/alert-action-settings.asciidoc | 7 +++++ .../resources/base/bin/kibana-docker | 2 ++ .../actions/server/actions_client.test.ts | 4 +++ .../actions/server/actions_config.mock.ts | 4 +++ .../actions/server/actions_config.test.ts | 16 ++++++++++ .../plugins/actions/server/actions_config.ts | 11 ++++++- .../server/builtin_action_types/email.test.ts | 2 ++ .../lib/axios_utils.test.ts | 19 ++++++++++++ .../builtin_action_types/lib/axios_utils.ts | 3 ++ .../server/builtin_action_types/teams.test.ts | 2 ++ .../builtin_action_types/webhook.test.ts | 29 +++++++++++++++++++ .../server/builtin_action_types/webhook.ts | 5 +++- x-pack/plugins/actions/server/config.test.ts | 8 +++++ x-pack/plugins/actions/server/config.ts | 2 ++ x-pack/plugins/actions/server/plugin.test.ts | 6 ++++ x-pack/plugins/actions/server/types.ts | 5 ++++ 16 files changed, 123 insertions(+), 2 deletions(-) diff --git a/docs/settings/alert-action-settings.asciidoc b/docs/settings/alert-action-settings.asciidoc index 08cbee8851b9..20bbbcf874c0 100644 --- a/docs/settings/alert-action-settings.asciidoc +++ b/docs/settings/alert-action-settings.asciidoc @@ -77,6 +77,13 @@ a|`xpack.actions.` + As an alternative to setting both `xpack.actions.proxyRejectUnauthorizedCertificates` and `xpack.actions.rejectUnauthorized`, you can point the OS level environment variable `NODE_EXTRA_CA_CERTS` to a file that contains the root CAs needed to trust certificates. +| `xpack.actions.maxResponseContentLength` {ess-icon} + | Specifies the max number of bytes of the http response for requests to external resources. Defaults to 1000000 (1MB). + +| `xpack.actions.responseTimeout` {ess-icon} + | Specifies the time allowed for requests to external resources. Requests that take longer are aborted. The time is formatted as [ms|s|m|h|d|w|M|Y], for example, '20m', '24h', '7d', '1w'. Defaults to 60s. + + |=== [float] diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker index 2c8cc185323a..504c3147a6f9 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker @@ -166,6 +166,8 @@ kibana_vars=( xpack.actions.proxyBypassHosts xpack.actions.proxyOnlyHosts xpack.actions.rejectUnauthorized + xpack.actions.maxResponseContentLength + xpack.actions.responseTimeout xpack.alerts.healthCheck.interval xpack.alerts.invalidateApiKeysTask.interval xpack.alerts.invalidateApiKeysTask.removalDelay diff --git a/x-pack/plugins/actions/server/actions_client.test.ts b/x-pack/plugins/actions/server/actions_client.test.ts index 92d3b4f29d96..6544a3c426e4 100644 --- a/x-pack/plugins/actions/server/actions_client.test.ts +++ b/x-pack/plugins/actions/server/actions_client.test.ts @@ -6,6 +6,8 @@ */ import { schema } from '@kbn/config-schema'; +import moment from 'moment'; +import { ByteSizeValue } from '@kbn/config-schema'; import { ActionTypeRegistry, ActionTypeRegistryOpts } from './action_type_registry'; import { ActionsClient } from './actions_client'; @@ -408,6 +410,8 @@ describe('create()', () => { rejectUnauthorized: true, proxyBypassHosts: undefined, proxyOnlyHosts: undefined, + maxResponseContentLength: new ByteSizeValue(1000000), + responseTimeout: moment.duration('60s'), }); const localActionTypeRegistryParams = { diff --git a/x-pack/plugins/actions/server/actions_config.mock.ts b/x-pack/plugins/actions/server/actions_config.mock.ts index 012cd63be270..76f6a62ce659 100644 --- a/x-pack/plugins/actions/server/actions_config.mock.ts +++ b/x-pack/plugins/actions/server/actions_config.mock.ts @@ -17,6 +17,10 @@ const createActionsConfigMock = () => { ensureActionTypeEnabled: jest.fn().mockReturnValue({}), isRejectUnauthorizedCertificatesEnabled: jest.fn().mockReturnValue(true), getProxySettings: jest.fn().mockReturnValue(undefined), + getResponseSettings: jest.fn().mockReturnValue({ + maxContentLength: 1000000, + timeout: 360000, + }), }; return mocked; }; diff --git a/x-pack/plugins/actions/server/actions_config.test.ts b/x-pack/plugins/actions/server/actions_config.test.ts index 36899f7661ba..c81f1f4a4bf2 100644 --- a/x-pack/plugins/actions/server/actions_config.test.ts +++ b/x-pack/plugins/actions/server/actions_config.test.ts @@ -5,12 +5,14 @@ * 2.0. */ +import { ByteSizeValue } from '@kbn/config-schema'; import { ActionsConfig } from './config'; import { getActionsConfigurationUtilities, AllowedHosts, EnabledActionTypes, } from './actions_config'; +import moment from 'moment'; const defaultActionsConfig: ActionsConfig = { enabled: false, @@ -19,6 +21,8 @@ const defaultActionsConfig: ActionsConfig = { preconfigured: {}, proxyRejectUnauthorizedCertificates: true, rejectUnauthorized: true, + maxResponseContentLength: new ByteSizeValue(1000000), + responseTimeout: moment.duration(60000), }; describe('ensureUriAllowed', () => { @@ -254,6 +258,18 @@ describe('ensureActionTypeEnabled', () => { }); }); +describe('getResponseSettingsFromConfig', () => { + test('returns expected parsed values for default config for responseTimeout and maxResponseContentLength', () => { + const config: ActionsConfig = { + ...defaultActionsConfig, + }; + expect(getActionsConfigurationUtilities(config).getResponseSettings()).toEqual({ + timeout: 60000, + maxContentLength: 1000000, + }); + }); +}); + describe('getProxySettings', () => { test('returns undefined when no proxy URL set', () => { const config: ActionsConfig = { diff --git a/x-pack/plugins/actions/server/actions_config.ts b/x-pack/plugins/actions/server/actions_config.ts index b35a4a0d7b6c..4c73cab76f9e 100644 --- a/x-pack/plugins/actions/server/actions_config.ts +++ b/x-pack/plugins/actions/server/actions_config.ts @@ -13,7 +13,7 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { ActionsConfig, AllowedHosts, EnabledActionTypes } from './config'; import { ActionTypeDisabledError } from './lib'; -import { ProxySettings } from './types'; +import { ProxySettings, ResponseSettings } from './types'; export { AllowedHosts, EnabledActionTypes } from './config'; @@ -31,6 +31,7 @@ export interface ActionsConfigurationUtilities { ensureActionTypeEnabled: (actionType: string) => void; isRejectUnauthorizedCertificatesEnabled: () => boolean; getProxySettings: () => undefined | ProxySettings; + getResponseSettings: () => ResponseSettings; } function allowListErrorMessage(field: AllowListingField, value: string) { @@ -99,6 +100,13 @@ function arrayAsSet(arr: T[] | undefined): Set | undefined { return new Set(arr); } +function getResponseSettingsFromConfig(config: ActionsConfig): ResponseSettings { + return { + maxContentLength: config.maxResponseContentLength.getValueInBytes(), + timeout: config.responseTimeout.asMilliseconds(), + }; +} + export function getActionsConfigurationUtilities( config: ActionsConfig ): ActionsConfigurationUtilities { @@ -110,6 +118,7 @@ export function getActionsConfigurationUtilities( isUriAllowed, isActionTypeEnabled, getProxySettings: () => getProxySettingsFromConfig(config), + getResponseSettings: () => getResponseSettingsFromConfig(config), isRejectUnauthorizedCertificatesEnabled: () => config.rejectUnauthorized, ensureUriAllowed(uri: string) { if (!isUriAllowed(uri)) { diff --git a/x-pack/plugins/actions/server/builtin_action_types/email.test.ts b/x-pack/plugins/actions/server/builtin_action_types/email.test.ts index b858d5491a6b..4596619c5094 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/email.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/email.test.ts @@ -283,6 +283,7 @@ describe('execute()', () => { "ensureHostnameAllowed": [MockFunction], "ensureUriAllowed": [MockFunction], "getProxySettings": [MockFunction], + "getResponseSettings": [MockFunction], "isActionTypeEnabled": [MockFunction], "isHostnameAllowed": [MockFunction], "isRejectUnauthorizedCertificatesEnabled": [MockFunction], @@ -342,6 +343,7 @@ describe('execute()', () => { "ensureHostnameAllowed": [MockFunction], "ensureUriAllowed": [MockFunction], "getProxySettings": [MockFunction], + "getResponseSettings": [MockFunction], "isActionTypeEnabled": [MockFunction], "isHostnameAllowed": [MockFunction], "isRejectUnauthorizedCertificatesEnabled": [MockFunction], diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts index a932b38ede2b..edc9429e4fac 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts @@ -42,6 +42,10 @@ describe('request', () => { headers: { 'content-type': 'application/json' }, data: { incidentId: '123' }, })); + configurationUtilities.getResponseSettings.mockReturnValue({ + maxContentLength: 1000000, + timeout: 360000, + }); }); test('it fetch correctly with defaults', async () => { @@ -58,6 +62,8 @@ describe('request', () => { httpAgent: undefined, httpsAgent: expect.any(HttpsAgent), proxy: false, + maxContentLength: 1000000, + timeout: 360000, }); expect(res).toEqual({ status: 200, @@ -88,6 +94,8 @@ describe('request', () => { httpAgent, httpsAgent, proxy: false, + maxContentLength: 1000000, + timeout: 360000, }); expect(res).toEqual({ status: 200, @@ -116,6 +124,8 @@ describe('request', () => { httpAgent: undefined, httpsAgent: expect.any(HttpsAgent), proxy: false, + maxContentLength: 1000000, + timeout: 360000, }); expect(res).toEqual({ status: 200, @@ -224,6 +234,8 @@ describe('request', () => { httpAgent: undefined, httpsAgent: expect.any(HttpsAgent), proxy: false, + maxContentLength: 1000000, + timeout: 360000, }); expect(res).toEqual({ status: 200, @@ -235,10 +247,15 @@ describe('request', () => { describe('patch', () => { beforeEach(() => { + jest.resetAllMocks(); axiosMock.mockImplementation(() => ({ status: 200, headers: { 'content-type': 'application/json' }, })); + configurationUtilities.getResponseSettings.mockReturnValue({ + maxContentLength: 1000000, + timeout: 360000, + }); }); test('it fetch correctly', async () => { @@ -249,6 +266,8 @@ describe('patch', () => { httpAgent: undefined, httpsAgent: expect.any(HttpsAgent), proxy: false, + maxContentLength: 1000000, + timeout: 360000, }); }); }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts index edce36909614..af353e1d1da5 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts @@ -31,6 +31,7 @@ export const request = async ({ auth?: AxiosBasicCredentials; }): Promise => { const { httpAgent, httpsAgent } = getCustomAgents(configurationUtilities, logger, url); + const { maxContentLength, timeout } = configurationUtilities.getResponseSettings(); return await axios(url, { ...rest, @@ -40,6 +41,8 @@ export const request = async ({ httpAgent, httpsAgent, proxy: false, + maxContentLength, + timeout, }); }; diff --git a/x-pack/plugins/actions/server/builtin_action_types/teams.test.ts b/x-pack/plugins/actions/server/builtin_action_types/teams.test.ts index c31adddc5a57..8a185d353de0 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/teams.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/teams.test.ts @@ -168,6 +168,7 @@ describe('execute()', () => { "ensureHostnameAllowed": [MockFunction], "ensureUriAllowed": [MockFunction], "getProxySettings": [MockFunction], + "getResponseSettings": [MockFunction], "isActionTypeEnabled": [MockFunction], "isHostnameAllowed": [MockFunction], "isRejectUnauthorizedCertificatesEnabled": [MockFunction], @@ -230,6 +231,7 @@ describe('execute()', () => { "ensureHostnameAllowed": [MockFunction], "ensureUriAllowed": [MockFunction], "getProxySettings": [MockFunction], + "getResponseSettings": [MockFunction], "isActionTypeEnabled": [MockFunction], "isHostnameAllowed": [MockFunction], "isRejectUnauthorizedCertificatesEnabled": [MockFunction], diff --git a/x-pack/plugins/actions/server/builtin_action_types/webhook.test.ts b/x-pack/plugins/actions/server/builtin_action_types/webhook.test.ts index c46845324780..d3f059eede61 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/webhook.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/webhook.test.ts @@ -291,6 +291,7 @@ describe('execute()', () => { "ensureHostnameAllowed": [MockFunction], "ensureUriAllowed": [MockFunction], "getProxySettings": [MockFunction], + "getResponseSettings": [MockFunction], "isActionTypeEnabled": [MockFunction], "isHostnameAllowed": [MockFunction], "isRejectUnauthorizedCertificatesEnabled": [MockFunction], @@ -329,6 +330,33 @@ describe('execute()', () => { `); }); + test('execute with exception maxContentLength size exceeded should log the proper error', async () => { + const config: ActionTypeConfigType = { + url: 'https://abc.def/my-webhook', + method: WebhookMethods.POST, + headers: { + aheader: 'a value', + }, + hasAuth: true, + }; + requestMock.mockReset(); + requestMock.mockRejectedValueOnce({ + tag: 'err', + isAxiosError: true, + message: 'maxContentLength size of 1000000 exceeded', + }); + await actionType.executor({ + actionId: 'some-id', + services, + config, + secrets: { user: 'abc', password: '123' }, + params: { body: 'some data' }, + }); + expect(mockedLogger.error).toBeCalledWith( + 'error on some-id webhook event: maxContentLength size of 1000000 exceeded' + ); + }); + test('execute without username/password sends request without basic auth', async () => { const config: ActionTypeConfigType = { url: 'https://abc.def/my-webhook', @@ -355,6 +383,7 @@ describe('execute()', () => { "ensureHostnameAllowed": [MockFunction], "ensureUriAllowed": [MockFunction], "getProxySettings": [MockFunction], + "getResponseSettings": [MockFunction], "isActionTypeEnabled": [MockFunction], "isHostnameAllowed": [MockFunction], "isRejectUnauthorizedCertificatesEnabled": [MockFunction], diff --git a/x-pack/plugins/actions/server/builtin_action_types/webhook.ts b/x-pack/plugins/actions/server/builtin_action_types/webhook.ts index 269449686acf..93c9bbdbab18 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/webhook.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/webhook.ts @@ -180,7 +180,6 @@ export async function executor( return successResult(actionId, data); } else { const { error } = result; - if (error.response) { const { status, @@ -211,6 +210,10 @@ export async function executor( const message = `[${error.code}] ${error.message}`; logger.error(`error on ${actionId} webhook event: ${message}`); return errorResultRequestFailed(actionId, message); + } else if (error.isAxiosError) { + const message = `${error.message}`; + logger.error(`error on ${actionId} webhook event: ${message}`); + return errorResultRequestFailed(actionId, message); } logger.error(`error on ${actionId} webhook action: unexpected error`); diff --git a/x-pack/plugins/actions/server/config.test.ts b/x-pack/plugins/actions/server/config.test.ts index 0d270512d1de..2eecaa19da0c 100644 --- a/x-pack/plugins/actions/server/config.test.ts +++ b/x-pack/plugins/actions/server/config.test.ts @@ -27,9 +27,13 @@ describe('config validation', () => { "enabledActionTypes": Array [ "*", ], + "maxResponseContentLength": ByteSizeValue { + "valueInBytes": 1048576, + }, "preconfigured": Object {}, "proxyRejectUnauthorizedCertificates": true, "rejectUnauthorized": true, + "responseTimeout": "PT1M", } `); }); @@ -57,6 +61,9 @@ describe('config validation', () => { "enabledActionTypes": Array [ "*", ], + "maxResponseContentLength": ByteSizeValue { + "valueInBytes": 1048576, + }, "preconfigured": Object { "mySlack1": Object { "actionTypeId": ".slack", @@ -69,6 +76,7 @@ describe('config validation', () => { }, "proxyRejectUnauthorizedCertificates": false, "rejectUnauthorized": false, + "responseTimeout": "PT1M", } `); }); diff --git a/x-pack/plugins/actions/server/config.ts b/x-pack/plugins/actions/server/config.ts index 450f03308ab0..4aa77ded315b 100644 --- a/x-pack/plugins/actions/server/config.ts +++ b/x-pack/plugins/actions/server/config.ts @@ -47,6 +47,8 @@ export const configSchema = schema.object({ proxyBypassHosts: schema.maybe(schema.arrayOf(schema.string({ hostname: true }))), proxyOnlyHosts: schema.maybe(schema.arrayOf(schema.string({ hostname: true }))), rejectUnauthorized: schema.boolean({ defaultValue: true }), + maxResponseContentLength: schema.byteSize({ defaultValue: '1mb' }), + responseTimeout: schema.duration({ defaultValue: '60s' }), }); export type ActionsConfig = TypeOf; diff --git a/x-pack/plugins/actions/server/plugin.test.ts b/x-pack/plugins/actions/server/plugin.test.ts index b8f83e91239e..30bbedbedbe9 100644 --- a/x-pack/plugins/actions/server/plugin.test.ts +++ b/x-pack/plugins/actions/server/plugin.test.ts @@ -5,6 +5,8 @@ * 2.0. */ +import moment from 'moment'; +import { ByteSizeValue } from '@kbn/config-schema'; import { PluginInitializerContext, RequestHandlerContext } from '../../../../src/core/server'; import { coreMock, httpServerMock } from '../../../../src/core/server/mocks'; import { usageCollectionPluginMock } from '../../../../src/plugins/usage_collection/server/mocks'; @@ -37,6 +39,8 @@ describe('Actions Plugin', () => { preconfigured: {}, proxyRejectUnauthorizedCertificates: true, rejectUnauthorized: true, + maxResponseContentLength: new ByteSizeValue(1000000), + responseTimeout: moment.duration(60000), }); plugin = new ActionsPlugin(context); coreSetup = coreMock.createSetup(); @@ -197,6 +201,8 @@ describe('Actions Plugin', () => { }, proxyRejectUnauthorizedCertificates: true, rejectUnauthorized: true, + maxResponseContentLength: new ByteSizeValue(1000000), + responseTimeout: moment.duration(60000), }); plugin = new ActionsPlugin(context); coreSetup = coreMock.createSetup(); diff --git a/x-pack/plugins/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts index 6830f013ade5..b7a6750a520e 100644 --- a/x-pack/plugins/actions/server/types.ts +++ b/x-pack/plugins/actions/server/types.ts @@ -138,3 +138,8 @@ export interface ProxySettings { proxyHeaders?: Record; proxyRejectUnauthorizedCertificates: boolean; } + +export interface ResponseSettings { + maxContentLength: number; + timeout: number; +} From f06be93a406878d085e75f8351ca48f41fd37779 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 7 Apr 2021 18:57:40 -0700 Subject: [PATCH 09/49] skip suite block es promotion (#96515) --- x-pack/test/fleet_api_integration/apis/fleet_setup.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/fleet_api_integration/apis/fleet_setup.ts b/x-pack/test/fleet_api_integration/apis/fleet_setup.ts index c9709475d182..a82ed3f8cf22 100644 --- a/x-pack/test/fleet_api_integration/apis/fleet_setup.ts +++ b/x-pack/test/fleet_api_integration/apis/fleet_setup.ts @@ -15,7 +15,8 @@ export default function (providerContext: FtrProviderContext) { const es = getService('es'); const esArchiver = getService('esArchiver'); - describe('fleet_setup', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/96515 + describe.skip('fleet_setup', () => { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('empty_kibana'); From 6af5828b3d4b37af9ba6facb0bbeedc700a26bce Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 7 Apr 2021 23:06:05 -0400 Subject: [PATCH 10/49] [Security Solution][Detections]Fixes Rule Management Cypress Tests (#96505) (#96521) ## Summary Fixes two cypress tests: > Deleting prebuilt rules "before each" hook for "Does not allow to delete one rule when more than one is selected" https://github.com/elastic/kibana/issues/68607 This one is more of a drive around the pot-hole fix as we were waiting for the Alerts Table to load when we really didn't need to. Removed unnecessary check.

> Alerts rules, prebuilt rules Loads prebuilt rules https://github.com/elastic/kibana/issues/71300 This one was fixed with a `.pipe()` and `.should('not.be.visible')` to ensure the click was successful. Also removed unnecessary check on the Alerts Table loading that was present here as well too..

Co-authored-by: Garrett Spong --- .../integration/detection_rules/prebuilt_rules.spec.ts | 8 +------- .../cypress/tasks/alerts_detection_rules.ts | 5 ++++- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/prebuilt_rules.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/prebuilt_rules.spec.ts index d290773d425e..fb0a01bd1c7d 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/prebuilt_rules.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/prebuilt_rules.spec.ts @@ -14,11 +14,7 @@ import { SHOWING_RULES_TEXT, } from '../../screens/alerts_detection_rules'; -import { - goToManageAlertsDetectionRules, - waitForAlertsIndexToBeCreated, - waitForAlertsPanelToBeLoaded, -} from '../../tasks/alerts'; +import { goToManageAlertsDetectionRules, waitForAlertsIndexToBeCreated } from '../../tasks/alerts'; import { changeRowsPerPageTo300, deleteFirstRule, @@ -47,7 +43,6 @@ describe('Alerts rules, prebuilt rules', () => { const expectedElasticRulesBtnText = `Elastic rules (${expectedNumberOfRules})`; loginAndWaitForPageWithoutDateRange(DETECTIONS_URL); - waitForAlertsPanelToBeLoaded(); waitForAlertsIndexToBeCreated(); goToManageAlertsDetectionRules(); waitForRulesTableToBeLoaded(); @@ -79,7 +74,6 @@ describe('Deleting prebuilt rules', () => { cleanKibana(); loginAndWaitForPageWithoutDateRange(DETECTIONS_URL); - waitForAlertsPanelToBeLoaded(); waitForAlertsIndexToBeCreated(); goToManageAlertsDetectionRules(); waitForRulesTableToBeLoaded(); diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts index 10644e046a68..d66b839267ea 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts @@ -191,7 +191,10 @@ export const resetAllRulesIdleModalTimeout = () => { export const changeRowsPerPageTo = (rowsCount: number) => { cy.get(PAGINATION_POPOVER_BTN).click({ force: true }); - cy.get(rowsPerPageSelector(rowsCount)).click(); + cy.get(rowsPerPageSelector(rowsCount)) + .pipe(($el) => $el.trigger('click')) + .should('not.be.visible'); + waitForRulesTableToBeRefreshed(); }; From 36d86ad29ad93121b3b1fda62cb403801debb180 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 8 Apr 2021 02:36:07 -0400 Subject: [PATCH 11/49] [Security Solution][Detections] Fixes Closing Alerts Cypress Test (#96523) (#96526) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary As identified in https://github.com/elastic/kibana/pull/96505#issuecomment-815392671, this fixes the flakiness in the `Closing alerts` cypress test. Method used was to just delete the rule after the initial batch of alerts were generated. Alternatively we could add a function for disabling the rule (didn't see one in there), but the outcome is the same, no more alerts generated while the test is being performed. 🙂 > Passing locally, though upon further inspection, this test is definitely going to be flakey as it's checking counts on alerts as they move through different states and there are new alerts that keep coming in (hence the count mis-match in the above failure). Potential fixes would be to use an absolute daterange to after the first round of alerts were generated, or just stop generating alerts before performing the alert state changes. ##### Before:

##### After:

Co-authored-by: Garrett Spong --- .../cypress/integration/detection_alerts/closing.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/closing.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/closing.spec.ts index e9d17a361d33..b7c0e1c6fcd6 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/closing.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/closing.spec.ts @@ -25,7 +25,7 @@ import { waitForAlerts, waitForAlertsIndexToBeCreated, } from '../../tasks/alerts'; -import { createCustomRuleActivated } from '../../tasks/api_calls/rules'; +import { createCustomRuleActivated, deleteCustomRule } from '../../tasks/api_calls/rules'; import { cleanKibana } from '../../tasks/common'; import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; import { loginAndWaitForPage } from '../../tasks/login'; @@ -42,6 +42,7 @@ describe('Closing alerts', () => { createCustomRuleActivated(newRule); refreshPage(); waitForAlertsToPopulate(); + deleteCustomRule(); }); it('Closes and opens alerts', () => { From 95992f0e984ed2dd9e2959cd5f1059b6e74c9a1f Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 8 Apr 2021 03:01:58 -0400 Subject: [PATCH 12/49] [Fleet] Install security_rule assets as saved objects (#95885) (#96527) * [Fleet] Install security_rule assets as saved objects * Add security-rule to update_assets.ts * Update UUIDs for security_rule asset * Change .type to match the saved object type not the asset type * Add saved object mapping for security-rule * Make SO non-hidden * Fix SO mapping for security-rule * Make security-rule a non-hidden asset Co-authored-by: Ross Wolf <31489089+rw-access@users.noreply.github.com> --- .../package_to_package_policy.test.ts | 1 + .../plugins/fleet/common/types/models/epm.ts | 2 + .../fleet/sections/epm/constants.tsx | 2 + .../services/epm/kibana/assets/install.ts | 2 + .../services/epm/packages/assets.test.ts | 2 +- .../rules/saved_object_mappings.ts | 24 +++++++++ .../security_solution/server/saved_objects.ts | 6 ++- .../apis/epm/install_remove_assets.ts | 10 ++++ .../apis/epm/update_assets.ts | 5 ++ .../security_rule/sample_security_rule.json | 50 +++++++++++++++++++ .../security_rule/sample_security_rule.json | 50 +++++++++++++++++++ 11 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/security_rule/sample_security_rule.json create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/security_rule/sample_security_rule.json diff --git a/x-pack/plugins/fleet/common/services/package_to_package_policy.test.ts b/x-pack/plugins/fleet/common/services/package_to_package_policy.test.ts index a4cca4455a27..65b853ed5b38 100644 --- a/x-pack/plugins/fleet/common/services/package_to_package_policy.test.ts +++ b/x-pack/plugins/fleet/common/services/package_to_package_policy.test.ts @@ -31,6 +31,7 @@ describe('Fleet - packageToPackagePolicy', () => { map: [], lens: [], ml_module: [], + security_rule: [], }, elasticsearch: { ingest_pipeline: [], diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index 80fabd51613a..3bc0d97d6464 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -50,6 +50,7 @@ export enum KibanaAssetType { indexPattern = 'index_pattern', map = 'map', lens = 'lens', + securityRule = 'security_rule', mlModule = 'ml_module', } @@ -64,6 +65,7 @@ export enum KibanaSavedObjectType { map = 'map', lens = 'lens', mlModule = 'ml-module', + securityRule = 'security-rule', } export enum ElasticsearchAssetType { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/epm/constants.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/constants.tsx index ea19a330adfe..6ddff968bd3f 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/epm/constants.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/constants.tsx @@ -33,6 +33,7 @@ export const AssetTitleMap: Record = { map: 'Map', data_stream_ilm_policy: 'Data Stream ILM Policy', lens: 'Lens', + security_rule: 'Security Rule', ml_module: 'ML Module', }; @@ -48,6 +49,7 @@ export const AssetIcons: Record = { visualization: 'visualizeApp', map: 'emsApp', lens: 'lensApp', + security_rule: 'securityApp', ml_module: 'mlApp', }; diff --git a/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts index bfcc40e18fe8..0f2d7b6679bf 100644 --- a/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts @@ -38,6 +38,7 @@ const KibanaSavedObjectTypeMapping: Record { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts index 999cf878d07b..c5b104696aaf 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/assets.test.ts @@ -43,7 +43,7 @@ const tests = [ name: 'coredns', version: '1.0.1', }, - // Non existant dataset + // Non existent dataset dataset: 'foo', filter: (path: string) => { return true; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/saved_object_mappings.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/saved_object_mappings.ts index 4ed53e39fa5e..813e800f34ce 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/saved_object_mappings.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/saved_object_mappings.ts @@ -53,3 +53,27 @@ export const type: SavedObjectsType = { namespaceType: 'single', mappings: ruleStatusSavedObjectMappings, }; + +export const ruleAssetSavedObjectType = 'security-rule'; + +export const ruleAssetSavedObjectMappings: SavedObjectsType['mappings'] = { + dynamic: false, + properties: { + name: { + type: 'keyword', + }, + rule_id: { + type: 'keyword', + }, + version: { + type: 'long', + }, + }, +}; + +export const ruleAssetType: SavedObjectsType = { + name: ruleAssetSavedObjectType, + hidden: false, + namespaceType: 'agnostic', + mappings: ruleAssetSavedObjectMappings, +}; diff --git a/x-pack/plugins/security_solution/server/saved_objects.ts b/x-pack/plugins/security_solution/server/saved_objects.ts index d483bd25266a..42abb3dab2ac 100644 --- a/x-pack/plugins/security_solution/server/saved_objects.ts +++ b/x-pack/plugins/security_solution/server/saved_objects.ts @@ -8,7 +8,10 @@ import { CoreSetup } from '../../../../src/core/server'; import { noteType, pinnedEventType, timelineType } from './lib/timeline/saved_object_mappings'; -import { type as ruleStatusType } from './lib/detection_engine/rules/saved_object_mappings'; +import { + type as ruleStatusType, + ruleAssetType, +} from './lib/detection_engine/rules/saved_object_mappings'; import { type as ruleActionsType } from './lib/detection_engine/rule_actions/saved_object_mappings'; import { type as signalsMigrationType } from './lib/detection_engine/migrations/saved_objects'; import { @@ -21,6 +24,7 @@ const types = [ pinnedEventType, ruleActionsType, ruleStatusType, + ruleAssetType, timelineType, exceptionsArtifactType, manifestType, diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts index abc91a973e6b..8e09e331bf86 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts @@ -399,6 +399,11 @@ const expectAssetsInstalled = ({ id: 'sample_ml_module', }); expect(resMlModule.id).equal('sample_ml_module'); + const resSecurityRule = await kibanaServer.savedObjects.get({ + type: 'security-rule', + id: 'sample_security_rule', + }); + expect(resSecurityRule.id).equal('sample_security_rule'); const resIndexPattern = await kibanaServer.savedObjects.get({ type: 'index-pattern', id: 'test-*', @@ -472,6 +477,10 @@ const expectAssetsInstalled = ({ id: 'sample_search', type: 'search', }, + { + id: 'sample_security_rule', + type: 'security-rule', + }, { id: 'sample_visualization', type: 'visualization', @@ -537,6 +546,7 @@ const expectAssetsInstalled = ({ { id: 'e21b59b5-eb76-5ab0-bef2-1c8e379e6197', type: 'epm-packages-assets' }, { id: '4c758d70-ecf1-56b3-b704-6d8374841b34', type: 'epm-packages-assets' }, { id: 'e786cbd9-0f3b-5a0b-82a6-db25145ebf58', type: 'epm-packages-assets' }, + { id: 'd8b175c3-0d42-5ec7-90c1-d1e4b307a4c2', type: 'epm-packages-assets' }, { id: '53c94591-aa33-591d-8200-cd524c2a0561', type: 'epm-packages-assets' }, { id: 'b658d2d4-752e-54b8-afc2-4c76155c1466', type: 'epm-packages-assets' }, ], diff --git a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts index 1a559ac5a5c7..9b55822311bd 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts @@ -296,6 +296,10 @@ export default function (providerContext: FtrProviderContext) { id: 'sample_lens', type: 'lens', }, + { + id: 'sample_security_rule', + type: 'security-rule', + }, { id: 'sample_ml_module', type: 'ml-module', @@ -350,6 +354,7 @@ export default function (providerContext: FtrProviderContext) { { id: '7f4c5aca-b4f5-5f0a-95af-051da37513fc', type: 'epm-packages-assets' }, { id: '4281a436-45a8-54ab-9724-fda6849f789d', type: 'epm-packages-assets' }, { id: '2e56f08b-1d06-55ed-abee-4708e1ccf0aa', type: 'epm-packages-assets' }, + { id: '4035007b-9c33-5227-9803-2de8a17523b5', type: 'epm-packages-assets' }, { id: 'c7bf1a39-e057-58a0-afde-fb4b48751d8c', type: 'epm-packages-assets' }, { id: '8c665f28-a439-5f43-b5fd-8fda7b576735', type: 'epm-packages-assets' }, ], diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/security_rule/sample_security_rule.json b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/security_rule/sample_security_rule.json new file mode 100644 index 000000000000..6bedde67b892 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/security_rule/sample_security_rule.json @@ -0,0 +1,50 @@ +{ + "attributes": { + "author": [ + "Elastic" + ], + "description": "Identifies a suspicious parent child process relationship with cmd.exe descending from svchost.exe", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-endpoint.events.*", + "logs-windows.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Svchost spawning Cmd", + "query": "event.category:process and event.type:(start or process_started) and process.parent.name:svchost.exe and process.name:cmd.exe", + "risk_score": 21, + "rule_id": "sample_security_rule", + "severity": "low", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Execution" + ], + "threat": [ + { + "framework": "MITRE ATT\u0026CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command and Scripting Interpreter", + "reference": "https://attack.mitre.org/techniques/T1059/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 7 + }, + "id": "sample_security_rule", + "type": "security-rule" +} diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/security_rule/sample_security_rule.json b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/security_rule/sample_security_rule.json new file mode 100644 index 000000000000..6bedde67b892 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/security_rule/sample_security_rule.json @@ -0,0 +1,50 @@ +{ + "attributes": { + "author": [ + "Elastic" + ], + "description": "Identifies a suspicious parent child process relationship with cmd.exe descending from svchost.exe", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-endpoint.events.*", + "logs-windows.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Svchost spawning Cmd", + "query": "event.category:process and event.type:(start or process_started) and process.parent.name:svchost.exe and process.name:cmd.exe", + "risk_score": 21, + "rule_id": "sample_security_rule", + "severity": "low", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Execution" + ], + "threat": [ + { + "framework": "MITRE ATT\u0026CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command and Scripting Interpreter", + "reference": "https://attack.mitre.org/techniques/T1059/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 7 + }, + "id": "sample_security_rule", + "type": "security-rule" +} From 5180afc26312995db2cba7d373a725bafcf9ac20 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Thu, 8 Apr 2021 02:13:14 -0600 Subject: [PATCH 13/49] [Detection Rules] Resolves regression where Elastic Endgame rules would warn about unmapped timestamp override field (#96394) (#96528) related to https://github.com/elastic/detection-rules/pull/1082 ## Summary Endgame promotion rules in Kibana/7.12 are at version 5 and have timestamp_override defined (which should not be). These same rules are at version 4 in the detection-rules repo 7.12 branch and kibana/master and timestamp_override is not defined. These updates are targeted for 7.12.1 There most likely was an issue with the maze of backports and interlaced updates. To fix the rules, they need to be reconciled across: detection-rules 7.12 & main kibana 7.12.1 and master bump detection-rules/7.12 to v6 -> PR to kibana/master -> backport to 7.12.1 ### Checklist Delete any items that are not applicable to this PR. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/master/packages/kbn-i18n/README.md) ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) # Conflicts: # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_adversary_behavior_detected.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_detected.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_prevented.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_detected.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_prevented.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_detected.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_prevented.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_detected.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_prevented.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_detected.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_prevented.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_detected.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_prevented.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_detected.json # x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_prevented.json Co-authored-by: Justin Ibarra --- .../prepackaged_rules/endgame_adversary_behavior_detected.json | 3 +-- .../rules/prepackaged_rules/endgame_cred_dumping_detected.json | 3 +-- .../prepackaged_rules/endgame_cred_dumping_prevented.json | 3 +-- .../prepackaged_rules/endgame_cred_manipulation_detected.json | 3 +-- .../prepackaged_rules/endgame_cred_manipulation_prevented.json | 3 +-- .../rules/prepackaged_rules/endgame_exploit_detected.json | 3 +-- .../rules/prepackaged_rules/endgame_exploit_prevented.json | 3 +-- .../rules/prepackaged_rules/endgame_malware_detected.json | 3 +-- .../rules/prepackaged_rules/endgame_malware_prevented.json | 3 +-- .../prepackaged_rules/endgame_permission_theft_detected.json | 3 +-- .../prepackaged_rules/endgame_permission_theft_prevented.json | 3 +-- .../prepackaged_rules/endgame_process_injection_detected.json | 3 +-- .../prepackaged_rules/endgame_process_injection_prevented.json | 3 +-- .../rules/prepackaged_rules/endgame_ransomware_detected.json | 3 +-- .../rules/prepackaged_rules/endgame_ransomware_prevented.json | 3 +-- 15 files changed, 15 insertions(+), 30 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_adversary_behavior_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_adversary_behavior_detected.json index bf75f431da71..bf53625cef75 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_adversary_behavior_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_adversary_behavior_detected.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_detected.json index 3bc78b5f9b33..43cb19f50d67 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_detected.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_prevented.json index 4c81580727c2..29b5bc3f39cf 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_prevented.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_detected.json index 530daa7d5862..393591a24111 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_detected.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_prevented.json index c23c7cc4e301..e9ca199c4a79 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_prevented.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_detected.json index fed4b0d87c54..a169582c2da9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_detected.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_prevented.json index 84c4c0356bb6..b781a1fae184 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_prevented.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_detected.json index 0bca9c21bcc3..f7a064961f03 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_detected.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_prevented.json index 192c1b40e4c1..59cbd98e2d42 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_prevented.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_detected.json index 5f88961b724b..b3db96d6d121 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_detected.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_prevented.json index 80745c301ca4..18b316a293da 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_prevented.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_detected.json index 2510abc2b7bf..861daa2d004c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_detected.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_prevented.json index 79c262a8d68f..5f78a3517e93 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_prevented.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_detected.json index 6d378f712810..4c060bb52f32 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_detected.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_prevented.json index 0e4373825c95..78845ffc4c84 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_prevented.json @@ -19,7 +19,6 @@ "Elastic", "Elastic Endgame" ], - "timestamp_override": "event.ingested", "type": "query", - "version": 5 + "version": 6 } From 048b9f3c171fb14e54b9a166e3663bda342ce185 Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 8 Apr 2021 02:09:29 -0700 Subject: [PATCH 14/49] skip suite blocking es promotion (#96515) (cherry picked from commit f9317281d1ebdb8fb2aadf9f6a716cd776a51299) --- x-pack/test/fleet_api_integration/apis/agents_setup.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/fleet_api_integration/apis/agents_setup.ts b/x-pack/test/fleet_api_integration/apis/agents_setup.ts index 91d6ca0119d1..d49bc91251b0 100644 --- a/x-pack/test/fleet_api_integration/apis/agents_setup.ts +++ b/x-pack/test/fleet_api_integration/apis/agents_setup.ts @@ -15,7 +15,8 @@ export default function (providerContext: FtrProviderContext) { const es = getService('es'); const esArchiver = getService('esArchiver'); - describe('fleet_agents_setup', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/96515 + describe.skip('fleet_agents_setup', () => { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('empty_kibana'); From 8589455db7e7368ccf70505bdb0965e14dcdb883 Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Thu, 8 Apr 2021 06:23:19 -0400 Subject: [PATCH 15/49] [SECURITY SOLUTION] Add new exception list type and feature flag for event filtering (#96037) (#96485) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * New exception list type for event filtering * New feature flag for event filtering Co-authored-by: David Sánchez Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/lists/common/schemas/common/schemas.ts | 7 ++++++- .../common/detection_engine/schemas/types/lists.test.ts | 6 +++--- .../security_solution/common/experimental_features.ts | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/lists/common/schemas/common/schemas.ts b/x-pack/plugins/lists/common/schemas/common/schemas.ts index e553b65a2f61..f261e4e3eefa 100644 --- a/x-pack/plugins/lists/common/schemas/common/schemas.ts +++ b/x-pack/plugins/lists/common/schemas/common/schemas.ts @@ -212,13 +212,18 @@ export type Tags = t.TypeOf; export const tagsOrUndefined = t.union([tags, t.undefined]); export type TagsOrUndefined = t.TypeOf; -export const exceptionListType = t.keyof({ detection: null, endpoint: null }); +export const exceptionListType = t.keyof({ + detection: null, + endpoint: null, + endpoint_events: null, +}); export const exceptionListTypeOrUndefined = t.union([exceptionListType, t.undefined]); export type ExceptionListType = t.TypeOf; export type ExceptionListTypeOrUndefined = t.TypeOf; export enum ExceptionListTypeEnum { DETECTION = 'detection', ENDPOINT = 'endpoint', + ENDPOINT_EVENTS = 'endpoint_events', } export const exceptionListItemType = t.keyof({ simple: null }); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/types/lists.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/types/lists.test.ts index e331eea51eec..28b70f51742a 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/types/lists.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/types/lists.test.ts @@ -94,7 +94,7 @@ describe('Lists', () => { const message = pipe(decoded, foldLeftRight); expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "Array<{| id: NonEmptyString, list_id: NonEmptyString, type: "detection" | "endpoint", namespace_type: "agnostic" | "single" |}>"', + 'Invalid value "1" supplied to "Array<{| id: NonEmptyString, list_id: NonEmptyString, type: "detection" | "endpoint" | "endpoint_events", namespace_type: "agnostic" | "single" |}>"', ]); expect(message.schema).toEqual({}); }); @@ -125,8 +125,8 @@ describe('Lists', () => { const message = pipe(decoded, foldLeftRight); expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "1" supplied to "(Array<{| id: NonEmptyString, list_id: NonEmptyString, type: "detection" | "endpoint", namespace_type: "agnostic" | "single" |}> | undefined)"', - 'Invalid value "[1]" supplied to "(Array<{| id: NonEmptyString, list_id: NonEmptyString, type: "detection" | "endpoint", namespace_type: "agnostic" | "single" |}> | undefined)"', + 'Invalid value "1" supplied to "(Array<{| id: NonEmptyString, list_id: NonEmptyString, type: "detection" | "endpoint" | "endpoint_events", namespace_type: "agnostic" | "single" |}> | undefined)"', + 'Invalid value "[1]" supplied to "(Array<{| id: NonEmptyString, list_id: NonEmptyString, type: "detection" | "endpoint" | "endpoint_events", namespace_type: "agnostic" | "single" |}> | undefined)"', ]); expect(message.schema).toEqual({}); }); diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index 19de81cb95c3..39551e3ee6f1 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -14,6 +14,7 @@ export type ExperimentalFeatures = typeof allowedExperimentalValues; const allowedExperimentalValues = Object.freeze({ fleetServerEnabled: false, trustedAppsByPolicyEnabled: false, + eventFilteringEnabled: false, }); type ExperimentalConfigKeys = Array; From ed3d8b574d040270acf1ca6cb3da6b46cf64f84c Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 8 Apr 2021 07:34:28 -0400 Subject: [PATCH 16/49] Skip rendering empty add action variables button as disabled (#96342) (#96541) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Skip rendering empty add action variables button * Fix jest tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Mike Côté --- .../components/add_message_variables.test.tsx | 12 ++++++++++++ .../application/components/add_message_variables.tsx | 7 +++++-- .../es_index/es_index_params.test.tsx | 7 +++++++ .../pagerduty/pagerduty_params.test.tsx | 7 +++++++ .../webhook/webhook_params.test.tsx | 7 +++++++ 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.test.tsx index 8d27edd9e4bc..4e03a2a09bed 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.test.tsx @@ -117,4 +117,16 @@ describe('AddMessageVariables', () => { wrapper.find('button[data-test-subj="variableMenuButton-deprecatedVar"]').getDOMNode() ).toBeDisabled(); }); + + test(`it does't render when no variables exist`, () => { + const wrapper = mountWithIntl( + + ); + + expect(wrapper.find('[data-test-subj="fooAddVariableButton"]')).toHaveLength(0); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx index bf89e4f6ae6e..57b251fba0d4 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/add_message_variables.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useState } from 'react'; +import React, { useState, Fragment } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiPopover, @@ -61,13 +61,16 @@ export const AddMessageVariables: React.FunctionComponent = ({ } ); + if ((messageVariables?.length ?? 0) === 0) { + return ; + } + return ( setIsVariablesPopoverOpen(true)} iconType="indexOpen" diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.test.tsx index 97c1c41f6873..b792cf657445 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/es_index/es_index_params.test.tsx @@ -22,6 +22,13 @@ describe('IndexParamsFields renders', () => { errors={{ index: [] }} editAction={() => {}} index={0} + messageVariables={[ + { + name: 'myVar', + description: 'My variable description', + useWithTripleBracesInTemplates: true, + }, + ]} /> ); expect(wrapper.find('[data-test-subj="documentsJsonEditor"]').first().prop('value')).toBe(`{ diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.test.tsx index 6e3f4213b790..4d47cbf3685a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/pagerduty/pagerduty_params.test.tsx @@ -30,6 +30,13 @@ describe('PagerDutyParamsFields renders', () => { errors={{ summary: [], timestamp: [], dedupKey: [] }} editAction={() => {}} index={0} + messageVariables={[ + { + name: 'myVar', + description: 'My variable description', + useWithTripleBracesInTemplates: true, + }, + ]} /> ); expect(wrapper.find('[data-test-subj="severitySelect"]').length > 0).toBeTruthy(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.test.tsx index 801d9a6b43ec..a3756ae74fd1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_params.test.tsx @@ -21,6 +21,13 @@ describe('WebhookParamsFields renders', () => { errors={{ body: [] }} editAction={() => {}} index={0} + messageVariables={[ + { + name: 'myVar', + description: 'My variable description', + useWithTripleBracesInTemplates: true, + }, + ]} /> ); expect(wrapper.find('[data-test-subj="bodyJsonEditor"]').length > 0).toBeTruthy(); From e88148235deff84ba64d1514d40e012f599d5893 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 8 Apr 2021 08:43:05 -0400 Subject: [PATCH 17/49] [Telemetry] enforce import export type (#96487) (#96546) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: hardikpnsp --- packages/kbn-analytics/tsconfig.json | 1 + packages/kbn-telemetry-tools/src/tools/tasks/index.ts | 4 +++- packages/kbn-telemetry-tools/tsconfig.json | 3 ++- src/plugins/kibana_usage_collection/tsconfig.json | 3 ++- .../telemetry/common/telemetry_config/index.ts | 6 ++---- src/plugins/telemetry/public/index.ts | 2 +- src/plugins/telemetry/server/index.ts | 9 ++++++--- .../telemetry_collection/get_data_telemetry/index.ts | 9 ++------- .../telemetry/server/telemetry_collection/index.ts | 11 ++++------- .../telemetry/server/telemetry_repository/index.ts | 2 +- src/plugins/telemetry/tsconfig.json | 3 ++- .../telemetry_collection_manager/server/index.ts | 2 +- .../telemetry_collection_manager/tsconfig.json | 3 ++- .../telemetry_management_section/public/index.ts | 2 +- .../telemetry_management_section/tsconfig.json | 3 ++- src/plugins/usage_collection/public/index.ts | 2 +- .../usage_collection/server/collector/index.ts | 10 ++++++---- src/plugins/usage_collection/server/index.ts | 7 +++---- .../usage_collection/server/usage_collection.mock.ts | 3 ++- src/plugins/usage_collection/tsconfig.json | 3 ++- .../telemetry_collection_xpack/server/index.ts | 2 +- .../server/telemetry_collection/index.ts | 2 +- .../plugins/telemetry_collection_xpack/tsconfig.json | 3 ++- 23 files changed, 50 insertions(+), 45 deletions(-) diff --git a/packages/kbn-analytics/tsconfig.json b/packages/kbn-analytics/tsconfig.json index c2e579e7fdbe..80a2255d7180 100644 --- a/packages/kbn-analytics/tsconfig.json +++ b/packages/kbn-analytics/tsconfig.json @@ -7,6 +7,7 @@ "emitDeclarationOnly": true, "declaration": true, "declarationMap": true, + "isolatedModules": true, "sourceMap": true, "sourceRoot": "../../../../../packages/kbn-analytics/src", "types": [ diff --git a/packages/kbn-telemetry-tools/src/tools/tasks/index.ts b/packages/kbn-telemetry-tools/src/tools/tasks/index.ts index 5d946b73d975..f55a9aa80d40 100644 --- a/packages/kbn-telemetry-tools/src/tools/tasks/index.ts +++ b/packages/kbn-telemetry-tools/src/tools/tasks/index.ts @@ -7,7 +7,9 @@ */ export { ErrorReporter } from './error_reporter'; -export { TaskContext, createTaskContext } from './task_context'; + +export type { TaskContext } from './task_context'; +export { createTaskContext } from './task_context'; export { parseConfigsTask } from './parse_configs_task'; export { extractCollectorsTask } from './extract_collectors_task'; diff --git a/packages/kbn-telemetry-tools/tsconfig.json b/packages/kbn-telemetry-tools/tsconfig.json index 39946fe9907e..419af1d02f83 100644 --- a/packages/kbn-telemetry-tools/tsconfig.json +++ b/packages/kbn-telemetry-tools/tsconfig.json @@ -6,7 +6,8 @@ "declaration": true, "declarationMap": true, "sourceMap": true, - "sourceRoot": "../../../../packages/kbn-telemetry-tools/src" + "sourceRoot": "../../../../packages/kbn-telemetry-tools/src", + "isolatedModules": true }, "include": [ "src/**/*", diff --git a/src/plugins/kibana_usage_collection/tsconfig.json b/src/plugins/kibana_usage_collection/tsconfig.json index d664d936f666..ee07dfe589e4 100644 --- a/src/plugins/kibana_usage_collection/tsconfig.json +++ b/src/plugins/kibana_usage_collection/tsconfig.json @@ -5,7 +5,8 @@ "outDir": "./target/types", "emitDeclarationOnly": true, "declaration": true, - "declarationMap": true + "declarationMap": true, + "isolatedModules": true }, "include": [ "common/*", diff --git a/src/plugins/telemetry/common/telemetry_config/index.ts b/src/plugins/telemetry/common/telemetry_config/index.ts index 84b6486f35b2..cc4ff102742d 100644 --- a/src/plugins/telemetry/common/telemetry_config/index.ts +++ b/src/plugins/telemetry/common/telemetry_config/index.ts @@ -9,7 +9,5 @@ export { getTelemetryOptIn } from './get_telemetry_opt_in'; export { getTelemetrySendUsageFrom } from './get_telemetry_send_usage_from'; export { getTelemetryAllowChangingOptInStatus } from './get_telemetry_allow_changing_opt_in_status'; -export { - getTelemetryFailureDetails, - TelemetryFailureDetails, -} from './get_telemetry_failure_details'; +export { getTelemetryFailureDetails } from './get_telemetry_failure_details'; +export type { TelemetryFailureDetails } from './get_telemetry_failure_details'; diff --git a/src/plugins/telemetry/public/index.ts b/src/plugins/telemetry/public/index.ts index 6cca9bdf881d..47ba7828eaec 100644 --- a/src/plugins/telemetry/public/index.ts +++ b/src/plugins/telemetry/public/index.ts @@ -8,7 +8,7 @@ import { PluginInitializerContext } from 'kibana/public'; import { TelemetryPlugin, TelemetryPluginConfig } from './plugin'; -export { TelemetryPluginStart, TelemetryPluginSetup } from './plugin'; +export type { TelemetryPluginStart, TelemetryPluginSetup } from './plugin'; export function plugin(initializerContext: PluginInitializerContext) { return new TelemetryPlugin(initializerContext); diff --git a/src/plugins/telemetry/server/index.ts b/src/plugins/telemetry/server/index.ts index debdf7515cd5..1c335426ffd0 100644 --- a/src/plugins/telemetry/server/index.ts +++ b/src/plugins/telemetry/server/index.ts @@ -13,7 +13,7 @@ import { configSchema, TelemetryConfigType } from './config'; export { FetcherTask } from './fetcher'; export { handleOldSettings } from './handle_old_settings'; -export { TelemetryPluginSetup, TelemetryPluginStart } from './plugin'; +export type { TelemetryPluginSetup, TelemetryPluginStart } from './plugin'; export const config: PluginConfigDescriptor = { schema: configSchema, @@ -34,9 +34,12 @@ export { constants }; export { getClusterUuids, getLocalStats, - TelemetryLocalStats, DATA_TELEMETRY_ID, + buildDataTelemetryPayload, +} from './telemetry_collection'; + +export type { + TelemetryLocalStats, DataTelemetryIndex, DataTelemetryPayload, - buildDataTelemetryPayload, } from './telemetry_collection'; diff --git a/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/index.ts b/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/index.ts index def1131dfb1a..c93b7e872924 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/index.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/index.ts @@ -7,10 +7,5 @@ */ export { DATA_TELEMETRY_ID } from './constants'; - -export { - getDataTelemetry, - buildDataTelemetryPayload, - DataTelemetryPayload, - DataTelemetryIndex, -} from './get_data_telemetry'; +export { getDataTelemetry, buildDataTelemetryPayload } from './get_data_telemetry'; +export type { DataTelemetryPayload, DataTelemetryIndex } from './get_data_telemetry'; diff --git a/src/plugins/telemetry/server/telemetry_collection/index.ts b/src/plugins/telemetry/server/telemetry_collection/index.ts index 55f9c7f0e624..151e89a11a19 100644 --- a/src/plugins/telemetry/server/telemetry_collection/index.ts +++ b/src/plugins/telemetry/server/telemetry_collection/index.ts @@ -6,12 +6,9 @@ * Side Public License, v 1. */ -export { - DATA_TELEMETRY_ID, - DataTelemetryIndex, - DataTelemetryPayload, - buildDataTelemetryPayload, -} from './get_data_telemetry'; -export { getLocalStats, TelemetryLocalStats } from './get_local_stats'; +export { DATA_TELEMETRY_ID, buildDataTelemetryPayload } from './get_data_telemetry'; +export type { DataTelemetryIndex, DataTelemetryPayload } from './get_data_telemetry'; +export { getLocalStats } from './get_local_stats'; +export type { TelemetryLocalStats } from './get_local_stats'; export { getClusterUuids } from './get_cluster_stats'; export { registerCollection } from './register_collection'; diff --git a/src/plugins/telemetry/server/telemetry_repository/index.ts b/src/plugins/telemetry/server/telemetry_repository/index.ts index 4e3f046f7611..594b53259a65 100644 --- a/src/plugins/telemetry/server/telemetry_repository/index.ts +++ b/src/plugins/telemetry/server/telemetry_repository/index.ts @@ -8,7 +8,7 @@ export { getTelemetrySavedObject } from './get_telemetry_saved_object'; export { updateTelemetrySavedObject } from './update_telemetry_saved_object'; -export { +export type { TelemetrySavedObject, TelemetrySavedObjectAttributes, } from '../../common/telemetry_config/types'; diff --git a/src/plugins/telemetry/tsconfig.json b/src/plugins/telemetry/tsconfig.json index bdced01d9eb6..6629e479906c 100644 --- a/src/plugins/telemetry/tsconfig.json +++ b/src/plugins/telemetry/tsconfig.json @@ -5,7 +5,8 @@ "outDir": "./target/types", "emitDeclarationOnly": true, "declaration": true, - "declarationMap": true + "declarationMap": true, + "isolatedModules": true }, "include": [ "public/**/**/*", diff --git a/src/plugins/telemetry_collection_manager/server/index.ts b/src/plugins/telemetry_collection_manager/server/index.ts index 77077b73cf8a..c0cd124a132c 100644 --- a/src/plugins/telemetry_collection_manager/server/index.ts +++ b/src/plugins/telemetry_collection_manager/server/index.ts @@ -16,7 +16,7 @@ export function plugin(initializerContext: PluginInitializerContext) { return new TelemetryCollectionManagerPlugin(initializerContext); } -export { +export type { TelemetryCollectionManagerPluginSetup, TelemetryCollectionManagerPluginStart, StatsCollectionConfig, diff --git a/src/plugins/telemetry_collection_manager/tsconfig.json b/src/plugins/telemetry_collection_manager/tsconfig.json index 1bba81769f0d..132997986060 100644 --- a/src/plugins/telemetry_collection_manager/tsconfig.json +++ b/src/plugins/telemetry_collection_manager/tsconfig.json @@ -5,7 +5,8 @@ "outDir": "./target/types", "emitDeclarationOnly": true, "declaration": true, - "declarationMap": true + "declarationMap": true, + "isolatedModules": true }, "include": [ "server/**/*", diff --git a/src/plugins/telemetry_management_section/public/index.ts b/src/plugins/telemetry_management_section/public/index.ts index 28b04418f512..db6ea17556ed 100644 --- a/src/plugins/telemetry_management_section/public/index.ts +++ b/src/plugins/telemetry_management_section/public/index.ts @@ -10,7 +10,7 @@ import { TelemetryManagementSectionPlugin } from './plugin'; export { OptInExampleFlyout } from './components'; -export { TelemetryManagementSectionPluginSetup } from './plugin'; +export type { TelemetryManagementSectionPluginSetup } from './plugin'; export function plugin() { return new TelemetryManagementSectionPlugin(); } diff --git a/src/plugins/telemetry_management_section/tsconfig.json b/src/plugins/telemetry_management_section/tsconfig.json index 48e40814b857..2daee868ac20 100644 --- a/src/plugins/telemetry_management_section/tsconfig.json +++ b/src/plugins/telemetry_management_section/tsconfig.json @@ -5,7 +5,8 @@ "outDir": "./target/types", "emitDeclarationOnly": true, "declaration": true, - "declarationMap": true + "declarationMap": true, + "isolatedModules": true }, "include": [ "public/**/*", diff --git a/src/plugins/usage_collection/public/index.ts b/src/plugins/usage_collection/public/index.ts index b9e0e0a8985b..9b009b1d9e26 100644 --- a/src/plugins/usage_collection/public/index.ts +++ b/src/plugins/usage_collection/public/index.ts @@ -10,7 +10,7 @@ import { PluginInitializerContext } from '../../../core/public'; import { UsageCollectionPlugin } from './plugin'; export { METRIC_TYPE } from '@kbn/analytics'; -export { UsageCollectionSetup, UsageCollectionStart } from './plugin'; +export type { UsageCollectionSetup, UsageCollectionStart } from './plugin'; export { TrackApplicationView } from './components'; export function plugin(initializerContext: PluginInitializerContext) { diff --git a/src/plugins/usage_collection/server/collector/index.ts b/src/plugins/usage_collection/server/collector/index.ts index 5f48f9fb9381..d5e0d95659e5 100644 --- a/src/plugins/usage_collection/server/collector/index.ts +++ b/src/plugins/usage_collection/server/collector/index.ts @@ -6,9 +6,10 @@ * Side Public License, v 1. */ -export { CollectorSet, CollectorSetPublic } from './collector_set'; -export { - Collector, +export { CollectorSet } from './collector_set'; +export type { CollectorSetPublic } from './collector_set'; +export { Collector } from './collector'; +export type { AllowedSchemaTypes, AllowedSchemaNumberTypes, SchemaField, @@ -16,4 +17,5 @@ export { CollectorOptions, CollectorFetchContext, } from './collector'; -export { UsageCollector, UsageCollectorOptions } from './usage_collector'; +export { UsageCollector } from './usage_collector'; +export type { UsageCollectorOptions } from './usage_collector'; diff --git a/src/plugins/usage_collection/server/index.ts b/src/plugins/usage_collection/server/index.ts index dfc9d19b6964..dd9e6644a827 100644 --- a/src/plugins/usage_collection/server/index.ts +++ b/src/plugins/usage_collection/server/index.ts @@ -9,17 +9,16 @@ import { PluginInitializerContext } from 'src/core/server'; import { UsageCollectionPlugin } from './plugin'; -export { +export { Collector } from './collector'; +export type { AllowedSchemaTypes, MakeSchemaFrom, SchemaField, CollectorOptions, UsageCollectorOptions, - Collector, CollectorFetchContext, } from './collector'; - -export { UsageCollectionSetup } from './plugin'; +export type { UsageCollectionSetup } from './plugin'; export { config } from './config'; export const plugin = (initializerContext: PluginInitializerContext) => new UsageCollectionPlugin(initializerContext); diff --git a/src/plugins/usage_collection/server/usage_collection.mock.ts b/src/plugins/usage_collection/server/usage_collection.mock.ts index 1a60d84e7948..7e3f4273bbea 100644 --- a/src/plugins/usage_collection/server/usage_collection.mock.ts +++ b/src/plugins/usage_collection/server/usage_collection.mock.ts @@ -16,7 +16,8 @@ import { import { CollectorOptions, Collector, UsageCollector } from './collector'; import { UsageCollectionSetup, CollectorFetchContext } from './index'; -export { CollectorOptions, Collector }; +export type { CollectorOptions }; +export { Collector }; const logger = loggingSystemMock.createLogger(); diff --git a/src/plugins/usage_collection/tsconfig.json b/src/plugins/usage_collection/tsconfig.json index 96b2c4d37e17..68a0853994e8 100644 --- a/src/plugins/usage_collection/tsconfig.json +++ b/src/plugins/usage_collection/tsconfig.json @@ -5,7 +5,8 @@ "outDir": "./target/types", "emitDeclarationOnly": true, "declaration": true, - "declarationMap": true + "declarationMap": true, + "isolatedModules": true }, "include": [ "public/**/*", diff --git a/x-pack/plugins/telemetry_collection_xpack/server/index.ts b/x-pack/plugins/telemetry_collection_xpack/server/index.ts index d924882e17fb..aab1bdb58fe5 100644 --- a/x-pack/plugins/telemetry_collection_xpack/server/index.ts +++ b/x-pack/plugins/telemetry_collection_xpack/server/index.ts @@ -7,7 +7,7 @@ import { TelemetryCollectionXpackPlugin } from './plugin'; -export { ESLicense } from './telemetry_collection'; +export type { ESLicense } from './telemetry_collection'; // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. diff --git a/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/index.ts b/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/index.ts index 4599b068b9b3..c1a11caf44f2 100644 --- a/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/index.ts +++ b/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/index.ts @@ -5,5 +5,5 @@ * 2.0. */ -export { ESLicense } from './get_license'; +export type { ESLicense } from './get_license'; export { getStatsWithXpack } from './get_stats_with_xpack'; diff --git a/x-pack/plugins/telemetry_collection_xpack/tsconfig.json b/x-pack/plugins/telemetry_collection_xpack/tsconfig.json index 476f5926f757..1221200c7548 100644 --- a/x-pack/plugins/telemetry_collection_xpack/tsconfig.json +++ b/x-pack/plugins/telemetry_collection_xpack/tsconfig.json @@ -5,7 +5,8 @@ "outDir": "./target/types", "emitDeclarationOnly": true, "declaration": true, - "declarationMap": true + "declarationMap": true, + "isolatedModules": true }, "include": [ "common/**/*", From 5ae94462603fc800fd2f5d0cee105f12d3794098 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 8 Apr 2021 09:16:58 -0400 Subject: [PATCH 18/49] [ML] Fix switches positioning on the Transform and DFA wizards (#96535) (#96549) * [ML] fix edit runtime mapping switch positioning * [ML] fix transform wizard switches Co-authored-by: Dima Arnautov --- .../components/runtime_mappings/runtime_mappings.tsx | 2 +- .../advanced_runtime_mappings_settings.tsx | 2 +- .../components/step_define/step_define_form.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/runtime_mappings/runtime_mappings.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/runtime_mappings/runtime_mappings.tsx index d21bf67a1f51..5b8fc82ef587 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/runtime_mappings/runtime_mappings.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/runtime_mappings/runtime_mappings.tsx @@ -131,7 +131,7 @@ export const RuntimeMappings: FC = ({ actions, state }) => { defaultMessage: 'Runtime mappings', })} > - + {isPopulatedObject(runtimeMappings) ? ( diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/advanced_runtime_mappings_settings/advanced_runtime_mappings_settings.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/advanced_runtime_mappings_settings/advanced_runtime_mappings_settings.tsx index 277226c81c92..7965db99b335 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/advanced_runtime_mappings_settings/advanced_runtime_mappings_settings.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/advanced_runtime_mappings_settings/advanced_runtime_mappings_settings.tsx @@ -91,7 +91,7 @@ export const AdvancedRuntimeMappingsSettings: FC = (props) = defaultMessage: 'Runtime mappings', })} > - + {runtimeMappings !== undefined && Object.keys(runtimeMappings).length > 0 ? ( = React.memo((props) => { } > <> - + {/* Flex Column #1: Search Bar / Advanced Search Editor */} {searchItems.savedSearch === undefined && ( From d972b8e50bb80cc38dc328c3bc3fd5569f257a73 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 8 Apr 2021 09:52:29 -0400 Subject: [PATCH 19/49] [Alerting] Update feature privilege display names (#96083) (#96554) * Updating feature display names * Updating feature display names Co-authored-by: ymao1 --- x-pack/examples/alerting_example/server/plugin.ts | 2 +- x-pack/plugins/stack_alerts/server/feature.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/examples/alerting_example/server/plugin.ts b/x-pack/examples/alerting_example/server/plugin.ts index db9c996147c9..f6131679874d 100644 --- a/x-pack/examples/alerting_example/server/plugin.ts +++ b/x-pack/examples/alerting_example/server/plugin.ts @@ -33,7 +33,7 @@ export class AlertingExamplePlugin implements Plugin Date: Thu, 8 Apr 2021 15:57:04 +0200 Subject: [PATCH 20/49] [7.x] [APM] Extract server type utils to package (#96349) (#96552) --- package.json | 2 + packages/kbn-io-ts-utils/jest.config.js | 13 + packages/kbn-io-ts-utils/package.json | 13 + packages/kbn-io-ts-utils/src/index.ts | 11 + .../src}/json_rt/index.test.ts | 9 +- .../kbn-io-ts-utils/src}/json_rt/index.ts | 5 +- .../src/merge_rt}/index.test.ts | 25 +- .../kbn-io-ts-utils/src/merge_rt}/index.ts | 37 +- .../src}/strict_keys_rt/index.test.ts | 28 +- .../src}/strict_keys_rt/index.ts | 78 +-- packages/kbn-io-ts-utils/tsconfig.json | 19 + .../kbn-server-route-repository/README.md | 7 + .../jest.config.js | 13 + .../kbn-server-route-repository/package.json | 16 + .../src/create_server_route_factory.ts | 38 ++ .../src/create_server_route_repository.ts | 39 ++ .../src/decode_request_params.test.ts | 122 +++++ .../src/decode_request_params.ts | 43 ++ .../src/format_request.ts | 20 + .../kbn-server-route-repository/src/index.ts | 24 + .../src/parse_endpoint.ts | 22 + .../src/route_validation_object.ts | 20 + .../src/test_types.ts | 238 ++++++++ .../src/typings.ts | 192 +++++++ .../kbn-server-route-repository/tsconfig.json | 20 + .../apm/common/latency_aggregation_types.ts | 6 +- .../runtime_types/iso_to_epoch_rt/index.ts | 5 +- .../link_preview.test.tsx | 9 +- .../CustomizeUI/CustomLink/index.test.tsx | 4 +- .../service_overview.test.tsx | 25 +- ...pm_observability_overview_fetchers.test.ts | 6 +- .../apm/public/services/rest/callApmApiSpy.ts | 24 + .../public/services/rest/createCallApmApi.ts | 83 ++- x-pack/plugins/apm/server/index.ts | 6 +- .../create_es_client/call_async_with_debug.ts | 2 +- .../create_internal_es_client/index.ts | 11 +- .../server/lib/helpers/setup_request.test.ts | 127 ++--- .../apm/server/lib/helpers/setup_request.ts | 33 +- .../create_static_index_pattern.test.ts | 36 +- .../create_static_index_pattern.ts | 8 +- .../get_apm_index_pattern_title.ts | 8 +- .../get_dynamic_index_pattern.ts | 12 +- .../settings/apm_indices/get_apm_indices.ts | 9 +- x-pack/plugins/apm/server/plugin.ts | 100 ++-- .../apm/server/routes/alerts/chart_preview.ts | 40 +- .../plugins/apm/server/routes/correlations.ts | 47 +- .../server/routes/create_api/index.test.ts | 368 ------------- .../apm/server/routes/create_api/index.ts | 185 ------- .../apm/server/routes/create_apm_api.ts | 230 -------- .../server/routes/create_apm_server_route.ts | 13 + .../create_apm_server_route_repository.ts | 15 + .../plugins/apm/server/routes/create_route.ts | 29 - .../plugins/apm/server/routes/environments.ts | 16 +- x-pack/plugins/apm/server/routes/errors.ts | 35 +- .../get_global_apm_server_route_repository.ts | 82 +++ .../apm/server/routes/index_pattern.ts | 48 +- x-pack/plugins/apm/server/routes/metrics.ts | 15 +- .../server/routes/observability_overview.ts | 22 +- .../routes/register_routes/index.test.ts | 507 ++++++++++++++++++ .../server/routes/register_routes/index.ts | 143 +++++ .../plugins/apm/server/routes/rum_client.ts | 122 +++-- .../plugins/apm/server/routes/service_map.ts | 31 +- .../apm/server/routes/service_nodes.ts | 15 +- x-pack/plugins/apm/server/routes/services.ts | 214 +++++--- .../routes/settings/agent_configuration.ts | 99 ++-- .../routes/settings/anomaly_detection.ts | 35 +- .../apm/server/routes/settings/apm_indices.ts | 28 +- .../apm/server/routes/settings/custom_link.ts | 70 ++- x-pack/plugins/apm/server/routes/traces.ts | 37 +- .../plugins/apm/server/routes/transactions.ts | 106 ++-- x-pack/plugins/apm/server/routes/typings.ts | 188 ++----- x-pack/plugins/apm/server/types.ts | 164 ++++++ .../common/apm_api_supertest.ts | 19 +- .../tests/inspect/inspect.ts | 1 - .../instances_primary_statistics.ts | 7 +- yarn.lock | 8 + 76 files changed, 2822 insertions(+), 1685 deletions(-) create mode 100644 packages/kbn-io-ts-utils/jest.config.js create mode 100644 packages/kbn-io-ts-utils/package.json create mode 100644 packages/kbn-io-ts-utils/src/index.ts rename {x-pack/plugins/apm/common/runtime_types => packages/kbn-io-ts-utils/src}/json_rt/index.test.ts (85%) rename {x-pack/plugins/apm/common/runtime_types => packages/kbn-io-ts-utils/src}/json_rt/index.ts (74%) rename {x-pack/plugins/apm/common/runtime_types/merge => packages/kbn-io-ts-utils/src/merge_rt}/index.test.ts (66%) rename {x-pack/plugins/apm/common/runtime_types/merge => packages/kbn-io-ts-utils/src/merge_rt}/index.ts (62%) rename {x-pack/plugins/apm/common/runtime_types => packages/kbn-io-ts-utils/src}/strict_keys_rt/index.test.ts (77%) rename {x-pack/plugins/apm/common/runtime_types => packages/kbn-io-ts-utils/src}/strict_keys_rt/index.ts (66%) create mode 100644 packages/kbn-io-ts-utils/tsconfig.json create mode 100644 packages/kbn-server-route-repository/README.md create mode 100644 packages/kbn-server-route-repository/jest.config.js create mode 100644 packages/kbn-server-route-repository/package.json create mode 100644 packages/kbn-server-route-repository/src/create_server_route_factory.ts create mode 100644 packages/kbn-server-route-repository/src/create_server_route_repository.ts create mode 100644 packages/kbn-server-route-repository/src/decode_request_params.test.ts create mode 100644 packages/kbn-server-route-repository/src/decode_request_params.ts create mode 100644 packages/kbn-server-route-repository/src/format_request.ts create mode 100644 packages/kbn-server-route-repository/src/index.ts create mode 100644 packages/kbn-server-route-repository/src/parse_endpoint.ts create mode 100644 packages/kbn-server-route-repository/src/route_validation_object.ts create mode 100644 packages/kbn-server-route-repository/src/test_types.ts create mode 100644 packages/kbn-server-route-repository/src/typings.ts create mode 100644 packages/kbn-server-route-repository/tsconfig.json create mode 100644 x-pack/plugins/apm/public/services/rest/callApmApiSpy.ts delete mode 100644 x-pack/plugins/apm/server/routes/create_api/index.test.ts delete mode 100644 x-pack/plugins/apm/server/routes/create_api/index.ts delete mode 100644 x-pack/plugins/apm/server/routes/create_apm_api.ts create mode 100644 x-pack/plugins/apm/server/routes/create_apm_server_route.ts create mode 100644 x-pack/plugins/apm/server/routes/create_apm_server_route_repository.ts delete mode 100644 x-pack/plugins/apm/server/routes/create_route.ts create mode 100644 x-pack/plugins/apm/server/routes/get_global_apm_server_route_repository.ts create mode 100644 x-pack/plugins/apm/server/routes/register_routes/index.test.ts create mode 100644 x-pack/plugins/apm/server/routes/register_routes/index.ts create mode 100644 x-pack/plugins/apm/server/types.ts diff --git a/package.json b/package.json index 1aa32375411a..623247b4fd1a 100644 --- a/package.json +++ b/package.json @@ -128,10 +128,12 @@ "@kbn/crypto": "link:packages/kbn-crypto", "@kbn/i18n": "link:packages/kbn-i18n", "@kbn/interpreter": "link:packages/kbn-interpreter", + "@kbn/io-ts-utils": "link:packages/kbn-io-ts-utils", "@kbn/legacy-logging": "link:packages/kbn-legacy-logging", "@kbn/logging": "link:packages/kbn-logging", "@kbn/monaco": "link:packages/kbn-monaco", "@kbn/server-http-tools": "link:packages/kbn-server-http-tools", + "@kbn/server-route-repository": "link:packages/kbn-server-route-repository", "@kbn/std": "link:packages/kbn-std", "@kbn/tinymath": "link:packages/kbn-tinymath", "@kbn/ui-framework": "link:packages/kbn-ui-framework", diff --git a/packages/kbn-io-ts-utils/jest.config.js b/packages/kbn-io-ts-utils/jest.config.js new file mode 100644 index 000000000000..1a71166fae84 --- /dev/null +++ b/packages/kbn-io-ts-utils/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../..', + roots: ['/packages/kbn-io-ts-utils'], +}; diff --git a/packages/kbn-io-ts-utils/package.json b/packages/kbn-io-ts-utils/package.json new file mode 100644 index 000000000000..4d6f02d3f85a --- /dev/null +++ b/packages/kbn-io-ts-utils/package.json @@ -0,0 +1,13 @@ +{ + "name": "@kbn/io-ts-utils", + "main": "./target/index.js", + "types": "./target/index.d.ts", + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0", + "private": true, + "scripts": { + "build": "../../node_modules/.bin/tsc", + "kbn:bootstrap": "yarn build", + "kbn:watch": "yarn build --watch" + } +} diff --git a/packages/kbn-io-ts-utils/src/index.ts b/packages/kbn-io-ts-utils/src/index.ts new file mode 100644 index 000000000000..2032127b1eb9 --- /dev/null +++ b/packages/kbn-io-ts-utils/src/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { jsonRt } from './json_rt'; +export { mergeRt } from './merge_rt'; +export { strictKeysRt } from './strict_keys_rt'; diff --git a/x-pack/plugins/apm/common/runtime_types/json_rt/index.test.ts b/packages/kbn-io-ts-utils/src/json_rt/index.test.ts similarity index 85% rename from x-pack/plugins/apm/common/runtime_types/json_rt/index.test.ts rename to packages/kbn-io-ts-utils/src/json_rt/index.test.ts index d6c286c672d9..1220639fc7be 100644 --- a/x-pack/plugins/apm/common/runtime_types/json_rt/index.test.ts +++ b/packages/kbn-io-ts-utils/src/json_rt/index.test.ts @@ -1,8 +1,9 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import * as t from 'io-ts'; @@ -12,9 +13,7 @@ import { Right } from 'fp-ts/lib/Either'; import { pipe } from 'fp-ts/lib/pipeable'; import { identity } from 'fp-ts/lib/function'; -function getValueOrThrow>( - either: TEither -): Right { +function getValueOrThrow>(either: TEither): Right { const value = pipe( either, fold(() => { diff --git a/x-pack/plugins/apm/common/runtime_types/json_rt/index.ts b/packages/kbn-io-ts-utils/src/json_rt/index.ts similarity index 74% rename from x-pack/plugins/apm/common/runtime_types/json_rt/index.ts rename to packages/kbn-io-ts-utils/src/json_rt/index.ts index 0207145a17be..bc596d53db54 100644 --- a/x-pack/plugins/apm/common/runtime_types/json_rt/index.ts +++ b/packages/kbn-io-ts-utils/src/json_rt/index.ts @@ -1,8 +1,9 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import * as t from 'io-ts'; diff --git a/x-pack/plugins/apm/common/runtime_types/merge/index.test.ts b/packages/kbn-io-ts-utils/src/merge_rt/index.test.ts similarity index 66% rename from x-pack/plugins/apm/common/runtime_types/merge/index.test.ts rename to packages/kbn-io-ts-utils/src/merge_rt/index.test.ts index af5a0221662d..b25d4451895f 100644 --- a/x-pack/plugins/apm/common/runtime_types/merge/index.test.ts +++ b/packages/kbn-io-ts-utils/src/merge_rt/index.test.ts @@ -1,18 +1,19 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import * as t from 'io-ts'; import { isLeft } from 'fp-ts/lib/Either'; -import { merge } from './'; +import { mergeRt } from '.'; import { jsonRt } from '../json_rt'; describe('merge', () => { it('fails on one or more errors', () => { - const type = merge([t.type({ foo: t.string }), t.type({ bar: t.number })]); + const type = mergeRt(t.type({ foo: t.string }), t.type({ bar: t.number })); const result = type.decode({ foo: '' }); @@ -20,10 +21,7 @@ describe('merge', () => { }); it('merges left to right', () => { - const typeBoolean = merge([ - t.type({ foo: t.string }), - t.type({ foo: jsonRt.pipe(t.boolean) }), - ]); + const typeBoolean = mergeRt(t.type({ foo: t.string }), t.type({ foo: jsonRt.pipe(t.boolean) })); const resultBoolean = typeBoolean.decode({ foo: 'true', @@ -34,10 +32,7 @@ describe('merge', () => { foo: true, }); - const typeString = merge([ - t.type({ foo: jsonRt.pipe(t.boolean) }), - t.type({ foo: t.string }), - ]); + const typeString = mergeRt(t.type({ foo: jsonRt.pipe(t.boolean) }), t.type({ foo: t.string })); const resultString = typeString.decode({ foo: 'true', @@ -50,10 +45,10 @@ describe('merge', () => { }); it('deeply merges values', () => { - const type = merge([ + const type = mergeRt( t.type({ foo: t.type({ baz: t.string }) }), - t.type({ foo: t.type({ bar: t.string }) }), - ]); + t.type({ foo: t.type({ bar: t.string }) }) + ); const result = type.decode({ foo: { diff --git a/x-pack/plugins/apm/common/runtime_types/merge/index.ts b/packages/kbn-io-ts-utils/src/merge_rt/index.ts similarity index 62% rename from x-pack/plugins/apm/common/runtime_types/merge/index.ts rename to packages/kbn-io-ts-utils/src/merge_rt/index.ts index 451edf678aab..c582767fb510 100644 --- a/x-pack/plugins/apm/common/runtime_types/merge/index.ts +++ b/packages/kbn-io-ts-utils/src/merge_rt/index.ts @@ -1,31 +1,40 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import * as t from 'io-ts'; import { merge as lodashMerge } from 'lodash'; import { isLeft } from 'fp-ts/lib/Either'; -import { ValuesType } from 'utility-types'; -export type MergeType< - T extends t.Any[], - U extends ValuesType = ValuesType -> = t.Type & { - _tag: 'MergeType'; - types: T; -}; +type PlainObject = Record; + +type DeepMerge = U extends PlainObject + ? T extends PlainObject + ? Omit & + { + [key in keyof U]: T extends { [k in key]: any } ? DeepMerge : U[key]; + } + : U + : U; // this is similar to t.intersection, but does a deep merge // instead of a shallow merge -export function merge( - types: [A, B] -): MergeType<[A, B]>; +export type MergeType = t.Type< + DeepMerge, t.TypeOf>, + DeepMerge, t.OutputOf> +> & { + _tag: 'MergeType'; + types: [T1, T2]; +}; + +export function mergeRt(a: T1, b: T2): MergeType; -export function merge(types: t.Any[]) { +export function mergeRt(...types: t.Any[]) { const mergeType = new t.Type( 'merge', (u): u is unknown => { diff --git a/x-pack/plugins/apm/common/runtime_types/strict_keys_rt/index.test.ts b/packages/kbn-io-ts-utils/src/strict_keys_rt/index.test.ts similarity index 77% rename from x-pack/plugins/apm/common/runtime_types/strict_keys_rt/index.test.ts rename to packages/kbn-io-ts-utils/src/strict_keys_rt/index.test.ts index 4212e0430ff5..ab20ca42a283 100644 --- a/x-pack/plugins/apm/common/runtime_types/strict_keys_rt/index.test.ts +++ b/packages/kbn-io-ts-utils/src/strict_keys_rt/index.test.ts @@ -1,8 +1,9 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import * as t from 'io-ts'; @@ -14,10 +15,7 @@ describe('strictKeysRt', () => { it('correctly and deeply validates object keys', () => { const checks: Array<{ type: t.Type; passes: any[]; fails: any[] }> = [ { - type: t.intersection([ - t.type({ foo: t.string }), - t.partial({ bar: t.string }), - ]), + type: t.intersection([t.type({ foo: t.string }), t.partial({ bar: t.string })]), passes: [{ foo: '' }, { foo: '', bar: '' }], fails: [ { foo: '', unknownKey: '' }, @@ -26,15 +24,9 @@ describe('strictKeysRt', () => { }, { type: t.type({ - path: t.union([ - t.type({ serviceName: t.string }), - t.type({ transactionType: t.string }), - ]), + path: t.union([t.type({ serviceName: t.string }), t.type({ transactionType: t.string })]), }), - passes: [ - { path: { serviceName: '' } }, - { path: { transactionType: '' } }, - ], + passes: [{ path: { serviceName: '' } }, { path: { transactionType: '' } }], fails: [ { path: { serviceName: '', unknownKey: '' } }, { path: { transactionType: '', unknownKey: '' } }, @@ -62,9 +54,7 @@ describe('strictKeysRt', () => { if (!isRight(result)) { throw new Error( - `Expected ${JSON.stringify( - value - )} to be allowed, but validation failed with ${ + `Expected ${JSON.stringify(value)} to be allowed, but validation failed with ${ result.left[0].message }` ); @@ -76,9 +66,7 @@ describe('strictKeysRt', () => { if (!isLeft(result)) { throw new Error( - `Expected ${JSON.stringify( - value - )} to be disallowed, but validation succeeded` + `Expected ${JSON.stringify(value)} to be disallowed, but validation succeeded` ); } }); diff --git a/x-pack/plugins/apm/common/runtime_types/strict_keys_rt/index.ts b/packages/kbn-io-ts-utils/src/strict_keys_rt/index.ts similarity index 66% rename from x-pack/plugins/apm/common/runtime_types/strict_keys_rt/index.ts rename to packages/kbn-io-ts-utils/src/strict_keys_rt/index.ts index e90ccf7eb8d3..56afdf54463f 100644 --- a/x-pack/plugins/apm/common/runtime_types/strict_keys_rt/index.ts +++ b/packages/kbn-io-ts-utils/src/strict_keys_rt/index.ts @@ -1,14 +1,15 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import * as t from 'io-ts'; import { either, isRight } from 'fp-ts/lib/Either'; import { mapValues, difference, isPlainObject, forEach } from 'lodash'; -import { MergeType, merge } from '../merge'; +import { MergeType, mergeRt } from '../merge_rt'; /* Type that tracks validated keys, and fails when the input value @@ -21,7 +22,7 @@ type ParsableType = | t.PartialType | t.ExactType | t.InterfaceType - | MergeType; + | MergeType; function getKeysInObject>( object: T, @@ -32,17 +33,16 @@ function getKeysInObject>( const ownPrefix = prefix ? `${prefix}.${key}` : key; keys.push(ownPrefix); if (isPlainObject(object[key])) { - keys.push( - ...getKeysInObject(object[key] as Record, ownPrefix) - ); + keys.push(...getKeysInObject(object[key] as Record, ownPrefix)); } }); return keys; } -function addToContextWhenValidated< - T extends t.InterfaceType | t.PartialType ->(type: T, prefix: string): T { +function addToContextWhenValidated | t.PartialType>( + type: T, + prefix: string +): T { const validate = (input: unknown, context: t.Context) => { const result = type.validate(input, context); const keysType = context[0].type as StrictKeysType; @@ -50,36 +50,19 @@ function addToContextWhenValidated< throw new Error('Expected a top-level StrictKeysType'); } if (isRight(result)) { - keysType.trackedKeys.push( - ...Object.keys(type.props).map((propKey) => `${prefix}${propKey}`) - ); + keysType.trackedKeys.push(...Object.keys(type.props).map((propKey) => `${prefix}${propKey}`)); } return result; }; if (type._tag === 'InterfaceType') { - return new t.InterfaceType( - type.name, - type.is, - validate, - type.encode, - type.props - ) as T; + return new t.InterfaceType(type.name, type.is, validate, type.encode, type.props) as T; } - return new t.PartialType( - type.name, - type.is, - validate, - type.encode, - type.props - ) as T; + return new t.PartialType(type.name, type.is, validate, type.encode, type.props) as T; } -function trackKeysOfValidatedTypes( - type: ParsableType | t.Any, - prefix: string = '' -): t.Any { +function trackKeysOfValidatedTypes(type: ParsableType | t.Any, prefix: string = ''): t.Any { if (!('_tag' in type)) { return type; } @@ -89,27 +72,24 @@ function trackKeysOfValidatedTypes( case 'IntersectionType': { const collectionType = type as t.IntersectionType; return t.intersection( - collectionType.types.map((rt) => - trackKeysOfValidatedTypes(rt, prefix) - ) as [t.Any, t.Any] + collectionType.types.map((rt) => trackKeysOfValidatedTypes(rt, prefix)) as [t.Any, t.Any] ); } case 'UnionType': { const collectionType = type as t.UnionType; return t.union( - collectionType.types.map((rt) => - trackKeysOfValidatedTypes(rt, prefix) - ) as [t.Any, t.Any] + collectionType.types.map((rt) => trackKeysOfValidatedTypes(rt, prefix)) as [t.Any, t.Any] ); } case 'MergeType': { - const collectionType = type as MergeType; - return merge( - collectionType.types.map((rt) => - trackKeysOfValidatedTypes(rt, prefix) - ) as [t.Any, t.Any] + const collectionType = type as MergeType; + return mergeRt( + ...(collectionType.types.map((rt) => trackKeysOfValidatedTypes(rt, prefix)) as [ + t.Any, + t.Any + ]) ); } @@ -142,9 +122,7 @@ function trackKeysOfValidatedTypes( case 'ExactType': { const exactType = type as t.ExactType; - return t.exact( - trackKeysOfValidatedTypes(exactType.type, prefix) as t.HasProps - ); + return t.exact(trackKeysOfValidatedTypes(exactType.type, prefix) as t.HasProps); } default: @@ -169,17 +147,11 @@ class StrictKeysType< (input, context) => { this.trackedKeys.length = 0; return either.chain(trackedType.validate(input, context), (i) => { - const originalKeys = getKeysInObject( - input as Record - ); + const originalKeys = getKeysInObject(input as Record); const excessKeys = difference(originalKeys, this.trackedKeys); if (excessKeys.length) { - return t.failure( - i, - context, - `Excess keys are not allowed: \n${excessKeys.join('\n')}` - ); + return t.failure(i, context, `Excess keys are not allowed: \n${excessKeys.join('\n')}`); } return t.success(i); diff --git a/packages/kbn-io-ts-utils/tsconfig.json b/packages/kbn-io-ts-utils/tsconfig.json new file mode 100644 index 000000000000..6c67518e2107 --- /dev/null +++ b/packages/kbn-io-ts-utils/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "incremental": false, + "outDir": "./target", + "stripInternal": false, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "sourceRoot": "../../../../packages/kbn-io-ts-utils/src", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/packages/kbn-server-route-repository/README.md b/packages/kbn-server-route-repository/README.md new file mode 100644 index 000000000000..e22205540ef3 --- /dev/null +++ b/packages/kbn-server-route-repository/README.md @@ -0,0 +1,7 @@ +# @kbn/server-route-repository + +Utility functions for creating a typed server route repository, and a typed client, generating runtime validation and type validation from the same route definition. + +## Usage + +TBD diff --git a/packages/kbn-server-route-repository/jest.config.js b/packages/kbn-server-route-repository/jest.config.js new file mode 100644 index 000000000000..7449bb7cd386 --- /dev/null +++ b/packages/kbn-server-route-repository/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../..', + roots: ['/packages/kbn-server-route-repository'], +}; diff --git a/packages/kbn-server-route-repository/package.json b/packages/kbn-server-route-repository/package.json new file mode 100644 index 000000000000..ce1ca02d0c4f --- /dev/null +++ b/packages/kbn-server-route-repository/package.json @@ -0,0 +1,16 @@ +{ + "name": "@kbn/server-route-repository", + "main": "./target/index.js", + "types": "./target/index.d.ts", + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0", + "private": true, + "scripts": { + "build": "../../node_modules/.bin/tsc", + "kbn:bootstrap": "yarn build", + "kbn:watch": "yarn build --watch" + }, + "dependencies": { + "@kbn/io-ts-utils": "link:../kbn-io-ts-utils" + } +} diff --git a/packages/kbn-server-route-repository/src/create_server_route_factory.ts b/packages/kbn-server-route-repository/src/create_server_route_factory.ts new file mode 100644 index 000000000000..edf9bd657f99 --- /dev/null +++ b/packages/kbn-server-route-repository/src/create_server_route_factory.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { + ServerRouteCreateOptions, + ServerRouteHandlerResources, + RouteParamsRT, + ServerRoute, +} from './typings'; + +export function createServerRouteFactory< + TRouteHandlerResources extends ServerRouteHandlerResources, + TRouteCreateOptions extends ServerRouteCreateOptions +>(): < + TEndpoint extends string, + TReturnType, + TRouteParamsRT extends RouteParamsRT | undefined = undefined +>( + route: ServerRoute< + TEndpoint, + TRouteParamsRT, + TRouteHandlerResources, + TReturnType, + TRouteCreateOptions + > +) => ServerRoute< + TEndpoint, + TRouteParamsRT, + TRouteHandlerResources, + TReturnType, + TRouteCreateOptions +> { + return (route) => route; +} diff --git a/packages/kbn-server-route-repository/src/create_server_route_repository.ts b/packages/kbn-server-route-repository/src/create_server_route_repository.ts new file mode 100644 index 000000000000..5ac89ebcac77 --- /dev/null +++ b/packages/kbn-server-route-repository/src/create_server_route_repository.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { + ServerRouteHandlerResources, + ServerRouteRepository, + ServerRouteCreateOptions, +} from './typings'; + +export function createServerRouteRepository< + TRouteHandlerResources extends ServerRouteHandlerResources = never, + TRouteCreateOptions extends ServerRouteCreateOptions = never +>(): ServerRouteRepository { + let routes: Record = {}; + + return { + add(route) { + routes = { + ...routes, + [route.endpoint]: route, + }; + + return this as any; + }, + merge(repository) { + routes = { + ...routes, + ...Object.fromEntries(repository.getRoutes().map((route) => [route.endpoint, route])), + }; + + return this as any; + }, + getRoutes: () => Object.values(routes), + }; +} diff --git a/packages/kbn-server-route-repository/src/decode_request_params.test.ts b/packages/kbn-server-route-repository/src/decode_request_params.test.ts new file mode 100644 index 000000000000..08ef303ad0b3 --- /dev/null +++ b/packages/kbn-server-route-repository/src/decode_request_params.test.ts @@ -0,0 +1,122 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { jsonRt } from '@kbn/io-ts-utils'; +import * as t from 'io-ts'; +import { decodeRequestParams } from './decode_request_params'; + +describe('decodeRequestParams', () => { + it('decodes request params', () => { + const decode = () => { + return decodeRequestParams( + { + params: { + serviceName: 'opbeans-java', + }, + body: null, + query: { + start: '', + }, + }, + t.type({ + path: t.type({ + serviceName: t.string, + }), + query: t.type({ + start: t.string, + }), + }) + ); + }; + expect(decode).not.toThrow(); + + expect(decode()).toEqual({ + path: { + serviceName: 'opbeans-java', + }, + query: { + start: '', + }, + }); + }); + + it('fails on excess keys', () => { + const decode = () => { + return decodeRequestParams( + { + params: { + serviceName: 'opbeans-java', + extraKey: '', + }, + body: null, + query: { + start: '', + }, + }, + t.type({ + path: t.type({ + serviceName: t.string, + }), + query: t.type({ + start: t.string, + }), + }) + ); + }; + + expect(decode).toThrowErrorMatchingInlineSnapshot(` + "Excess keys are not allowed: + path.extraKey" + `); + }); + + it('returns the decoded output', () => { + const decode = () => { + return decodeRequestParams( + { + params: {}, + query: { + _inspect: 'true', + }, + body: null, + }, + t.type({ + query: t.type({ + _inspect: jsonRt.pipe(t.boolean), + }), + }) + ); + }; + + expect(decode).not.toThrow(); + + expect(decode()).toEqual({ + query: { + _inspect: true, + }, + }); + }); + + it('strips empty params', () => { + const decode = () => { + return decodeRequestParams( + { + params: {}, + query: {}, + body: {}, + }, + t.type({ + body: t.any, + }) + ); + }; + + expect(decode).not.toThrow(); + + expect(decode()).toEqual({}); + }); +}); diff --git a/packages/kbn-server-route-repository/src/decode_request_params.ts b/packages/kbn-server-route-repository/src/decode_request_params.ts new file mode 100644 index 000000000000..00492d69b8ac --- /dev/null +++ b/packages/kbn-server-route-repository/src/decode_request_params.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import * as t from 'io-ts'; +import { omitBy, isPlainObject, isEmpty } from 'lodash'; +import { isLeft } from 'fp-ts/lib/Either'; +import { PathReporter } from 'io-ts/lib/PathReporter'; +import Boom from '@hapi/boom'; +import { strictKeysRt } from '@kbn/io-ts-utils'; +import { RouteParamsRT } from './typings'; + +interface KibanaRequestParams { + body: unknown; + query: unknown; + params: unknown; +} + +export function decodeRequestParams( + params: KibanaRequestParams, + paramsRt: T +): t.OutputOf { + const paramMap = omitBy( + { + path: params.params, + body: params.body, + query: params.query, + }, + (val) => val === null || val === undefined || (isPlainObject(val) && isEmpty(val)) + ); + + // decode = validate + const result = strictKeysRt(paramsRt).decode(paramMap); + + if (isLeft(result)) { + throw Boom.badRequest(PathReporter.report(result)[0]); + } + + return result.right; +} diff --git a/packages/kbn-server-route-repository/src/format_request.ts b/packages/kbn-server-route-repository/src/format_request.ts new file mode 100644 index 000000000000..49004a78ce0e --- /dev/null +++ b/packages/kbn-server-route-repository/src/format_request.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { parseEndpoint } from './parse_endpoint'; + +export function formatRequest(endpoint: string, pathParams: Record = {}) { + const { method, pathname: rawPathname } = parseEndpoint(endpoint); + + // replace template variables with path params + const pathname = Object.keys(pathParams).reduce((acc, paramName) => { + return acc.replace(`{${paramName}}`, pathParams[paramName]); + }, rawPathname); + + return { method, pathname }; +} diff --git a/packages/kbn-server-route-repository/src/index.ts b/packages/kbn-server-route-repository/src/index.ts new file mode 100644 index 000000000000..23621c5b213b --- /dev/null +++ b/packages/kbn-server-route-repository/src/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { createServerRouteRepository } from './create_server_route_repository'; +export { createServerRouteFactory } from './create_server_route_factory'; +export { formatRequest } from './format_request'; +export { parseEndpoint } from './parse_endpoint'; +export { decodeRequestParams } from './decode_request_params'; +export { routeValidationObject } from './route_validation_object'; +export { + RouteRepositoryClient, + ReturnOf, + EndpointOf, + ClientRequestParamsOf, + DecodedRequestParamsOf, + ServerRouteRepository, + ServerRoute, + RouteParamsRT, +} from './typings'; diff --git a/packages/kbn-server-route-repository/src/parse_endpoint.ts b/packages/kbn-server-route-repository/src/parse_endpoint.ts new file mode 100644 index 000000000000..fd40489b0f4a --- /dev/null +++ b/packages/kbn-server-route-repository/src/parse_endpoint.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +type Method = 'get' | 'post' | 'put' | 'delete'; + +export function parseEndpoint(endpoint: string) { + const parts = endpoint.split(' '); + + const method = parts[0].trim().toLowerCase() as Method; + const pathname = parts[1].trim(); + + if (!['get', 'post', 'put', 'delete'].includes(method)) { + throw new Error('Endpoint was not prefixed with a valid HTTP method'); + } + + return { method, pathname }; +} diff --git a/packages/kbn-server-route-repository/src/route_validation_object.ts b/packages/kbn-server-route-repository/src/route_validation_object.ts new file mode 100644 index 000000000000..550be8d20d44 --- /dev/null +++ b/packages/kbn-server-route-repository/src/route_validation_object.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { schema } from '@kbn/config-schema'; + +const anyObject = schema.object({}, { unknowns: 'allow' }); + +export const routeValidationObject = { + // `body` can be null, but `validate` expects non-nullable types + // if any validation is defined. Not having validation currently + // means we don't get the payload. See + // https://github.com/elastic/kibana/issues/50179 + body: schema.nullable(anyObject), + params: anyObject, + query: anyObject, +}; diff --git a/packages/kbn-server-route-repository/src/test_types.ts b/packages/kbn-server-route-repository/src/test_types.ts new file mode 100644 index 000000000000..c9015e19b82f --- /dev/null +++ b/packages/kbn-server-route-repository/src/test_types.ts @@ -0,0 +1,238 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import * as t from 'io-ts'; +import { createServerRouteRepository } from './create_server_route_repository'; +import { decodeRequestParams } from './decode_request_params'; +import { EndpointOf, ReturnOf, RouteRepositoryClient } from './typings'; + +function assertType(value: TShape) { + return value; +} + +// Generic arguments for createServerRouteRepository should be set, +// if not, registering routes should not be allowed +createServerRouteRepository().add({ + // @ts-expect-error + endpoint: 'any_endpoint', + // @ts-expect-error + handler: async ({ params }) => {}, +}); + +// If a params codec is not set, its type should not be available in +// the request handler. +createServerRouteRepository<{}, {}>().add({ + endpoint: 'endpoint_without_params', + handler: async (resources) => { + // @ts-expect-error Argument of type '{}' is not assignable to parameter of type '{ params: any; }'. + assertType<{ params: any }>(resources); + }, +}); + +// If a params codec is set, its type _should_ be available in the +// request handler. +createServerRouteRepository<{}, {}>().add({ + endpoint: 'endpoint_with_params', + params: t.type({ + path: t.type({ + serviceName: t.string, + }), + }), + handler: async (resources) => { + assertType<{ params: { path: { serviceName: string } } }>(resources); + }, +}); + +// Resources should be passed to the request handler. +createServerRouteRepository<{ context: { getSpaceId: () => string } }, {}>().add({ + endpoint: 'endpoint_with_params', + params: t.type({ + path: t.type({ + serviceName: t.string, + }), + }), + handler: async ({ context }) => { + const spaceId = context.getSpaceId(); + assertType(spaceId); + }, +}); + +// Create options are available when registering a route. +createServerRouteRepository<{}, { options: { tags: string[] } }>().add({ + endpoint: 'endpoint_with_params', + params: t.type({ + path: t.type({ + serviceName: t.string, + }), + }), + options: { + tags: [], + }, + handler: async (resources) => { + assertType<{ params: { path: { serviceName: string } } }>(resources); + }, +}); + +const repository = createServerRouteRepository<{}, {}>() + .add({ + endpoint: 'endpoint_without_params', + handler: async () => { + return { + noParamsForMe: true, + }; + }, + }) + .add({ + endpoint: 'endpoint_with_params', + params: t.type({ + path: t.type({ + serviceName: t.string, + }), + }), + handler: async () => { + return { + yesParamsForMe: true, + }; + }, + }) + .add({ + endpoint: 'endpoint_with_optional_params', + params: t.partial({ + query: t.partial({ + serviceName: t.string, + }), + }), + handler: async () => { + return { + someParamsForMe: true, + }; + }, + }); + +type TestRepository = typeof repository; + +// EndpointOf should return all valid endpoints of a repository + +assertType>>([ + 'endpoint_with_params', + 'endpoint_without_params', + 'endpoint_with_optional_params', +]); + +// @ts-expect-error Type '"this_endpoint_does_not_exist"' is not assignable to type '"endpoint_without_params" | "endpoint_with_params" | "endpoint_with_optional_params"' +assertType>>(['this_endpoint_does_not_exist']); + +// ReturnOf should return the return type of a request handler. + +assertType>({ + noParamsForMe: true, +}); + +const noParamsInvalid: ReturnOf = { + // @ts-expect-error type '{ paramsForMe: boolean; }' is not assignable to type '{ noParamsForMe: boolean; }'. + paramsForMe: true, +}; + +// RouteRepositoryClient + +type TestClient = RouteRepositoryClient; + +const client: TestClient = {} as any; + +// It should respect any additional create options. + +// @ts-expect-error Property 'timeout' is missing +client({ + endpoint: 'endpoint_without_params', +}); + +client({ + endpoint: 'endpoint_without_params', + timeout: 1, +}); + +// It does not allow params for routes without a params codec +client({ + endpoint: 'endpoint_without_params', + // @ts-expect-error Object literal may only specify known properties, and 'params' does not exist in type + params: {}, + timeout: 1, +}); + +// It requires params for routes with a params codec +client({ + endpoint: 'endpoint_with_params', + params: { + // @ts-expect-error property 'serviceName' is missing in type '{}' + path: {}, + }, + timeout: 1, +}); + +// Params are optional if the codec has no required keys +client({ + endpoint: 'endpoint_with_optional_params', + timeout: 1, +}); + +// If optional, an error will still occur if the params do not match +client({ + endpoint: 'endpoint_with_optional_params', + timeout: 1, + params: { + // @ts-expect-error Object literal may only specify known properties, and 'path' does not exist in type + path: '', + }, +}); + +// The return type is correctly inferred +client({ + endpoint: 'endpoint_with_params', + params: { + path: { + serviceName: '', + }, + }, + timeout: 1, +}).then((res) => { + assertType<{ + noParamsForMe: boolean; + // @ts-expect-error Property 'noParamsForMe' is missing in type + }>(res); + + assertType<{ + yesParamsForMe: boolean; + }>(res); +}); + +// decodeRequestParams should return the type of the codec that is passed +assertType<{ path: { serviceName: string } }>( + decodeRequestParams( + { + params: { + serviceName: 'serviceName', + }, + body: undefined, + query: undefined, + }, + t.type({ path: t.type({ serviceName: t.string }) }) + ) +); + +assertType<{ path: { serviceName: boolean } }>( + // @ts-expect-error The types of 'path.serviceName' are incompatible between these types. + decodeRequestParams( + { + params: { + serviceName: 'serviceName', + }, + body: undefined, + query: undefined, + }, + t.type({ path: t.type({ serviceName: t.string }) }) + ) +); diff --git a/packages/kbn-server-route-repository/src/typings.ts b/packages/kbn-server-route-repository/src/typings.ts new file mode 100644 index 000000000000..c27f67c71e88 --- /dev/null +++ b/packages/kbn-server-route-repository/src/typings.ts @@ -0,0 +1,192 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as t from 'io-ts'; +import { RequiredKeys } from 'utility-types'; + +type MaybeOptional }> = RequiredKeys< + T['params'] +> extends never + ? { params?: T['params'] } + : { params: T['params'] }; + +type WithoutIncompatibleMethods = Omit & { + encode: t.Encode; + asEncoder: () => t.Encoder; +}; + +export type RouteParamsRT = WithoutIncompatibleMethods< + t.Type<{ + path?: any; + query?: any; + body?: any; + }> +>; + +export interface RouteState { + [endpoint: string]: ServerRoute; +} + +export type ServerRouteHandlerResources = Record; +export type ServerRouteCreateOptions = Record; + +export type ServerRoute< + TEndpoint extends string, + TRouteParamsRT extends RouteParamsRT | undefined, + TRouteHandlerResources extends ServerRouteHandlerResources, + TReturnType, + TRouteCreateOptions extends ServerRouteCreateOptions +> = { + endpoint: TEndpoint; + params?: TRouteParamsRT; + handler: ({}: TRouteHandlerResources & + (TRouteParamsRT extends RouteParamsRT + ? DecodedRequestParamsOfType + : {})) => Promise; +} & TRouteCreateOptions; + +export interface ServerRouteRepository< + TRouteHandlerResources extends ServerRouteHandlerResources = ServerRouteHandlerResources, + TRouteCreateOptions extends ServerRouteCreateOptions = ServerRouteCreateOptions, + TRouteState extends RouteState = RouteState +> { + add< + TEndpoint extends string, + TReturnType, + TRouteParamsRT extends RouteParamsRT | undefined = undefined + >( + route: ServerRoute< + TEndpoint, + TRouteParamsRT, + TRouteHandlerResources, + TReturnType, + TRouteCreateOptions + > + ): ServerRouteRepository< + TRouteHandlerResources, + TRouteCreateOptions, + TRouteState & + { + [key in TEndpoint]: ServerRoute< + TEndpoint, + TRouteParamsRT, + TRouteHandlerResources, + TReturnType, + TRouteCreateOptions + >; + } + >; + merge< + TServerRouteRepository extends ServerRouteRepository< + TRouteHandlerResources, + TRouteCreateOptions + > + >( + repository: TServerRouteRepository + ): TServerRouteRepository extends ServerRouteRepository< + TRouteHandlerResources, + TRouteCreateOptions, + infer TRouteStateToMerge + > + ? ServerRouteRepository< + TRouteHandlerResources, + TRouteCreateOptions, + TRouteState & TRouteStateToMerge + > + : never; + getRoutes: () => Array< + ServerRoute + >; +} + +type ClientRequestParamsOfType< + TRouteParamsRT extends RouteParamsRT +> = TRouteParamsRT extends t.Mixed + ? MaybeOptional<{ + params: t.OutputOf; + }> + : {}; + +type DecodedRequestParamsOfType< + TRouteParamsRT extends RouteParamsRT +> = TRouteParamsRT extends t.Mixed + ? MaybeOptional<{ + params: t.TypeOf; + }> + : {}; + +export type EndpointOf< + TServerRouteRepository extends ServerRouteRepository +> = TServerRouteRepository extends ServerRouteRepository + ? keyof TRouteState + : never; + +export type ReturnOf< + TServerRouteRepository extends ServerRouteRepository, + TEndpoint extends EndpointOf +> = TServerRouteRepository extends ServerRouteRepository + ? TEndpoint extends keyof TRouteState + ? TRouteState[TEndpoint] extends ServerRoute< + any, + any, + any, + infer TReturnType, + ServerRouteCreateOptions + > + ? TReturnType + : never + : never + : never; + +export type DecodedRequestParamsOf< + TServerRouteRepository extends ServerRouteRepository, + TEndpoint extends EndpointOf +> = TServerRouteRepository extends ServerRouteRepository + ? TEndpoint extends keyof TRouteState + ? TRouteState[TEndpoint] extends ServerRoute< + any, + infer TRouteParamsRT, + any, + any, + ServerRouteCreateOptions + > + ? TRouteParamsRT extends RouteParamsRT + ? DecodedRequestParamsOfType + : {} + : never + : never + : never; + +export type ClientRequestParamsOf< + TServerRouteRepository extends ServerRouteRepository, + TEndpoint extends EndpointOf +> = TServerRouteRepository extends ServerRouteRepository + ? TEndpoint extends keyof TRouteState + ? TRouteState[TEndpoint] extends ServerRoute< + any, + infer TRouteParamsRT, + any, + any, + ServerRouteCreateOptions + > + ? TRouteParamsRT extends RouteParamsRT + ? ClientRequestParamsOfType + : {} + : never + : never + : never; + +export type RouteRepositoryClient< + TServerRouteRepository extends ServerRouteRepository, + TAdditionalClientOptions extends Record +> = >( + options: { + endpoint: TEndpoint; + } & ClientRequestParamsOf & + TAdditionalClientOptions +) => Promise>; diff --git a/packages/kbn-server-route-repository/tsconfig.json b/packages/kbn-server-route-repository/tsconfig.json new file mode 100644 index 000000000000..8f1e72172c67 --- /dev/null +++ b/packages/kbn-server-route-repository/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "incremental": false, + "outDir": "./target", + "stripInternal": false, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "sourceRoot": "../../../../packages/kbn-server-route-repository/src", + "types": [ + "jest", + "node" + ], + "noUnusedLocals": false + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/x-pack/plugins/apm/common/latency_aggregation_types.ts b/x-pack/plugins/apm/common/latency_aggregation_types.ts index d9db58f22314..964d6f4ed101 100644 --- a/x-pack/plugins/apm/common/latency_aggregation_types.ts +++ b/x-pack/plugins/apm/common/latency_aggregation_types.ts @@ -14,7 +14,7 @@ export enum LatencyAggregationType { } export const latencyAggregationTypeRt = t.union([ - t.literal('avg'), - t.literal('p95'), - t.literal('p99'), + t.literal(LatencyAggregationType.avg), + t.literal(LatencyAggregationType.p95), + t.literal(LatencyAggregationType.p99), ]); diff --git a/x-pack/plugins/apm/common/runtime_types/iso_to_epoch_rt/index.ts b/x-pack/plugins/apm/common/runtime_types/iso_to_epoch_rt/index.ts index 1a17f82a5214..970e39bc4f86 100644 --- a/x-pack/plugins/apm/common/runtime_types/iso_to_epoch_rt/index.ts +++ b/x-pack/plugins/apm/common/runtime_types/iso_to_epoch_rt/index.ts @@ -21,8 +21,5 @@ export const isoToEpochRt = new t.Type( ? t.failure(input, context) : t.success(epochDate); }), - (a) => { - const d = new Date(a); - return d.toISOString(); - } + (output) => new Date(output).toISOString() ); diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.test.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.test.tsx index 6a6db40892e1..407f460f25ad 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.test.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateEditCustomLinkFlyout/link_preview.test.tsx @@ -14,15 +14,18 @@ import { act, waitFor, } from '@testing-library/react'; -import * as apmApi from '../../../../../../services/rest/createCallApmApi'; +import { + getCallApmApiSpy, + CallApmApiSpy, +} from '../../../../../../services/rest/callApmApiSpy'; export const removeExternalLinkText = (str: string) => str.replace(/\(opens in a new tab or window\)/g, ''); describe('LinkPreview', () => { - let callApmApiSpy: jest.SpyInstance; + let callApmApiSpy: CallApmApiSpy; beforeAll(() => { - callApmApiSpy = jest.spyOn(apmApi, 'callApmApi').mockResolvedValue({ + callApmApiSpy = getCallApmApiSpy().mockResolvedValue({ transaction: { id: 'foo' }, }); }); diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx index 77835afef863..7d119b8c406d 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/index.test.tsx @@ -8,6 +8,7 @@ import { fireEvent, render, RenderResult } from '@testing-library/react'; import React from 'react'; import { act } from 'react-dom/test-utils'; +import { getCallApmApiSpy } from '../../../../../services/rest/callApmApiSpy'; import { CustomLinkOverview } from '.'; import { License } from '../../../../../../../licensing/common/license'; import { ApmPluginContextValue } from '../../../../../context/apm_plugin/apm_plugin_context'; @@ -17,7 +18,6 @@ import { } from '../../../../../context/apm_plugin/mock_apm_plugin_context'; import { LicenseContext } from '../../../../../context/license/license_context'; import * as hooks from '../../../../../hooks/use_fetcher'; -import * as apmApi from '../../../../../services/rest/createCallApmApi'; import { expectTextsInDocument, expectTextsNotInDocument, @@ -43,7 +43,7 @@ function getMockAPMContext({ canSave }: { canSave: boolean }) { describe('CustomLink', () => { beforeAll(() => { - jest.spyOn(apmApi, 'callApmApi').mockResolvedValue({}); + getCallApmApiSpy().mockResolvedValue({}); }); afterAll(() => { jest.resetAllMocks(); diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview.test.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview.test.tsx index b30faac7a65a..c6ed4e640693 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview.test.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview.test.tsx @@ -22,9 +22,12 @@ import * as useTransactionBreakdownHooks from '../../shared/charts/transaction_b import { renderWithTheme } from '../../../utils/testHelpers'; import { ServiceOverview } from './'; import { waitFor } from '@testing-library/dom'; -import * as callApmApiModule from '../../../services/rest/createCallApmApi'; import * as useApmServiceContextHooks from '../../../context/apm_service/use_apm_service_context'; import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; +import { + getCallApmApiSpy, + getCreateCallApmApiSpy, +} from '../../../services/rest/callApmApiSpy'; const KibanaReactContext = createKibanaReactContext({ usageCollection: { reportUiCounter: () => {} }, @@ -83,10 +86,10 @@ describe('ServiceOverview', () => { /* eslint-disable @typescript-eslint/naming-convention */ const calls = { 'GET /api/apm/services/{serviceName}/error_groups/primary_statistics': { - error_groups: [], + error_groups: [] as any[], }, 'GET /api/apm/services/{serviceName}/transactions/groups/primary_statistics': { - transactionGroups: [], + transactionGroups: [] as any[], totalTransactionGroups: 0, isAggregationAccurate: true, }, @@ -95,19 +98,17 @@ describe('ServiceOverview', () => { }; /* eslint-enable @typescript-eslint/naming-convention */ - jest - .spyOn(callApmApiModule, 'createCallApmApi') - .mockImplementation(() => {}); - - const callApmApi = jest - .spyOn(callApmApiModule, 'callApmApi') - .mockImplementation(({ endpoint }) => { + const callApmApiSpy = getCallApmApiSpy().mockImplementation( + ({ endpoint }) => { const response = calls[endpoint as keyof typeof calls]; return response ? Promise.resolve(response) : Promise.reject(`Response for ${endpoint} is not defined`); - }); + } + ); + + getCreateCallApmApiSpy().mockImplementation(() => callApmApiSpy as any); jest .spyOn(useTransactionBreakdownHooks, 'useTransactionBreakdown') .mockReturnValue({ @@ -124,7 +125,7 @@ describe('ServiceOverview', () => { ); await waitFor(() => - expect(callApmApi).toHaveBeenCalledTimes(Object.keys(calls).length) + expect(callApmApiSpy).toHaveBeenCalledTimes(Object.keys(calls).length) ); expect((await findAllByText('Latency')).length).toBeGreaterThan(0); diff --git a/x-pack/plugins/apm/public/services/rest/apm_observability_overview_fetchers.test.ts b/x-pack/plugins/apm/public/services/rest/apm_observability_overview_fetchers.test.ts index 29fabc51fd58..00447607cf78 100644 --- a/x-pack/plugins/apm/public/services/rest/apm_observability_overview_fetchers.test.ts +++ b/x-pack/plugins/apm/public/services/rest/apm_observability_overview_fetchers.test.ts @@ -10,10 +10,10 @@ import { fetchObservabilityOverviewPageData, getHasData, } from './apm_observability_overview_fetchers'; -import * as createCallApmApi from './createCallApmApi'; +import { getCallApmApiSpy } from './callApmApiSpy'; describe('Observability dashboard data', () => { - const callApmApiMock = jest.spyOn(createCallApmApi, 'callApmApi'); + const callApmApiMock = getCallApmApiSpy(); const params = { absoluteTime: { start: moment('2020-07-02T13:25:11.629Z').valueOf(), @@ -84,7 +84,7 @@ describe('Observability dashboard data', () => { callApmApiMock.mockImplementation(() => Promise.resolve({ serviceCount: 0, - transactionPerMinute: { value: null, timeseries: [] }, + transactionPerMinute: { value: null, timeseries: [] as any }, }) ); const response = await fetchObservabilityOverviewPageData(params); diff --git a/x-pack/plugins/apm/public/services/rest/callApmApiSpy.ts b/x-pack/plugins/apm/public/services/rest/callApmApiSpy.ts new file mode 100644 index 000000000000..ba9f740e06d0 --- /dev/null +++ b/x-pack/plugins/apm/public/services/rest/callApmApiSpy.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as createCallApmApi from './createCallApmApi'; +import type { AbstractAPMClient } from './createCallApmApi'; + +export type CallApmApiSpy = jest.SpyInstance< + Promise, + Parameters +>; + +export type CreateCallApmApiSpy = jest.SpyInstance; + +export const getCreateCallApmApiSpy = () => + (jest.spyOn( + createCallApmApi, + 'createCallApmApi' + ) as unknown) as CreateCallApmApiSpy; +export const getCallApmApiSpy = () => + (jest.spyOn(createCallApmApi, 'callApmApi') as unknown) as CallApmApiSpy; diff --git a/x-pack/plugins/apm/public/services/rest/createCallApmApi.ts b/x-pack/plugins/apm/public/services/rest/createCallApmApi.ts index b0cce3296fe2..0e82d70faf1e 100644 --- a/x-pack/plugins/apm/public/services/rest/createCallApmApi.ts +++ b/x-pack/plugins/apm/public/services/rest/createCallApmApi.ts @@ -6,30 +6,68 @@ */ import { CoreSetup, CoreStart } from 'kibana/public'; -import { parseEndpoint } from '../../../common/apm_api/parse_endpoint'; +import * as t from 'io-ts'; +import type { + ClientRequestParamsOf, + EndpointOf, + ReturnOf, + RouteRepositoryClient, + ServerRouteRepository, + ServerRoute, +} from '@kbn/server-route-repository'; +import { formatRequest } from '@kbn/server-route-repository/target/format_request'; import { FetchOptions } from '../../../common/fetch_options'; import { callApi } from './callApi'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { APMAPI } from '../../../server/routes/create_apm_api'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import type { Client } from '../../../server/routes/typings'; - -export type APMClient = Client; -export type AutoAbortedAPMClient = Client; +import type { + APMServerRouteRepository, + InspectResponse, + APMRouteHandlerResources, + // eslint-disable-next-line @kbn/eslint/no-restricted-paths +} from '../../../server'; export type APMClientOptions = Omit< FetchOptions, 'query' | 'body' | 'pathname' | 'signal' > & { - endpoint: string; signal: AbortSignal | null; - params?: { - body?: any; - query?: Record; - path?: Record; - }; }; +export type APMClient = RouteRepositoryClient< + APMServerRouteRepository, + APMClientOptions +>; + +export type AutoAbortedAPMClient = RouteRepositoryClient< + APMServerRouteRepository, + Omit +>; + +export type APIReturnType< + TEndpoint extends EndpointOf +> = ReturnOf & { + _inspect?: InspectResponse; +}; + +export type APIEndpoint = EndpointOf; + +export type APIClientRequestParamsOf< + TEndpoint extends EndpointOf +> = ClientRequestParamsOf; + +export type AbstractAPMRepository = ServerRouteRepository< + APMRouteHandlerResources, + {}, + Record< + string, + ServerRoute + > +>; + +export type AbstractAPMClient = RouteRepositoryClient< + AbstractAPMRepository, + APMClientOptions +>; + export let callApmApi: APMClient = () => { throw new Error( 'callApmApi has to be initialized before used. Call createCallApmApi first.' @@ -37,9 +75,13 @@ export let callApmApi: APMClient = () => { }; export function createCallApmApi(core: CoreStart | CoreSetup) { - callApmApi = ((options: APMClientOptions) => { - const { endpoint, params, ...opts } = options; - const { method, pathname } = parseEndpoint(endpoint, params?.path); + callApmApi = ((options) => { + const { endpoint, ...opts } = options; + const { params } = (options as unknown) as { + params?: Partial>; + }; + + const { method, pathname } = formatRequest(endpoint, params?.path); return callApi(core, { ...opts, @@ -50,10 +92,3 @@ export function createCallApmApi(core: CoreStart | CoreSetup) { }); }) as APMClient; } - -// infer return type from API -export type APIReturnType< - TPath extends keyof APMAPI['_S'] -> = APMAPI['_S'][TPath] extends { ret: any } - ? APMAPI['_S'][TPath]['ret'] - : unknown; diff --git a/x-pack/plugins/apm/server/index.ts b/x-pack/plugins/apm/server/index.ts index 00910353ac27..9ab56c1a303e 100644 --- a/x-pack/plugins/apm/server/index.ts +++ b/x-pack/plugins/apm/server/index.ts @@ -120,5 +120,9 @@ export function mergeConfigs( export const plugin = (initContext: PluginInitializerContext) => new APMPlugin(initContext); -export { APMPlugin, APMPluginSetup } from './plugin'; +export { APMPlugin } from './plugin'; +export { APMPluginSetup } from './types'; +export { APMServerRouteRepository } from './routes/get_global_apm_server_route_repository'; +export { InspectResponse, APMRouteHandlerResources } from './routes/typings'; + export type { ProcessorEvent } from '../common/processor_event'; diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/call_async_with_debug.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/call_async_with_debug.ts index 1f0aa401bcab..989297544c78 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/call_async_with_debug.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/call_async_with_debug.ts @@ -10,7 +10,7 @@ import { omit } from 'lodash'; import chalk from 'chalk'; import { KibanaRequest } from '../../../../../../../src/core/server'; -import { inspectableEsQueriesMap } from '../../../routes/create_api'; +import { inspectableEsQueriesMap } from '../../../routes/register_routes'; function formatObj(obj: Record) { return JSON.stringify(obj, null, 2); diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts index 45e17c167851..9d7434d127ea 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { KibanaRequest } from 'src/core/server'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; import { CreateIndexRequest, @@ -13,7 +12,7 @@ import { IndexRequest, } from '@elastic/elasticsearch/api/types'; import { unwrapEsResponse } from '../../../../../../observability/server'; -import { APMRequestHandlerContext } from '../../../../routes/typings'; +import { APMRouteHandlerResources } from '../../../../routes/typings'; import { ESSearchResponse, ESSearchRequest, @@ -31,11 +30,9 @@ export type APMInternalClient = ReturnType; export function createInternalESClient({ context, + debug, request, -}: { - context: APMRequestHandlerContext; - request: KibanaRequest; -}) { +}: Pick & { debug: boolean }) { const { asInternalUser } = context.core.elasticsearch.client; function callEs({ @@ -53,7 +50,7 @@ export function createInternalESClient({ title: getDebugTitle(request), body: getDebugBody(params, requestType), }), - debug: context.params.query._inspect, + debug, isCalledWithInternalUser: true, request, requestType, diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts index c0707d028618..c0ff0cab88f4 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts @@ -7,8 +7,7 @@ import { setupRequest } from './setup_request'; import { APMConfig } from '../..'; -import { APMRequestHandlerContext } from '../../routes/typings'; -import { KibanaRequest } from '../../../../../../src/core/server'; +import { APMRouteHandlerResources } from '../../routes/typings'; import { ProcessorEvent } from '../../../common/processor_event'; import { PROCESSOR_EVENT } from '../../../common/elasticsearch_fieldnames'; @@ -32,7 +31,7 @@ jest.mock('../index_pattern/get_dynamic_index_pattern', () => ({ }, })); -function getMockRequest() { +function getMockResources() { const esClientMock = { asCurrentUser: { search: jest.fn().mockResolvedValue({ body: {} }), @@ -42,7 +41,7 @@ function getMockRequest() { }, }; - const mockContext = ({ + const mockResources = ({ config: new Proxy( {}, { @@ -54,65 +53,69 @@ function getMockRequest() { _inspect: false, }, }, - core: { - elasticsearch: { - client: esClientMock, - }, - uiSettings: { - client: { - get: jest.fn().mockResolvedValue(false), + context: { + core: { + elasticsearch: { + client: esClientMock, }, - }, - savedObjects: { - client: { - get: jest.fn(), + uiSettings: { + client: { + get: jest.fn().mockResolvedValue(false), + }, + }, + savedObjects: { + client: { + get: jest.fn(), + }, }, }, }, plugins: { ml: undefined, }, - } as unknown) as APMRequestHandlerContext & { - core: { - elasticsearch: { - client: typeof esClientMock; - }; - uiSettings: { - client: { - get: jest.Mock; + request: { + url: '', + events: { + aborted$: { + subscribe: jest.fn().mockReturnValue({ unsubscribe: jest.fn() }), + }, + }, + }, + } as unknown) as APMRouteHandlerResources & { + context: { + core: { + elasticsearch: { + client: typeof esClientMock; }; - }; - savedObjects: { - client: { - get: jest.Mock; + uiSettings: { + client: { + get: jest.Mock; + }; + }; + savedObjects: { + client: { + get: jest.Mock; + }; }; }; }; }; - const mockRequest = ({ - url: '', - events: { - aborted$: { - subscribe: jest.fn().mockReturnValue({ unsubscribe: jest.fn() }), - }, - }, - } as unknown) as KibanaRequest; - - return { mockContext, mockRequest }; + return mockResources; } describe('setupRequest', () => { describe('with default args', () => { it('calls callWithRequest', async () => { - const { mockContext, mockRequest } = getMockRequest(); - const { apmEventClient } = await setupRequest(mockContext, mockRequest); + const mockResources = getMockResources(); + const { apmEventClient } = await setupRequest(mockResources); await apmEventClient.search({ apm: { events: [ProcessorEvent.transaction] }, body: { foo: 'bar' }, }); + expect( - mockContext.core.elasticsearch.client.asCurrentUser.search + mockResources.context.core.elasticsearch.client.asCurrentUser.search ).toHaveBeenCalledWith({ index: ['apm-*'], body: { @@ -132,14 +135,14 @@ describe('setupRequest', () => { }); it('calls callWithInternalUser', async () => { - const { mockContext, mockRequest } = getMockRequest(); - const { internalClient } = await setupRequest(mockContext, mockRequest); + const mockResources = getMockResources(); + const { internalClient } = await setupRequest(mockResources); await internalClient.search({ index: ['apm-*'], body: { foo: 'bar' }, } as any); expect( - mockContext.core.elasticsearch.client.asInternalUser.search + mockResources.context.core.elasticsearch.client.asInternalUser.search ).toHaveBeenCalledWith({ index: ['apm-*'], body: { @@ -151,8 +154,8 @@ describe('setupRequest', () => { describe('with a bool filter', () => { it('adds a range filter for `observer.version_major` to the existing filter', async () => { - const { mockContext, mockRequest } = getMockRequest(); - const { apmEventClient } = await setupRequest(mockContext, mockRequest); + const mockResources = getMockResources(); + const { apmEventClient } = await setupRequest(mockResources); await apmEventClient.search({ apm: { events: [ProcessorEvent.transaction], @@ -162,8 +165,8 @@ describe('setupRequest', () => { }, }); const params = - mockContext.core.elasticsearch.client.asCurrentUser.search.mock - .calls[0][0]; + mockResources.context.core.elasticsearch.client.asCurrentUser.search + .mock.calls[0][0]; expect(params.body).toEqual({ query: { bool: { @@ -178,8 +181,8 @@ describe('setupRequest', () => { }); it('does not add a range filter for `observer.version_major` if includeLegacyData=true', async () => { - const { mockContext, mockRequest } = getMockRequest(); - const { apmEventClient } = await setupRequest(mockContext, mockRequest); + const mockResources = getMockResources(); + const { apmEventClient } = await setupRequest(mockResources); await apmEventClient.search( { apm: { @@ -194,8 +197,8 @@ describe('setupRequest', () => { } ); const params = - mockContext.core.elasticsearch.client.asCurrentUser.search.mock - .calls[0][0]; + mockResources.context.core.elasticsearch.client.asCurrentUser.search + .mock.calls[0][0]; expect(params.body).toEqual({ query: { bool: { @@ -216,15 +219,15 @@ describe('setupRequest', () => { describe('without a bool filter', () => { it('adds a range filter for `observer.version_major`', async () => { - const { mockContext, mockRequest } = getMockRequest(); - const { apmEventClient } = await setupRequest(mockContext, mockRequest); + const mockResources = getMockResources(); + const { apmEventClient } = await setupRequest(mockResources); await apmEventClient.search({ apm: { events: [ProcessorEvent.error], }, }); const params = - mockContext.core.elasticsearch.client.asCurrentUser.search.mock + mockResources.context.core.elasticsearch.client.asCurrentUser.search.mock .calls[0][0]; expect(params.body).toEqual({ query: { @@ -241,12 +244,12 @@ describe('without a bool filter', () => { describe('with includeFrozen=false', () => { it('sets `ignore_throttled=true`', async () => { - const { mockContext, mockRequest } = getMockRequest(); + const mockResources = getMockResources(); // mock includeFrozen to return false - mockContext.core.uiSettings.client.get.mockResolvedValue(false); + mockResources.context.core.uiSettings.client.get.mockResolvedValue(false); - const { apmEventClient } = await setupRequest(mockContext, mockRequest); + const { apmEventClient } = await setupRequest(mockResources); await apmEventClient.search({ apm: { @@ -255,7 +258,7 @@ describe('with includeFrozen=false', () => { }); const params = - mockContext.core.elasticsearch.client.asCurrentUser.search.mock + mockResources.context.core.elasticsearch.client.asCurrentUser.search.mock .calls[0][0]; expect(params.ignore_throttled).toBe(true); }); @@ -263,19 +266,19 @@ describe('with includeFrozen=false', () => { describe('with includeFrozen=true', () => { it('sets `ignore_throttled=false`', async () => { - const { mockContext, mockRequest } = getMockRequest(); + const mockResources = getMockResources(); // mock includeFrozen to return true - mockContext.core.uiSettings.client.get.mockResolvedValue(true); + mockResources.context.core.uiSettings.client.get.mockResolvedValue(true); - const { apmEventClient } = await setupRequest(mockContext, mockRequest); + const { apmEventClient } = await setupRequest(mockResources); await apmEventClient.search({ apm: { events: [] }, }); const params = - mockContext.core.elasticsearch.client.asCurrentUser.search.mock + mockResources.context.core.elasticsearch.client.asCurrentUser.search.mock .calls[0][0]; expect(params.ignore_throttled).toBe(false); }); diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts index fff661250c6d..40836cb6635e 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts @@ -11,7 +11,7 @@ import { APMConfig } from '../..'; import { KibanaRequest } from '../../../../../../src/core/server'; import { UI_SETTINGS } from '../../../../../../src/plugins/data/common'; import { UIFilters } from '../../../typings/ui_filters'; -import { APMRequestHandlerContext } from '../../routes/typings'; +import { APMRouteHandlerResources } from '../../routes/typings'; import { ApmIndicesConfig, getApmIndices, @@ -44,7 +44,7 @@ export interface SetupTimeRange { } interface SetupRequestParams { - query?: { + query: { _inspect?: boolean; /** @@ -64,13 +64,19 @@ type InferSetup = Setup & (TParams extends { query: { start: number } } ? { start: number } : {}) & (TParams extends { query: { end: number } } ? { end: number } : {}); -export async function setupRequest( - context: APMRequestHandlerContext, - request: KibanaRequest -): Promise> { +export async function setupRequest({ + context, + params, + core, + plugins, + request, + config, + logger, +}: APMRouteHandlerResources & { + params: TParams; +}): Promise> { return withApmSpan('setup_request', async () => { - const { config, logger } = context; - const { query } = context.params; + const { query } = params; const [indices, includeFrozen] = await Promise.all([ getApmIndices({ @@ -88,7 +94,7 @@ export async function setupRequest( indices, apmEventClient: createApmEventClient({ esClient: context.core.elasticsearch.client.asCurrentUser, - debug: context.params.query._inspect, + debug: query._inspect, request, indices, options: { includeFrozen }, @@ -96,11 +102,12 @@ export async function setupRequest( internalClient: createInternalESClient({ context, request, + debug: query._inspect, }), ml: - context.plugins.ml && isActivePlatinumLicense(context.licensing.license) + plugins.ml && isActivePlatinumLicense(context.licensing.license) ? getMlSetup( - context.plugins.ml, + plugins.ml.setup, context.core.savedObjects.client, request ) @@ -118,8 +125,8 @@ export async function setupRequest( } function getMlSetup( - ml: Required['ml'], - savedObjectsClient: APMRequestHandlerContext['core']['savedObjects']['client'], + ml: Required['ml']['setup'], + savedObjectsClient: APMRouteHandlerResources['context']['core']['savedObjects']['client'], request: KibanaRequest ) { return { diff --git a/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.test.ts b/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.test.ts index 19163da449b9..a5340c1220b4 100644 --- a/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.test.ts +++ b/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.test.ts @@ -8,21 +8,9 @@ import { createStaticIndexPattern } from './create_static_index_pattern'; import { Setup } from '../helpers/setup_request'; import * as HistoricalAgentData from '../services/get_services/has_historical_agent_data'; -import { APMRequestHandlerContext } from '../../routes/typings'; import { InternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client'; +import { APMConfig } from '../..'; -function getMockContext(config: Record) { - return ({ - config, - core: { - savedObjects: { - client: { - create: jest.fn(), - }, - }, - }, - } as unknown) as APMRequestHandlerContext; -} function getMockSavedObjectsClient() { return ({ create: jest.fn(), @@ -32,13 +20,13 @@ function getMockSavedObjectsClient() { describe('createStaticIndexPattern', () => { it(`should not create index pattern if 'xpack.apm.autocreateApmIndexPattern=false'`, async () => { const setup = {} as Setup; - const context = getMockContext({ - 'xpack.apm.autocreateApmIndexPattern': false, - }); + const savedObjectsClient = getMockSavedObjectsClient(); await createStaticIndexPattern( setup, - context, + { + 'xpack.apm.autocreateApmIndexPattern': false, + } as APMConfig, savedObjectsClient, 'default' ); @@ -47,9 +35,6 @@ describe('createStaticIndexPattern', () => { it(`should not create index pattern if no APM data is found`, async () => { const setup = {} as Setup; - const context = getMockContext({ - 'xpack.apm.autocreateApmIndexPattern': true, - }); // does not have APM data jest @@ -60,7 +45,9 @@ describe('createStaticIndexPattern', () => { await createStaticIndexPattern( setup, - context, + { + 'xpack.apm.autocreateApmIndexPattern': true, + } as APMConfig, savedObjectsClient, 'default' ); @@ -69,9 +56,6 @@ describe('createStaticIndexPattern', () => { it(`should create index pattern`, async () => { const setup = {} as Setup; - const context = getMockContext({ - 'xpack.apm.autocreateApmIndexPattern': true, - }); // does have APM data jest @@ -82,7 +66,9 @@ describe('createStaticIndexPattern', () => { await createStaticIndexPattern( setup, - context, + { + 'xpack.apm.autocreateApmIndexPattern': true, + } as APMConfig, savedObjectsClient, 'default' ); diff --git a/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.ts b/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.ts index b91fb8342a21..e627e9ed1d6c 100644 --- a/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.ts +++ b/x-pack/plugins/apm/server/lib/index_pattern/create_static_index_pattern.ts @@ -12,20 +12,18 @@ import { } from '../../../../../../src/plugins/apm_oss/server'; import { hasHistoricalAgentData } from '../services/get_services/has_historical_agent_data'; import { Setup } from '../helpers/setup_request'; -import { APMRequestHandlerContext } from '../../routes/typings'; +import { APMRouteHandlerResources } from '../../routes/typings'; import { InternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client.js'; import { withApmSpan } from '../../utils/with_apm_span'; import { getApmIndexPatternTitle } from './get_apm_index_pattern_title'; export async function createStaticIndexPattern( setup: Setup, - context: APMRequestHandlerContext, + config: APMRouteHandlerResources['config'], savedObjectsClient: InternalSavedObjectsClient, spaceId: string | undefined ): Promise { return withApmSpan('create_static_index_pattern', async () => { - const { config } = context; - // don't autocreate APM index pattern if it's been disabled via the config if (!config['xpack.apm.autocreateApmIndexPattern']) { return false; @@ -39,7 +37,7 @@ export async function createStaticIndexPattern( } try { - const apmIndexPatternTitle = getApmIndexPatternTitle(context); + const apmIndexPatternTitle = getApmIndexPatternTitle(config); await withApmSpan('create_index_pattern_saved_object', () => savedObjectsClient.create( 'index-pattern', diff --git a/x-pack/plugins/apm/server/lib/index_pattern/get_apm_index_pattern_title.ts b/x-pack/plugins/apm/server/lib/index_pattern/get_apm_index_pattern_title.ts index 41abe82de8ff..faec64c798c7 100644 --- a/x-pack/plugins/apm/server/lib/index_pattern/get_apm_index_pattern_title.ts +++ b/x-pack/plugins/apm/server/lib/index_pattern/get_apm_index_pattern_title.ts @@ -5,8 +5,10 @@ * 2.0. */ -import { APMRequestHandlerContext } from '../../routes/typings'; +import { APMRouteHandlerResources } from '../../routes/typings'; -export function getApmIndexPatternTitle(context: APMRequestHandlerContext) { - return context.config['apm_oss.indexPattern']; +export function getApmIndexPatternTitle( + config: APMRouteHandlerResources['config'] +) { + return config['apm_oss.indexPattern']; } diff --git a/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts b/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts index 5d5e6eebb4c9..8bbc22fbf289 100644 --- a/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts +++ b/x-pack/plugins/apm/server/lib/index_pattern/get_dynamic_index_pattern.ts @@ -9,7 +9,7 @@ import { IndexPatternsFetcher, FieldDescriptor, } from '../../../../../../src/plugins/data/server'; -import { APMRequestHandlerContext } from '../../routes/typings'; +import { APMRouteHandlerResources } from '../../routes/typings'; import { withApmSpan } from '../../utils/with_apm_span'; export interface IndexPatternTitleAndFields { @@ -20,12 +20,12 @@ export interface IndexPatternTitleAndFields { // TODO: this is currently cached globally. In the future we might want to cache this per user export const getDynamicIndexPattern = ({ + config, context, -}: { - context: APMRequestHandlerContext; -}) => { + logger, +}: Pick) => { return withApmSpan('get_dynamic_index_pattern', async () => { - const indexPatternTitle = context.config['apm_oss.indexPattern']; + const indexPatternTitle = config['apm_oss.indexPattern']; const indexPatternsFetcher = new IndexPatternsFetcher( context.core.elasticsearch.client.asCurrentUser @@ -50,7 +50,7 @@ export const getDynamicIndexPattern = ({ } catch (e) { const notExists = e.output?.statusCode === 404; if (notExists) { - context.logger.error( + logger.error( `Could not get dynamic index pattern because indices "${indexPatternTitle}" don't exist` ); return; diff --git a/x-pack/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts b/x-pack/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts index a1587611b0a2..d8dbc242986a 100644 --- a/x-pack/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts +++ b/x-pack/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts @@ -14,7 +14,7 @@ import { APM_INDICES_SAVED_OBJECT_ID, } from '../../../../common/apm_saved_object_constants'; import { APMConfig } from '../../..'; -import { APMRequestHandlerContext } from '../../../routes/typings'; +import { APMRouteHandlerResources } from '../../../routes/typings'; import { withApmSpan } from '../../../utils/with_apm_span'; type ISavedObjectsClient = Pick; @@ -91,9 +91,8 @@ const APM_UI_INDICES: ApmIndicesName[] = [ export async function getApmIndexSettings({ context, -}: { - context: APMRequestHandlerContext; -}) { + config, +}: Pick) { let apmIndicesSavedObject: PromiseReturnType; try { apmIndicesSavedObject = await getApmIndicesSavedObject( @@ -106,7 +105,7 @@ export async function getApmIndexSettings({ throw error; } } - const apmIndicesConfig = getApmIndicesConfig(context.config); + const apmIndicesConfig = getApmIndicesConfig(config); return APM_UI_INDICES.map((configurationName) => ({ configurationName, diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index db9679462751..074df7eaafd3 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { combineLatest, Observable } from 'rxjs'; +import { combineLatest } from 'rxjs'; import { map, take } from 'rxjs/operators'; import { CoreSetup, @@ -16,22 +16,10 @@ import { Plugin, PluginInitializerContext, } from 'src/core/server'; -import { SpacesPluginSetup } from '../../spaces/server'; +import { mapValues } from 'lodash'; import { APMConfig, APMXPackConfig } from '.'; import { mergeConfigs } from './index'; -import { APMOSSPluginSetup } from '../../../../src/plugins/apm_oss/server'; -import { HomeServerPluginSetup } from '../../../../src/plugins/home/server'; -import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; import { UI_SETTINGS } from '../../../../src/plugins/data/common'; -import { ActionsPlugin } from '../../actions/server'; -import { AlertingPlugin } from '../../alerting/server'; -import { CloudSetup } from '../../cloud/server'; -import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; -import { LicensingPluginSetup } from '../../licensing/server'; -import { MlPluginSetup } from '../../ml/server'; -import { ObservabilityPluginSetup } from '../../observability/server'; -import { SecurityPluginSetup } from '../../security/server'; -import { TaskManagerSetupContract } from '../../task_manager/server'; import { APM_FEATURE, registerFeaturesUsage } from './feature'; import { registerApmAlerts } from './lib/alerts/register_apm_alerts'; import { createApmTelemetry } from './lib/apm_telemetry'; @@ -40,23 +28,29 @@ import { getInternalSavedObjectsClient } from './lib/helpers/get_internal_saved_ import { createApmAgentConfigurationIndex } from './lib/settings/agent_configuration/create_agent_config_index'; import { getApmIndices } from './lib/settings/apm_indices/get_apm_indices'; import { createApmCustomLinkIndex } from './lib/settings/custom_link/create_custom_link_index'; -import { createApmApi } from './routes/create_apm_api'; import { apmIndices, apmTelemetry } from './saved_objects'; import { createElasticCloudInstructions } from './tutorial/elastic_cloud'; import { uiSettings } from './ui_settings'; -import type { ApmPluginRequestHandlerContext } from './routes/typings'; - -export interface APMPluginSetup { - config$: Observable; - getApmIndices: () => ReturnType; - createApmEventClient: (params: { - debug?: boolean; - request: KibanaRequest; - context: ApmPluginRequestHandlerContext; - }) => Promise>; -} - -export class APMPlugin implements Plugin { +import type { + ApmPluginRequestHandlerContext, + APMRouteHandlerResources, +} from './routes/typings'; +import { + APMPluginSetup, + APMPluginSetupDependencies, + APMPluginStartDependencies, +} from './types'; +import { registerRoutes } from './routes/register_routes'; +import { getGlobalApmServerRouteRepository } from './routes/get_global_apm_server_route_repository'; + +export class APMPlugin + implements + Plugin< + APMPluginSetup, + void, + APMPluginSetupDependencies, + APMPluginStartDependencies + > { private currentConfig?: APMConfig; private logger?: Logger; constructor(private readonly initContext: PluginInitializerContext) { @@ -64,22 +58,8 @@ export class APMPlugin implements Plugin { } public setup( - core: CoreSetup, - plugins: { - spaces?: SpacesPluginSetup; - apmOss: APMOSSPluginSetup; - home: HomeServerPluginSetup; - licensing: LicensingPluginSetup; - cloud?: CloudSetup; - usageCollection?: UsageCollectionSetup; - taskManager?: TaskManagerSetupContract; - alerting?: AlertingPlugin['setup']; - actions?: ActionsPlugin['setup']; - observability?: ObservabilityPluginSetup; - features: FeaturesPluginSetup; - security?: SecurityPluginSetup; - ml?: MlPluginSetup; - } + core: CoreSetup, + plugins: Omit ) { this.logger = this.initContext.logger.get(); const config$ = this.initContext.config.create(); @@ -101,11 +81,13 @@ export class APMPlugin implements Plugin { }); } - this.currentConfig = mergeConfigs( + const currentConfig = mergeConfigs( plugins.apmOss.config, this.initContext.config.get() ); + this.currentConfig = currentConfig; + if ( plugins.taskManager && plugins.usageCollection && @@ -122,8 +104,8 @@ export class APMPlugin implements Plugin { } const ossTutorialProvider = plugins.apmOss.getRegisteredTutorialProvider(); - plugins.home.tutorials.unregisterTutorial(ossTutorialProvider); - plugins.home.tutorials.registerTutorial(() => { + plugins.home?.tutorials.unregisterTutorial(ossTutorialProvider); + plugins.home?.tutorials.registerTutorial(() => { const ossPart = ossTutorialProvider({}); if (this.currentConfig!['xpack.apm.ui.enabled'] && ossPart.artifacts) { ossPart.artifacts.application = { @@ -147,10 +129,26 @@ export class APMPlugin implements Plugin { registerFeaturesUsage({ licensingPlugin: plugins.licensing }); - createApmApi().init(core, { - config$: mergedConfig$, - logger: this.logger!, - plugins, + registerRoutes({ + core: { + setup: core, + start: () => core.getStartServices().then(([coreStart]) => coreStart), + }, + logger: this.logger, + config: currentConfig, + repository: getGlobalApmServerRouteRepository(), + plugins: mapValues(plugins, (value, key) => { + return { + setup: value, + start: () => + core.getStartServices().then((services) => { + const [, pluginsStartContracts] = services; + return pluginsStartContracts[ + key as keyof APMPluginStartDependencies + ]; + }), + }; + }) as APMRouteHandlerResources['plugins'], }); const boundGetApmIndices = async () => diff --git a/x-pack/plugins/apm/server/routes/alerts/chart_preview.ts b/x-pack/plugins/apm/server/routes/alerts/chart_preview.ts index 3bebcd49ec34..0175860e93d3 100644 --- a/x-pack/plugins/apm/server/routes/alerts/chart_preview.ts +++ b/x-pack/plugins/apm/server/routes/alerts/chart_preview.ts @@ -10,7 +10,8 @@ import { getTransactionDurationChartPreview } from '../../lib/alerts/chart_previ import { getTransactionErrorCountChartPreview } from '../../lib/alerts/chart_preview/get_transaction_error_count'; import { getTransactionErrorRateChartPreview } from '../../lib/alerts/chart_preview/get_transaction_error_rate'; import { setupRequest } from '../../lib/helpers/setup_request'; -import { createRoute } from '../create_route'; +import { createApmServerRoute } from '../create_apm_server_route'; +import { createApmServerRouteRepository } from '../create_apm_server_route_repository'; import { rangeRt } from '../default_api_types'; const alertParamsRt = t.intersection([ @@ -29,13 +30,14 @@ const alertParamsRt = t.intersection([ export type AlertParams = t.TypeOf; -export const transactionErrorRateChartPreview = createRoute({ +const transactionErrorRateChartPreview = createApmServerRoute({ endpoint: 'GET /api/apm/alerts/chart_preview/transaction_error_rate', params: t.type({ query: alertParamsRt }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { _inspect, ...alertParams } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { _inspect, ...alertParams } = params.query; const errorRateChartPreview = await getTransactionErrorRateChartPreview({ setup, @@ -46,13 +48,16 @@ export const transactionErrorRateChartPreview = createRoute({ }, }); -export const transactionErrorCountChartPreview = createRoute({ +const transactionErrorCountChartPreview = createApmServerRoute({ endpoint: 'GET /api/apm/alerts/chart_preview/transaction_error_count', params: t.type({ query: alertParamsRt }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { _inspect, ...alertParams } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + + const { _inspect, ...alertParams } = params.query; + const errorCountChartPreview = await getTransactionErrorCountChartPreview({ setup, alertParams, @@ -62,13 +67,16 @@ export const transactionErrorCountChartPreview = createRoute({ }, }); -export const transactionDurationChartPreview = createRoute({ +const transactionDurationChartPreview = createApmServerRoute({ endpoint: 'GET /api/apm/alerts/chart_preview/transaction_duration', params: t.type({ query: alertParamsRt }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { _inspect, ...alertParams } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + + const { params } = resources; + + const { _inspect, ...alertParams } = params.query; const latencyChartPreview = await getTransactionDurationChartPreview({ alertParams, @@ -78,3 +86,9 @@ export const transactionDurationChartPreview = createRoute({ return { latencyChartPreview }; }, }); + +export const alertsChartPreviewRouteRepository = createApmServerRouteRepository() + .add(transactionErrorRateChartPreview) + .add(transactionDurationChartPreview) + .add(transactionErrorCountChartPreview) + .add(transactionDurationChartPreview); diff --git a/x-pack/plugins/apm/server/routes/correlations.ts b/x-pack/plugins/apm/server/routes/correlations.ts index c7c69e077482..4728aa2e8d3f 100644 --- a/x-pack/plugins/apm/server/routes/correlations.ts +++ b/x-pack/plugins/apm/server/routes/correlations.ts @@ -14,7 +14,8 @@ import { getOverallErrorTimeseries } from '../lib/correlations/errors/get_overal import { getCorrelationsForSlowTransactions } from '../lib/correlations/latency/get_correlations_for_slow_transactions'; import { getOverallLatencyDistribution } from '../lib/correlations/latency/get_overall_latency_distribution'; import { setupRequest } from '../lib/helpers/setup_request'; -import { createRoute } from './create_route'; +import { createApmServerRoute } from './create_apm_server_route'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; import { environmentRt, kueryRt, rangeRt } from './default_api_types'; const INVALID_LICENSE = i18n.translate( @@ -25,7 +26,7 @@ const INVALID_LICENSE = i18n.translate( } ); -export const correlationsLatencyDistributionRoute = createRoute({ +const correlationsLatencyDistributionRoute = createApmServerRoute({ endpoint: 'GET /api/apm/correlations/latency/overall_distribution', params: t.type({ query: t.intersection([ @@ -40,18 +41,19 @@ export const correlationsLatencyDistributionRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { + handler: async (resources) => { + const { context, params } = resources; if (!isActivePlatinumLicense(context.licensing.license)) { throw Boom.forbidden(INVALID_LICENSE); } - const setup = await setupRequest(context, request); + const setup = await setupRequest(resources); const { environment, kuery, serviceName, transactionType, transactionName, - } = context.params.query; + } = params.query; return getOverallLatencyDistribution({ environment, @@ -64,7 +66,7 @@ export const correlationsLatencyDistributionRoute = createRoute({ }, }); -export const correlationsForSlowTransactionsRoute = createRoute({ +const correlationsForSlowTransactionsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/correlations/latency/slow_transactions', params: t.type({ query: t.intersection([ @@ -85,11 +87,13 @@ export const correlationsForSlowTransactionsRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { + handler: async (resources) => { + const { context, params } = resources; + if (!isActivePlatinumLicense(context.licensing.license)) { throw Boom.forbidden(INVALID_LICENSE); } - const setup = await setupRequest(context, request); + const setup = await setupRequest(resources); const { environment, kuery, @@ -100,7 +104,7 @@ export const correlationsForSlowTransactionsRoute = createRoute({ fieldNames, maxLatency, distributionInterval, - } = context.params.query; + } = params.query; return getCorrelationsForSlowTransactions({ environment, @@ -117,7 +121,7 @@ export const correlationsForSlowTransactionsRoute = createRoute({ }, }); -export const correlationsErrorDistributionRoute = createRoute({ +const correlationsErrorDistributionRoute = createApmServerRoute({ endpoint: 'GET /api/apm/correlations/errors/overall_timeseries', params: t.type({ query: t.intersection([ @@ -132,18 +136,20 @@ export const correlationsErrorDistributionRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { + handler: async (resources) => { + const { params, context } = resources; + if (!isActivePlatinumLicense(context.licensing.license)) { throw Boom.forbidden(INVALID_LICENSE); } - const setup = await setupRequest(context, request); + const setup = await setupRequest(resources); const { environment, kuery, serviceName, transactionType, transactionName, - } = context.params.query; + } = params.query; return getOverallErrorTimeseries({ environment, @@ -156,7 +162,7 @@ export const correlationsErrorDistributionRoute = createRoute({ }, }); -export const correlationsForFailedTransactionsRoute = createRoute({ +const correlationsForFailedTransactionsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/correlations/errors/failed_transactions', params: t.type({ query: t.intersection([ @@ -174,11 +180,12 @@ export const correlationsForFailedTransactionsRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { + handler: async (resources) => { + const { context, params } = resources; if (!isActivePlatinumLicense(context.licensing.license)) { throw Boom.forbidden(INVALID_LICENSE); } - const setup = await setupRequest(context, request); + const setup = await setupRequest(resources); const { environment, kuery, @@ -186,7 +193,7 @@ export const correlationsForFailedTransactionsRoute = createRoute({ transactionType, transactionName, fieldNames, - } = context.params.query; + } = params.query; return getCorrelationsForFailedTransactions({ environment, @@ -199,3 +206,9 @@ export const correlationsForFailedTransactionsRoute = createRoute({ }); }, }); + +export const correlationsRouteRepository = createApmServerRouteRepository() + .add(correlationsLatencyDistributionRoute) + .add(correlationsForSlowTransactionsRoute) + .add(correlationsErrorDistributionRoute) + .add(correlationsForFailedTransactionsRoute); diff --git a/x-pack/plugins/apm/server/routes/create_api/index.test.ts b/x-pack/plugins/apm/server/routes/create_api/index.test.ts deleted file mode 100644 index 9958b8dec012..000000000000 --- a/x-pack/plugins/apm/server/routes/create_api/index.test.ts +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as t from 'io-ts'; -import { createApi } from './index'; -import { CoreSetup, Logger } from 'src/core/server'; -import { RouteParamsRT } from '../typings'; -import { BehaviorSubject } from 'rxjs'; -import { APMConfig } from '../..'; -import { jsonRt } from '../../../common/runtime_types/json_rt'; - -const getCoreMock = () => { - const get = jest.fn(); - const post = jest.fn(); - const put = jest.fn(); - const createRouter = jest.fn().mockReturnValue({ - get, - post, - put, - }); - - const mock = {} as CoreSetup; - - return { - mock: { - ...mock, - http: { - ...mock.http, - createRouter, - }, - }, - get, - post, - put, - createRouter, - context: { - measure: () => undefined, - config$: new BehaviorSubject({} as APMConfig), - logger: ({ - error: jest.fn(), - } as unknown) as Logger, - plugins: {}, - }, - }; -}; - -const initApi = (params?: RouteParamsRT) => { - const { mock, context, createRouter, get, post } = getCoreMock(); - const handlerMock = jest.fn(); - createApi() - .add(() => ({ - endpoint: 'GET /foo', - params, - options: { tags: ['access:apm'] }, - handler: handlerMock, - })) - .init(mock, context); - - const routeHandler = get.mock.calls[0][1]; - - const responseMock = { - ok: jest.fn(), - custom: jest.fn(), - }; - - const simulateRequest = (requestMock: any) => { - return routeHandler( - {}, - { - // stub default values - params: {}, - query: {}, - body: null, - ...requestMock, - }, - responseMock - ); - }; - - return { - simulateRequest, - handlerMock, - createRouter, - get, - post, - responseMock, - }; -}; - -describe('createApi', () => { - it('registers a route with the server', () => { - const { mock, context, createRouter, post, get, put } = getCoreMock(); - - createApi() - .add(() => ({ - endpoint: 'GET /foo', - options: { tags: ['access:apm'] }, - handler: async () => ({}), - })) - .add(() => ({ - endpoint: 'POST /bar', - params: t.type({ - body: t.string, - }), - options: { tags: ['access:apm'] }, - handler: async () => ({}), - })) - .add(() => ({ - endpoint: 'PUT /baz', - options: { - tags: ['access:apm', 'access:apm_write'], - }, - handler: async () => ({}), - })) - .add({ - endpoint: 'GET /qux', - options: { - tags: ['access:apm', 'access:apm_write'], - }, - handler: async () => ({}), - }) - .init(mock, context); - - expect(createRouter).toHaveBeenCalledTimes(1); - - expect(get).toHaveBeenCalledTimes(2); - expect(post).toHaveBeenCalledTimes(1); - expect(put).toHaveBeenCalledTimes(1); - - expect(get.mock.calls[0][0]).toEqual({ - options: { - tags: ['access:apm'], - }, - path: '/foo', - validate: expect.anything(), - }); - - expect(get.mock.calls[1][0]).toEqual({ - options: { - tags: ['access:apm', 'access:apm_write'], - }, - path: '/qux', - validate: expect.anything(), - }); - - expect(post.mock.calls[0][0]).toEqual({ - options: { - tags: ['access:apm'], - }, - path: '/bar', - validate: expect.anything(), - }); - - expect(put.mock.calls[0][0]).toEqual({ - options: { - tags: ['access:apm', 'access:apm_write'], - }, - path: '/baz', - validate: expect.anything(), - }); - }); - - describe('when validating', () => { - describe('_inspect', () => { - it('allows _inspect=true', async () => { - const { simulateRequest, handlerMock, responseMock } = initApi(); - await simulateRequest({ query: { _inspect: 'true' } }); - - const params = handlerMock.mock.calls[0][0].context.params; - expect(params).toEqual({ query: { _inspect: true } }); - expect(handlerMock).toHaveBeenCalledTimes(1); - - // responds with ok - expect(responseMock.custom).not.toHaveBeenCalled(); - expect(responseMock.ok).toHaveBeenCalledWith({ - body: { _inspect: [] }, - }); - }); - - it('rejects _inspect=1', async () => { - const { simulateRequest, responseMock } = initApi(); - await simulateRequest({ query: { _inspect: 1 } }); - - // responds with error handler - expect(responseMock.ok).not.toHaveBeenCalled(); - expect(responseMock.custom).toHaveBeenCalledWith({ - body: { - attributes: { _inspect: [] }, - message: - 'Invalid value 1 supplied to : strict_keys/query: Partial<{| _inspect: pipe(JSON, boolean) |}>/_inspect: pipe(JSON, boolean)', - }, - statusCode: 400, - }); - }); - - it('allows omitting _inspect', async () => { - const { simulateRequest, handlerMock, responseMock } = initApi(); - await simulateRequest({ query: {} }); - - const params = handlerMock.mock.calls[0][0].context.params; - expect(params).toEqual({ query: { _inspect: false } }); - expect(handlerMock).toHaveBeenCalledTimes(1); - - // responds with ok - expect(responseMock.custom).not.toHaveBeenCalled(); - expect(responseMock.ok).toHaveBeenCalledWith({ body: {} }); - }); - }); - - it('throws if unknown parameters are provided', async () => { - const { simulateRequest, responseMock } = initApi(); - - await simulateRequest({ - query: { _inspect: true, extra: '' }, - }); - - expect(responseMock.custom).toHaveBeenCalledTimes(1); - - await simulateRequest({ - body: { foo: 'bar' }, - }); - - expect(responseMock.custom).toHaveBeenCalledTimes(2); - - await simulateRequest({ - params: { - foo: 'bar', - }, - }); - - expect(responseMock.custom).toHaveBeenCalledTimes(3); - }); - - it('validates path parameters', async () => { - const { simulateRequest, handlerMock, responseMock } = initApi( - t.type({ - path: t.type({ - foo: t.string, - }), - }) - ); - - await simulateRequest({ - params: { - foo: 'bar', - }, - }); - - expect(handlerMock).toHaveBeenCalledTimes(1); - - expect(responseMock.ok).toHaveBeenCalledTimes(1); - expect(responseMock.custom).not.toHaveBeenCalled(); - - const params = handlerMock.mock.calls[0][0].context.params; - - expect(params).toEqual({ - path: { - foo: 'bar', - }, - query: { - _inspect: false, - }, - }); - - await simulateRequest({ - params: { - bar: 'foo', - }, - }); - - expect(responseMock.custom).toHaveBeenCalledTimes(1); - - await simulateRequest({ - params: { - foo: 9, - }, - }); - - expect(responseMock.custom).toHaveBeenCalledTimes(2); - - await simulateRequest({ - params: { - foo: 'bar', - extra: '', - }, - }); - - expect(responseMock.custom).toHaveBeenCalledTimes(3); - }); - - it('validates body parameters', async () => { - const { simulateRequest, handlerMock, responseMock } = initApi( - t.type({ - body: t.string, - }) - ); - - await simulateRequest({ - body: '', - }); - - expect(responseMock.custom).not.toHaveBeenCalled(); - expect(handlerMock).toHaveBeenCalledTimes(1); - expect(responseMock.ok).toHaveBeenCalledTimes(1); - - const params = handlerMock.mock.calls[0][0].context.params; - - expect(params).toEqual({ - body: '', - query: { - _inspect: false, - }, - }); - - await simulateRequest({ - body: null, - }); - - expect(responseMock.custom).toHaveBeenCalledTimes(1); - }); - - it('validates query parameters', async () => { - const { simulateRequest, handlerMock, responseMock } = initApi( - t.type({ - query: t.type({ - bar: t.string, - filterNames: jsonRt.pipe(t.array(t.string)), - }), - }) - ); - - await simulateRequest({ - query: { - bar: '', - _inspect: 'true', - filterNames: JSON.stringify(['hostName', 'agentName']), - }, - }); - - expect(responseMock.custom).not.toHaveBeenCalled(); - expect(handlerMock).toHaveBeenCalledTimes(1); - expect(responseMock.ok).toHaveBeenCalledTimes(1); - - const params = handlerMock.mock.calls[0][0].context.params; - - expect(params).toEqual({ - query: { - bar: '', - _inspect: true, - filterNames: ['hostName', 'agentName'], - }, - }); - - await simulateRequest({ - query: { - bar: '', - foo: '', - }, - }); - - expect(responseMock.custom).toHaveBeenCalledTimes(1); - }); - }); -}); diff --git a/x-pack/plugins/apm/server/routes/create_api/index.ts b/x-pack/plugins/apm/server/routes/create_api/index.ts deleted file mode 100644 index 87bc97d34698..000000000000 --- a/x-pack/plugins/apm/server/routes/create_api/index.ts +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { merge as mergeLodash, pickBy, isEmpty, isPlainObject } from 'lodash'; -import Boom from '@hapi/boom'; -import { schema } from '@kbn/config-schema'; -import * as t from 'io-ts'; -import { PathReporter } from 'io-ts/lib/PathReporter'; -import { isLeft } from 'fp-ts/lib/Either'; -import { KibanaRequest, RouteRegistrar } from 'src/core/server'; -import { RequestAbortedError } from '@elastic/elasticsearch/lib/errors'; -import agent from 'elastic-apm-node'; -import { parseMethod } from '../../../common/apm_api/parse_endpoint'; -import { merge } from '../../../common/runtime_types/merge'; -import { strictKeysRt } from '../../../common/runtime_types/strict_keys_rt'; -import { APMConfig } from '../..'; -import { InspectResponse, RouteParamsRT, ServerAPI } from '../typings'; -import { jsonRt } from '../../../common/runtime_types/json_rt'; -import type { ApmPluginRequestHandlerContext } from '../typings'; - -const inspectRt = t.exact( - t.partial({ - query: t.exact(t.partial({ _inspect: jsonRt.pipe(t.boolean) })), - }) -); - -type RouteOrRouteFactoryFn = Parameters['add']>[0]; - -const isNotEmpty = (val: any) => - val !== undefined && val !== null && !(isPlainObject(val) && isEmpty(val)); - -export const inspectableEsQueriesMap = new WeakMap< - KibanaRequest, - InspectResponse ->(); - -export function createApi() { - const routes: RouteOrRouteFactoryFn[] = []; - const api: ServerAPI<{}> = { - _S: {}, - add(route) { - routes.push((route as unknown) as RouteOrRouteFactoryFn); - return this as any; - }, - init(core, { config$, logger, plugins }) { - const router = core.http.createRouter(); - - let config = {} as APMConfig; - - config$.subscribe((val) => { - config = val; - }); - - routes.forEach((routeOrFactoryFn) => { - const route = - typeof routeOrFactoryFn === 'function' - ? routeOrFactoryFn(core) - : routeOrFactoryFn; - - const { params, endpoint, options, handler } = route; - - const [method, path] = endpoint.split(' '); - const typedRouterMethod = parseMethod(method); - - // For all runtime types with props, we create an exact - // version that will strip all keys that are unvalidated. - const anyObject = schema.object({}, { unknowns: 'allow' }); - - (router[typedRouterMethod] as RouteRegistrar< - typeof typedRouterMethod, - ApmPluginRequestHandlerContext - >)( - { - path, - options, - validate: { - // `body` can be null, but `validate` expects non-nullable types - // if any validation is defined. Not having validation currently - // means we don't get the payload. See - // https://github.com/elastic/kibana/issues/50179 - body: schema.nullable(anyObject), - params: anyObject, - query: anyObject, - }, - }, - async (context, request, response) => { - if (agent.isStarted()) { - agent.addLabels({ - plugin: 'apm', - }); - } - - // init debug queries - inspectableEsQueriesMap.set(request, []); - - try { - const validParams = validateParams(request, params); - const data = await handler({ - request, - context: { - ...context, - plugins, - params: validParams, - config, - logger, - }, - }); - - const body = { ...data }; - if (validParams.query._inspect) { - body._inspect = inspectableEsQueriesMap.get(request); - } - - // cleanup - inspectableEsQueriesMap.delete(request); - - return response.ok({ body }); - } catch (error) { - logger.error(error); - const opts = { - statusCode: 500, - body: { - message: error.message, - attributes: { - _inspect: inspectableEsQueriesMap.get(request), - }, - }, - }; - - if (Boom.isBoom(error)) { - opts.statusCode = error.output.statusCode; - } - - if (error instanceof RequestAbortedError) { - opts.statusCode = 499; - opts.body.message = 'Client closed request'; - } - - return response.custom(opts); - } - } - ); - }); - }, - }; - - return api; -} - -function validateParams( - request: KibanaRequest, - params: RouteParamsRT | undefined -) { - const paramsRt = params ? merge([params, inspectRt]) : inspectRt; - const paramMap = pickBy( - { - path: request.params, - body: request.body, - query: { - _inspect: 'false', - // @ts-ignore - ...request.query, - }, - }, - isNotEmpty - ); - - const result = strictKeysRt(paramsRt).decode(paramMap); - - if (isLeft(result)) { - throw Boom.badRequest(PathReporter.report(result)[0]); - } - - // Only return values for parameters that have runtime types, - // but always include query as _inspect is always set even if - // it's not defined in the route. - return mergeLodash( - { query: { _inspect: false } }, - pickBy(result.right, isNotEmpty) - ); -} diff --git a/x-pack/plugins/apm/server/routes/create_apm_api.ts b/x-pack/plugins/apm/server/routes/create_apm_api.ts deleted file mode 100644 index 5b74aa4347f1..000000000000 --- a/x-pack/plugins/apm/server/routes/create_apm_api.ts +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - staticIndexPatternRoute, - dynamicIndexPatternRoute, - apmIndexPatternTitleRoute, -} from './index_pattern'; -import { createApi } from './create_api'; -import { environmentsRoute } from './environments'; -import { - errorDistributionRoute, - errorGroupsRoute, - errorsRoute, -} from './errors'; -import { - serviceAgentNameRoute, - serviceTransactionTypesRoute, - servicesRoute, - serviceNodeMetadataRoute, - serviceAnnotationsRoute, - serviceAnnotationsCreateRoute, - serviceErrorGroupsPrimaryStatisticsRoute, - serviceErrorGroupsComparisonStatisticsRoute, - serviceThroughputRoute, - serviceDependenciesRoute, - serviceMetadataDetailsRoute, - serviceMetadataIconsRoute, - serviceInstancesPrimaryStatisticsRoute, - serviceInstancesComparisonStatisticsRoute, - serviceProfilingStatisticsRoute, - serviceProfilingTimelineRoute, -} from './services'; -import { - agentConfigurationRoute, - getSingleAgentConfigurationRoute, - agentConfigurationSearchRoute, - deleteAgentConfigurationRoute, - listAgentConfigurationEnvironmentsRoute, - listAgentConfigurationServicesRoute, - createOrUpdateAgentConfigurationRoute, - agentConfigurationAgentNameRoute, -} from './settings/agent_configuration'; -import { - apmIndexSettingsRoute, - apmIndicesRoute, - saveApmIndicesRoute, -} from './settings/apm_indices'; -import { metricsChartsRoute } from './metrics'; -import { serviceNodesRoute } from './service_nodes'; -import { - tracesRoute, - tracesByIdRoute, - rootTransactionByTraceIdRoute, -} from './traces'; -import { - correlationsLatencyDistributionRoute, - correlationsForSlowTransactionsRoute, - correlationsErrorDistributionRoute, - correlationsForFailedTransactionsRoute, -} from './correlations'; -import { - transactionChartsBreakdownRoute, - transactionChartsDistributionRoute, - transactionChartsErrorRateRoute, - transactionGroupsRoute, - transactionGroupsPrimaryStatisticsRoute, - transactionLatencyChartsRoute, - transactionThroughputChartsRoute, - transactionGroupsComparisonStatisticsRoute, -} from './transactions'; -import { serviceMapRoute, serviceMapServiceNodeRoute } from './service_map'; -import { - createCustomLinkRoute, - updateCustomLinkRoute, - deleteCustomLinkRoute, - listCustomLinksRoute, - customLinkTransactionRoute, -} from './settings/custom_link'; -import { - observabilityOverviewHasDataRoute, - observabilityOverviewRoute, -} from './observability_overview'; -import { - anomalyDetectionJobsRoute, - createAnomalyDetectionJobsRoute, - anomalyDetectionEnvironmentsRoute, -} from './settings/anomaly_detection'; -import { - rumHasDataRoute, - rumClientMetricsRoute, - rumJSErrors, - rumLongTaskMetrics, - rumOverviewLocalFiltersRoute, - rumPageLoadDistBreakdownRoute, - rumPageLoadDistributionRoute, - rumPageViewsTrendRoute, - rumServicesRoute, - rumUrlSearch, - rumVisitorsBreakdownRoute, - rumWebCoreVitals, -} from './rum_client'; -import { - transactionErrorRateChartPreview, - transactionErrorCountChartPreview, - transactionDurationChartPreview, -} from './alerts/chart_preview'; - -const createApmApi = () => { - const api = createApi() - // index pattern - .add(staticIndexPatternRoute) - .add(dynamicIndexPatternRoute) - .add(apmIndexPatternTitleRoute) - - // Environments - .add(environmentsRoute) - - // Errors - .add(errorDistributionRoute) - .add(errorGroupsRoute) - .add(errorsRoute) - - // Services - .add(serviceAgentNameRoute) - .add(serviceTransactionTypesRoute) - .add(servicesRoute) - .add(serviceNodeMetadataRoute) - .add(serviceAnnotationsRoute) - .add(serviceAnnotationsCreateRoute) - .add(serviceErrorGroupsPrimaryStatisticsRoute) - .add(serviceThroughputRoute) - .add(serviceDependenciesRoute) - .add(serviceMetadataDetailsRoute) - .add(serviceMetadataIconsRoute) - .add(serviceInstancesPrimaryStatisticsRoute) - .add(serviceInstancesComparisonStatisticsRoute) - .add(serviceErrorGroupsComparisonStatisticsRoute) - .add(serviceProfilingTimelineRoute) - .add(serviceProfilingStatisticsRoute) - - // Agent configuration - .add(getSingleAgentConfigurationRoute) - .add(agentConfigurationAgentNameRoute) - .add(agentConfigurationRoute) - .add(agentConfigurationSearchRoute) - .add(deleteAgentConfigurationRoute) - .add(listAgentConfigurationEnvironmentsRoute) - .add(listAgentConfigurationServicesRoute) - .add(createOrUpdateAgentConfigurationRoute) - - // Correlations - .add(correlationsLatencyDistributionRoute) - .add(correlationsForSlowTransactionsRoute) - .add(correlationsErrorDistributionRoute) - .add(correlationsForFailedTransactionsRoute) - - // APM indices - .add(apmIndexSettingsRoute) - .add(apmIndicesRoute) - .add(saveApmIndicesRoute) - - // Metrics - .add(metricsChartsRoute) - .add(serviceNodesRoute) - - // Traces - .add(tracesRoute) - .add(tracesByIdRoute) - .add(rootTransactionByTraceIdRoute) - - // Transactions - .add(transactionChartsBreakdownRoute) - .add(transactionChartsDistributionRoute) - .add(transactionChartsErrorRateRoute) - .add(transactionGroupsRoute) - .add(transactionGroupsPrimaryStatisticsRoute) - .add(transactionLatencyChartsRoute) - .add(transactionThroughputChartsRoute) - .add(transactionGroupsComparisonStatisticsRoute) - - // Service map - .add(serviceMapRoute) - .add(serviceMapServiceNodeRoute) - - // Custom links - .add(createCustomLinkRoute) - .add(updateCustomLinkRoute) - .add(deleteCustomLinkRoute) - .add(listCustomLinksRoute) - .add(customLinkTransactionRoute) - - // Observability dashboard - .add(observabilityOverviewHasDataRoute) - .add(observabilityOverviewRoute) - - // Anomaly detection - .add(anomalyDetectionJobsRoute) - .add(createAnomalyDetectionJobsRoute) - .add(anomalyDetectionEnvironmentsRoute) - - // User Experience app api routes - .add(rumOverviewLocalFiltersRoute) - .add(rumPageViewsTrendRoute) - .add(rumPageLoadDistributionRoute) - .add(rumPageLoadDistBreakdownRoute) - .add(rumClientMetricsRoute) - .add(rumServicesRoute) - .add(rumVisitorsBreakdownRoute) - .add(rumWebCoreVitals) - .add(rumJSErrors) - .add(rumUrlSearch) - .add(rumLongTaskMetrics) - .add(rumHasDataRoute) - - // Alerting - .add(transactionErrorCountChartPreview) - .add(transactionDurationChartPreview) - .add(transactionErrorRateChartPreview); - - return api; -}; - -export type APMAPI = ReturnType; - -export { createApmApi }; diff --git a/x-pack/plugins/apm/server/routes/create_apm_server_route.ts b/x-pack/plugins/apm/server/routes/create_apm_server_route.ts new file mode 100644 index 000000000000..86330a87a8c5 --- /dev/null +++ b/x-pack/plugins/apm/server/routes/create_apm_server_route.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { createServerRouteFactory } from '@kbn/server-route-repository'; +import { APMRouteCreateOptions, APMRouteHandlerResources } from './typings'; + +export const createApmServerRoute = createServerRouteFactory< + APMRouteHandlerResources, + APMRouteCreateOptions +>(); diff --git a/x-pack/plugins/apm/server/routes/create_apm_server_route_repository.ts b/x-pack/plugins/apm/server/routes/create_apm_server_route_repository.ts new file mode 100644 index 000000000000..b7cbe890c57d --- /dev/null +++ b/x-pack/plugins/apm/server/routes/create_apm_server_route_repository.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { createServerRouteRepository } from '@kbn/server-route-repository'; +import { APMRouteCreateOptions, APMRouteHandlerResources } from './typings'; + +export function createApmServerRouteRepository() { + return createServerRouteRepository< + APMRouteHandlerResources, + APMRouteCreateOptions + >(); +} diff --git a/x-pack/plugins/apm/server/routes/create_route.ts b/x-pack/plugins/apm/server/routes/create_route.ts deleted file mode 100644 index d74aac0992eb..000000000000 --- a/x-pack/plugins/apm/server/routes/create_route.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { CoreSetup } from 'src/core/server'; -import { HandlerReturn, Route, RouteParamsRT } from './typings'; - -export function createRoute< - TEndpoint extends string, - TReturn extends HandlerReturn, - TRouteParamsRT extends RouteParamsRT | undefined = undefined ->( - route: Route -): Route; - -export function createRoute< - TEndpoint extends string, - TReturn extends HandlerReturn, - TRouteParamsRT extends RouteParamsRT | undefined = undefined ->( - route: (core: CoreSetup) => Route -): (core: CoreSetup) => Route; - -export function createRoute(routeOrFactoryFn: Function | object) { - return routeOrFactoryFn; -} diff --git a/x-pack/plugins/apm/server/routes/environments.ts b/x-pack/plugins/apm/server/routes/environments.ts index 4aa7d7e6d412..e06fbdf7fb6d 100644 --- a/x-pack/plugins/apm/server/routes/environments.ts +++ b/x-pack/plugins/apm/server/routes/environments.ts @@ -9,10 +9,11 @@ import * as t from 'io-ts'; import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; import { setupRequest } from '../lib/helpers/setup_request'; import { getEnvironments } from '../lib/environments/get_environments'; -import { createRoute } from './create_route'; import { rangeRt } from './default_api_types'; +import { createApmServerRoute } from './create_apm_server_route'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; -export const environmentsRoute = createRoute({ +const environmentsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/environments', params: t.type({ query: t.intersection([ @@ -23,9 +24,10 @@ export const environmentsRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.query; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup ); @@ -39,3 +41,7 @@ export const environmentsRoute = createRoute({ return { environments }; }, }); + +export const environmentsRouteRepository = createApmServerRouteRepository().add( + environmentsRoute +); diff --git a/x-pack/plugins/apm/server/routes/errors.ts b/x-pack/plugins/apm/server/routes/errors.ts index f69d3fc9631d..d6bb1d4bcbaa 100644 --- a/x-pack/plugins/apm/server/routes/errors.ts +++ b/x-pack/plugins/apm/server/routes/errors.ts @@ -6,14 +6,15 @@ */ import * as t from 'io-ts'; -import { createRoute } from './create_route'; +import { createApmServerRoute } from './create_apm_server_route'; import { getErrorDistribution } from '../lib/errors/distribution/get_distribution'; import { getErrorGroupSample } from '../lib/errors/get_error_group_sample'; import { getErrorGroups } from '../lib/errors/get_error_groups'; import { setupRequest } from '../lib/helpers/setup_request'; import { environmentRt, kueryRt, rangeRt } from './default_api_types'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; -export const errorsRoute = createRoute({ +const errorsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/errors', params: t.type({ path: t.type({ @@ -30,9 +31,9 @@ export const errorsRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { params } = context; + handler: async (resources) => { + const { params } = resources; + const setup = await setupRequest(resources); const { serviceName } = params.path; const { environment, kuery, sortField, sortDirection } = params.query; @@ -49,7 +50,7 @@ export const errorsRoute = createRoute({ }, }); -export const errorGroupsRoute = createRoute({ +const errorGroupsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/errors/{groupId}', params: t.type({ path: t.type({ @@ -59,10 +60,11 @@ export const errorGroupsRoute = createRoute({ query: t.intersection([environmentRt, kueryRt, rangeRt]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName, groupId } = context.params.path; - const { environment, kuery } = context.params.query; + handler: async (resources) => { + const { params } = resources; + const setup = await setupRequest(resources); + const { serviceName, groupId } = params.path; + const { environment, kuery } = params.query; return getErrorGroupSample({ environment, @@ -74,7 +76,7 @@ export const errorGroupsRoute = createRoute({ }, }); -export const errorDistributionRoute = createRoute({ +const errorDistributionRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/errors/distribution', params: t.type({ path: t.type({ @@ -90,9 +92,9 @@ export const errorDistributionRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { params } = context; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; const { serviceName } = params.path; const { environment, kuery, groupId } = params.query; return getErrorDistribution({ @@ -104,3 +106,8 @@ export const errorDistributionRoute = createRoute({ }); }, }); + +export const errorsRouteRepository = createApmServerRouteRepository() + .add(errorsRoute) + .add(errorGroupsRoute) + .add(errorDistributionRoute); diff --git a/x-pack/plugins/apm/server/routes/get_global_apm_server_route_repository.ts b/x-pack/plugins/apm/server/routes/get_global_apm_server_route_repository.ts new file mode 100644 index 000000000000..c151752b4b6e --- /dev/null +++ b/x-pack/plugins/apm/server/routes/get_global_apm_server_route_repository.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { + ServerRouteRepository, + ReturnOf, + EndpointOf, +} from '@kbn/server-route-repository'; +import { PickByValue } from 'utility-types'; +import { alertsChartPreviewRouteRepository } from './alerts/chart_preview'; +import { correlationsRouteRepository } from './correlations'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; +import { environmentsRouteRepository } from './environments'; +import { errorsRouteRepository } from './errors'; +import { indexPatternRouteRepository } from './index_pattern'; +import { metricsRouteRepository } from './metrics'; +import { observabilityOverviewRouteRepository } from './observability_overview'; +import { rumRouteRepository } from './rum_client'; +import { serviceRouteRepository } from './services'; +import { serviceMapRouteRepository } from './service_map'; +import { serviceNodeRouteRepository } from './service_nodes'; +import { agentConfigurationRouteRepository } from './settings/agent_configuration'; +import { anomalyDetectionRouteRepository } from './settings/anomaly_detection'; +import { apmIndicesRouteRepository } from './settings/apm_indices'; +import { customLinkRouteRepository } from './settings/custom_link'; +import { traceRouteRepository } from './traces'; +import { transactionRouteRepository } from './transactions'; +import { APMRouteHandlerResources } from './typings'; + +const getTypedGlobalApmServerRouteRepository = () => { + const repository = createApmServerRouteRepository() + .merge(indexPatternRouteRepository) + .merge(environmentsRouteRepository) + .merge(errorsRouteRepository) + .merge(metricsRouteRepository) + .merge(observabilityOverviewRouteRepository) + .merge(rumRouteRepository) + .merge(serviceMapRouteRepository) + .merge(serviceNodeRouteRepository) + .merge(serviceRouteRepository) + .merge(traceRouteRepository) + .merge(transactionRouteRepository) + .merge(alertsChartPreviewRouteRepository) + .merge(correlationsRouteRepository) + .merge(agentConfigurationRouteRepository) + .merge(anomalyDetectionRouteRepository) + .merge(apmIndicesRouteRepository) + .merge(customLinkRouteRepository); + + return repository; +}; + +const getGlobalApmServerRouteRepository = () => { + return getTypedGlobalApmServerRouteRepository() as ServerRouteRepository; +}; + +export type APMServerRouteRepository = ReturnType< + typeof getTypedGlobalApmServerRouteRepository +>; + +// Ensure no APIs return arrays (or, by proxy, the any type), +// to guarantee compatibility with _inspect. + +type CompositeEndpoint = EndpointOf; + +type EndpointReturnTypes = { + [Endpoint in CompositeEndpoint]: ReturnOf; +}; + +type ArrayLikeReturnTypes = PickByValue; + +type ViolatingEndpoints = keyof ArrayLikeReturnTypes; + +function assertType() {} + +// if any endpoint has an array-like return type, the assertion below will fail +assertType(); + +export { getGlobalApmServerRouteRepository }; diff --git a/x-pack/plugins/apm/server/routes/index_pattern.ts b/x-pack/plugins/apm/server/routes/index_pattern.ts index 3b800c23135c..aa70cde4f96a 100644 --- a/x-pack/plugins/apm/server/routes/index_pattern.ts +++ b/x-pack/plugins/apm/server/routes/index_pattern.ts @@ -6,49 +6,67 @@ */ import { createStaticIndexPattern } from '../lib/index_pattern/create_static_index_pattern'; -import { createRoute } from './create_route'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; import { setupRequest } from '../lib/helpers/setup_request'; -import { getInternalSavedObjectsClient } from '../lib/helpers/get_internal_saved_objects_client'; import { getApmIndexPatternTitle } from '../lib/index_pattern/get_apm_index_pattern_title'; import { getDynamicIndexPattern } from '../lib/index_pattern/get_dynamic_index_pattern'; +import { createApmServerRoute } from './create_apm_server_route'; -export const staticIndexPatternRoute = createRoute((core) => ({ +const staticIndexPatternRoute = createApmServerRoute({ endpoint: 'POST /api/apm/index_pattern/static', options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { + handler: async (resources) => { + const { + request, + core, + plugins: { spaces }, + config, + } = resources; + const [setup, savedObjectsClient] = await Promise.all([ - setupRequest(context, request), - getInternalSavedObjectsClient(core), + setupRequest(resources), + core + .start() + .then((coreStart) => coreStart.savedObjects.createInternalRepository()), ]); - const spaceId = context.plugins.spaces?.spacesService.getSpaceId(request); + const spaceId = spaces?.setup.spacesService.getSpaceId(request); const didCreateIndexPattern = await createStaticIndexPattern( setup, - context, + config, savedObjectsClient, spaceId ); return { created: didCreateIndexPattern }; }, -})); +}); -export const dynamicIndexPatternRoute = createRoute({ +const dynamicIndexPatternRoute = createApmServerRoute({ endpoint: 'GET /api/apm/index_pattern/dynamic', options: { tags: ['access:apm'] }, - handler: async ({ context }) => { - const dynamicIndexPattern = await getDynamicIndexPattern({ context }); + handler: async ({ context, config, logger }) => { + const dynamicIndexPattern = await getDynamicIndexPattern({ + context, + config, + logger, + }); return { dynamicIndexPattern }; }, }); -export const apmIndexPatternTitleRoute = createRoute({ +const indexPatternTitleRoute = createApmServerRoute({ endpoint: 'GET /api/apm/index_pattern/title', options: { tags: ['access:apm'] }, - handler: async ({ context }) => { + handler: async ({ config }) => { return { - indexPatternTitle: getApmIndexPatternTitle(context), + indexPatternTitle: getApmIndexPatternTitle(config), }; }, }); + +export const indexPatternRouteRepository = createApmServerRouteRepository() + .add(staticIndexPatternRoute) + .add(dynamicIndexPatternRoute) + .add(indexPatternTitleRoute); diff --git a/x-pack/plugins/apm/server/routes/metrics.ts b/x-pack/plugins/apm/server/routes/metrics.ts index c7e82e13d07b..9fa2346eb72f 100644 --- a/x-pack/plugins/apm/server/routes/metrics.ts +++ b/x-pack/plugins/apm/server/routes/metrics.ts @@ -8,10 +8,11 @@ import * as t from 'io-ts'; import { setupRequest } from '../lib/helpers/setup_request'; import { getMetricsChartDataByAgent } from '../lib/metrics/get_metrics_chart_data_by_agent'; -import { createRoute } from './create_route'; +import { createApmServerRoute } from './create_apm_server_route'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; import { environmentRt, kueryRt, rangeRt } from './default_api_types'; -export const metricsChartsRoute = createRoute({ +const metricsChartsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/metrics/charts', params: t.type({ path: t.type({ @@ -30,9 +31,9 @@ export const metricsChartsRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { params } = context; + handler: async (resources) => { + const { params } = resources; + const setup = await setupRequest(resources); const { serviceName } = params.path; const { agentName, environment, kuery, serviceNodeName } = params.query; return await getMetricsChartDataByAgent({ @@ -45,3 +46,7 @@ export const metricsChartsRoute = createRoute({ }); }, }); + +export const metricsRouteRepository = createApmServerRouteRepository().add( + metricsChartsRoute +); diff --git a/x-pack/plugins/apm/server/routes/observability_overview.ts b/x-pack/plugins/apm/server/routes/observability_overview.ts index 1aac2c09d01c..d459570cf733 100644 --- a/x-pack/plugins/apm/server/routes/observability_overview.ts +++ b/x-pack/plugins/apm/server/routes/observability_overview.ts @@ -10,30 +10,32 @@ import { setupRequest } from '../lib/helpers/setup_request'; import { getServiceCount } from '../lib/observability_overview/get_service_count'; import { getTransactionsPerMinute } from '../lib/observability_overview/get_transactions_per_minute'; import { getHasData } from '../lib/observability_overview/has_data'; -import { createRoute } from './create_route'; import { rangeRt } from './default_api_types'; import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; import { withApmSpan } from '../utils/with_apm_span'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; +import { createApmServerRoute } from './create_apm_server_route'; -export const observabilityOverviewHasDataRoute = createRoute({ +const observabilityOverviewHasDataRoute = createApmServerRoute({ endpoint: 'GET /api/apm/observability_overview/has_data', options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const res = await getHasData({ setup }); return { hasData: res }; }, }); -export const observabilityOverviewRoute = createRoute({ +const observabilityOverviewRoute = createApmServerRoute({ endpoint: 'GET /api/apm/observability_overview', params: t.type({ query: t.intersection([rangeRt, t.type({ bucketSize: t.string })]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { bucketSize } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { bucketSize } = resources.params.query; + const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup ); @@ -54,3 +56,7 @@ export const observabilityOverviewRoute = createRoute({ }); }, }); + +export const observabilityOverviewRouteRepository = createApmServerRouteRepository() + .add(observabilityOverviewRoute) + .add(observabilityOverviewHasDataRoute); diff --git a/x-pack/plugins/apm/server/routes/register_routes/index.test.ts b/x-pack/plugins/apm/server/routes/register_routes/index.test.ts new file mode 100644 index 000000000000..82b73d46da5c --- /dev/null +++ b/x-pack/plugins/apm/server/routes/register_routes/index.test.ts @@ -0,0 +1,507 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { jsonRt } from '@kbn/io-ts-utils'; +import { createServerRouteRepository } from '@kbn/server-route-repository'; +import { ServerRoute } from '@kbn/server-route-repository/target/typings'; +import * as t from 'io-ts'; +import { CoreSetup, Logger } from 'src/core/server'; +import { APMConfig } from '../..'; +import { APMRouteCreateOptions, APMRouteHandlerResources } from '../typings'; +import { registerRoutes } from './index'; + +type RegisterRouteDependencies = Parameters[0]; + +const getRegisterRouteDependencies = () => { + const get = jest.fn(); + const post = jest.fn(); + const put = jest.fn(); + const createRouter = jest.fn().mockReturnValue({ + get, + post, + put, + }); + + const coreSetup = ({ + http: { + createRouter, + }, + } as unknown) as CoreSetup; + + const logger = ({ + error: jest.fn(), + } as unknown) as Logger; + + return { + mocks: { + get, + post, + put, + createRouter, + coreSetup, + logger, + }, + dependencies: ({ + core: { + setup: coreSetup, + }, + logger, + config: {} as APMConfig, + plugins: {}, + } as unknown) as RegisterRouteDependencies, + }; +}; + +const getRepository = () => + createServerRouteRepository< + APMRouteHandlerResources, + APMRouteCreateOptions + >(); + +const initApi = ( + routes: Array< + ServerRoute< + any, + t.Any, + APMRouteHandlerResources, + any, + APMRouteCreateOptions + > + > +) => { + const { mocks, dependencies } = getRegisterRouteDependencies(); + + let repository = getRepository(); + + routes.forEach((route) => { + repository = repository.add(route); + }); + + registerRoutes({ + ...dependencies, + repository, + }); + + const responseMock = { + ok: jest.fn(), + custom: jest.fn(), + }; + + const simulateRequest = (request: { + method: 'get' | 'post' | 'put'; + pathname: string; + params?: Record; + body?: unknown; + query?: Record; + }) => { + const [, registeredRouteHandler] = + mocks[request.method].mock.calls.find((call) => { + return call[0].path === request.pathname; + }) ?? []; + + const result = registeredRouteHandler( + {}, + { + params: {}, + query: {}, + body: null, + ...request, + }, + responseMock + ); + + return result; + }; + + return { + simulateRequest, + mocks: { + ...mocks, + response: responseMock, + }, + }; +}; + +describe('createApi', () => { + it('registers a route with the server', () => { + const { + mocks: { createRouter, get, post, put }, + } = initApi([ + { + endpoint: 'GET /foo', + options: { tags: ['access:apm'] }, + handler: async () => ({}), + }, + { + endpoint: 'POST /bar', + params: t.type({ + body: t.string, + }), + options: { tags: ['access:apm'] }, + handler: async () => ({}), + }, + { + endpoint: 'PUT /baz', + options: { + tags: ['access:apm', 'access:apm_write'], + }, + handler: async () => ({}), + }, + { + endpoint: 'GET /qux', + options: { + tags: ['access:apm', 'access:apm_write'], + }, + handler: async () => ({}), + }, + ]); + + expect(createRouter).toHaveBeenCalledTimes(1); + + expect(get).toHaveBeenCalledTimes(2); + expect(post).toHaveBeenCalledTimes(1); + expect(put).toHaveBeenCalledTimes(1); + + expect(get.mock.calls[0][0]).toEqual({ + options: { + tags: ['access:apm'], + }, + path: '/foo', + validate: expect.anything(), + }); + + expect(get.mock.calls[1][0]).toEqual({ + options: { + tags: ['access:apm', 'access:apm_write'], + }, + path: '/qux', + validate: expect.anything(), + }); + + expect(post.mock.calls[0][0]).toEqual({ + options: { + tags: ['access:apm'], + }, + path: '/bar', + validate: expect.anything(), + }); + + expect(put.mock.calls[0][0]).toEqual({ + options: { + tags: ['access:apm', 'access:apm_write'], + }, + path: '/baz', + validate: expect.anything(), + }); + }); + + describe('when validating', () => { + describe('_inspect', () => { + it('allows _inspect=true', async () => { + const handlerMock = jest.fn(); + const { + simulateRequest, + mocks: { response }, + } = initApi([ + { + endpoint: 'GET /foo', + options: { + tags: [], + }, + handler: handlerMock, + }, + ]); + + await simulateRequest({ + method: 'get', + pathname: '/foo', + query: { _inspect: 'true' }, + }); + + // responds with ok + expect(response.custom).not.toHaveBeenCalled(); + + const params = handlerMock.mock.calls[0][0].params; + expect(params).toEqual({ query: { _inspect: true } }); + expect(handlerMock).toHaveBeenCalledTimes(1); + expect(response.ok).toHaveBeenCalledWith({ + body: { _inspect: [] }, + }); + }); + + it('rejects _inspect=1', async () => { + const handlerMock = jest.fn(); + + const { + simulateRequest, + mocks: { response }, + } = initApi([ + { + endpoint: 'GET /foo', + options: { + tags: [], + }, + handler: handlerMock, + }, + ]); + await simulateRequest({ + method: 'get', + pathname: '/foo', + query: { _inspect: 1 }, + }); + + // responds with error handler + expect(response.ok).not.toHaveBeenCalled(); + expect(response.custom).toHaveBeenCalledWith({ + body: { + attributes: { _inspect: [] }, + message: + 'Invalid value 1 supplied to : strict_keys/query: Partial<{| _inspect: pipe(JSON, boolean) |}>/_inspect: pipe(JSON, boolean)', + }, + statusCode: 400, + }); + }); + + it('allows omitting _inspect', async () => { + const handlerMock = jest.fn(); + + const { + simulateRequest, + mocks: { response }, + } = initApi([ + { endpoint: 'GET /foo', options: { tags: [] }, handler: handlerMock }, + ]); + await simulateRequest({ + method: 'get', + pathname: '/foo', + query: {}, + }); + + // responds with ok + expect(response.custom).not.toHaveBeenCalled(); + + const params = handlerMock.mock.calls[0][0].params; + expect(params).toEqual({ query: { _inspect: false } }); + expect(handlerMock).toHaveBeenCalledTimes(1); + + expect(response.ok).toHaveBeenCalledWith({ body: {} }); + }); + }); + + it('throws if unknown parameters are provided', async () => { + const { + simulateRequest, + mocks: { response }, + } = initApi([ + { endpoint: 'GET /foo', options: { tags: [] }, handler: jest.fn() }, + ]); + + await simulateRequest({ + method: 'get', + pathname: '/foo', + query: { _inspect: 'true', extra: '' }, + }); + + expect(response.custom).toHaveBeenCalledTimes(1); + + await simulateRequest({ + method: 'get', + pathname: '/foo', + body: { foo: 'bar' }, + }); + + expect(response.custom).toHaveBeenCalledTimes(2); + + await simulateRequest({ + method: 'get', + pathname: '/foo', + params: { + foo: 'bar', + }, + }); + + expect(response.custom).toHaveBeenCalledTimes(3); + }); + + it('validates path parameters', async () => { + const handlerMock = jest.fn(); + const { + simulateRequest, + mocks: { response }, + } = initApi([ + { + endpoint: 'GET /foo', + options: { tags: [] }, + params: t.type({ + path: t.type({ + foo: t.string, + }), + }), + handler: handlerMock, + }, + ]); + + await simulateRequest({ + method: 'get', + pathname: '/foo', + params: { + foo: 'bar', + }, + }); + + expect(handlerMock).toHaveBeenCalledTimes(1); + + expect(response.ok).toHaveBeenCalledTimes(1); + expect(response.custom).not.toHaveBeenCalled(); + + const params = handlerMock.mock.calls[0][0].params; + + expect(params).toEqual({ + path: { + foo: 'bar', + }, + query: { + _inspect: false, + }, + }); + + await simulateRequest({ + method: 'get', + pathname: '/foo', + params: { + bar: 'foo', + }, + }); + + expect(response.custom).toHaveBeenCalledTimes(1); + + await simulateRequest({ + method: 'get', + pathname: '/foo', + params: { + foo: 9, + }, + }); + + expect(response.custom).toHaveBeenCalledTimes(2); + + await simulateRequest({ + method: 'get', + pathname: '/foo', + params: { + foo: 'bar', + extra: '', + }, + }); + + expect(response.custom).toHaveBeenCalledTimes(3); + }); + + it('validates body parameters', async () => { + const handlerMock = jest.fn(); + const { + simulateRequest, + mocks: { response }, + } = initApi([ + { + endpoint: 'GET /foo', + options: { + tags: [], + }, + params: t.type({ + body: t.string, + }), + handler: handlerMock, + }, + ]); + + await simulateRequest({ + method: 'get', + pathname: '/foo', + body: '', + }); + + expect(response.custom).not.toHaveBeenCalled(); + expect(handlerMock).toHaveBeenCalledTimes(1); + expect(response.ok).toHaveBeenCalledTimes(1); + + const params = handlerMock.mock.calls[0][0].params; + + expect(params).toEqual({ + body: '', + query: { + _inspect: false, + }, + }); + + await simulateRequest({ + method: 'get', + pathname: '/foo', + body: null, + }); + + expect(response.custom).toHaveBeenCalledTimes(1); + }); + + it('validates query parameters', async () => { + const handlerMock = jest.fn(); + const { + simulateRequest, + mocks: { response }, + } = initApi([ + { + endpoint: 'GET /foo', + options: { + tags: [], + }, + params: t.type({ + query: t.type({ + bar: t.string, + filterNames: jsonRt.pipe(t.array(t.string)), + }), + }), + handler: handlerMock, + }, + ]); + + await simulateRequest({ + method: 'get', + pathname: '/foo', + query: { + bar: '', + _inspect: 'true', + filterNames: JSON.stringify(['hostName', 'agentName']), + }, + }); + + expect(response.custom).not.toHaveBeenCalled(); + expect(handlerMock).toHaveBeenCalledTimes(1); + expect(response.ok).toHaveBeenCalledTimes(1); + + const params = handlerMock.mock.calls[0][0].params; + + expect(params).toEqual({ + query: { + bar: '', + _inspect: true, + filterNames: ['hostName', 'agentName'], + }, + }); + + await simulateRequest({ + method: 'get', + pathname: '/foo', + query: { + bar: '', + foo: '', + }, + }); + + expect(response.custom).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/x-pack/plugins/apm/server/routes/register_routes/index.ts b/x-pack/plugins/apm/server/routes/register_routes/index.ts new file mode 100644 index 000000000000..3a88a496b923 --- /dev/null +++ b/x-pack/plugins/apm/server/routes/register_routes/index.ts @@ -0,0 +1,143 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import Boom from '@hapi/boom'; +import * as t from 'io-ts'; +import { KibanaRequest, RouteRegistrar } from 'src/core/server'; +import { RequestAbortedError } from '@elastic/elasticsearch/lib/errors'; +import agent from 'elastic-apm-node'; +import { ServerRouteRepository } from '@kbn/server-route-repository'; +import { merge } from 'lodash'; +import { + decodeRequestParams, + parseEndpoint, + routeValidationObject, +} from '@kbn/server-route-repository'; +import { mergeRt, jsonRt } from '@kbn/io-ts-utils'; +import { pickKeys } from '../../../common/utils/pick_keys'; +import { APMRouteHandlerResources, InspectResponse } from '../typings'; +import type { ApmPluginRequestHandlerContext } from '../typings'; + +const inspectRt = t.exact( + t.partial({ + query: t.exact(t.partial({ _inspect: jsonRt.pipe(t.boolean) })), + }) +); + +export const inspectableEsQueriesMap = new WeakMap< + KibanaRequest, + InspectResponse +>(); + +export function registerRoutes({ + core, + repository, + plugins, + logger, + config, +}: { + core: APMRouteHandlerResources['core']; + plugins: APMRouteHandlerResources['plugins']; + logger: APMRouteHandlerResources['logger']; + repository: ServerRouteRepository; + config: APMRouteHandlerResources['config']; +}) { + const routes = repository.getRoutes(); + + const router = core.setup.http.createRouter(); + + routes.forEach((route) => { + const { params, endpoint, options, handler } = route; + + const { method, pathname } = parseEndpoint(endpoint); + + (router[method] as RouteRegistrar< + typeof method, + ApmPluginRequestHandlerContext + >)( + { + path: pathname, + options, + validate: routeValidationObject, + }, + async (context, request, response) => { + if (agent.isStarted()) { + agent.addLabels({ + plugin: 'apm', + }); + } + + // init debug queries + inspectableEsQueriesMap.set(request, []); + + try { + const runtimeType = params ? mergeRt(params, inspectRt) : inspectRt; + + const validatedParams = decodeRequestParams( + pickKeys(request, 'params', 'body', 'query'), + runtimeType + ); + + const data: Record | undefined | null = (await handler({ + request, + context, + config, + logger, + core, + plugins, + params: merge( + { + query: { + _inspect: false, + }, + }, + validatedParams + ), + })) as any; + + if (Array.isArray(data)) { + throw new Error('Return type cannot be an array'); + } + + const body = validatedParams.query?._inspect + ? { + ...data, + _inspect: inspectableEsQueriesMap.get(request), + } + : { ...data }; + + // cleanup + inspectableEsQueriesMap.delete(request); + + return response.ok({ body }); + } catch (error) { + logger.error(error); + const opts = { + statusCode: 500, + body: { + message: error.message, + attributes: { + _inspect: inspectableEsQueriesMap.get(request), + }, + }, + }; + + if (Boom.isBoom(error)) { + opts.statusCode = error.output.statusCode; + } + + if (error instanceof RequestAbortedError) { + opts.statusCode = 499; + opts.body.message = 'Client closed request'; + } + + return response.custom(opts); + } + } + ); + }); +} diff --git a/x-pack/plugins/apm/server/routes/rum_client.ts b/x-pack/plugins/apm/server/routes/rum_client.ts index 3156acb469a7..d7f91adc0d68 100644 --- a/x-pack/plugins/apm/server/routes/rum_client.ts +++ b/x-pack/plugins/apm/server/routes/rum_client.ts @@ -6,7 +6,7 @@ */ import * as t from 'io-ts'; -import { jsonRt } from '../../common/runtime_types/json_rt'; +import { jsonRt } from '@kbn/io-ts-utils'; import { LocalUIFilterName } from '../../common/ui_filter'; import { Setup, @@ -28,9 +28,10 @@ import { getLocalUIFilters } from '../lib/rum_client/ui_filters/local_ui_filters import { localUIFilterNames } from '../lib/rum_client/ui_filters/local_ui_filters/config'; import { getRumPageLoadTransactionsProjection } from '../projections/rum_page_load_transactions'; import { Projection } from '../projections/typings'; -import { createRoute } from './create_route'; +import { createApmServerRoute } from './create_apm_server_route'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; import { rangeRt } from './default_api_types'; -import { APMRequestHandlerContext } from './typings'; +import { APMRouteHandlerResources } from './typings'; export const percentileRangeRt = t.partial({ minPercentile: t.string, @@ -45,18 +46,18 @@ const uxQueryRt = t.intersection([ t.partial({ urlQuery: t.string, percentile: t.string }), ]); -export const rumClientMetricsRoute = createRoute({ +const rumClientMetricsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/rum/client-metrics', params: t.type({ query: uxQueryRt, }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const { query: { urlQuery, percentile }, - } = context.params; + } = resources.params; return getClientMetrics({ setup, @@ -66,18 +67,18 @@ export const rumClientMetricsRoute = createRoute({ }, }); -export const rumPageLoadDistributionRoute = createRoute({ +const rumPageLoadDistributionRoute = createApmServerRoute({ endpoint: 'GET /api/apm/rum-client/page-load-distribution', params: t.type({ query: t.intersection([uxQueryRt, percentileRangeRt]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const { query: { minPercentile, maxPercentile, urlQuery }, - } = context.params; + } = resources.params; const pageLoadDistribution = await getPageLoadDistribution({ setup, @@ -90,7 +91,7 @@ export const rumPageLoadDistributionRoute = createRoute({ }, }); -export const rumPageLoadDistBreakdownRoute = createRoute({ +const rumPageLoadDistBreakdownRoute = createApmServerRoute({ endpoint: 'GET /api/apm/rum-client/page-load-distribution/breakdown', params: t.type({ query: t.intersection([ @@ -100,12 +101,12 @@ export const rumPageLoadDistBreakdownRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const { query: { minPercentile, maxPercentile, breakdown, urlQuery }, - } = context.params; + } = resources.params; const pageLoadDistBreakdown = await getPageLoadDistBreakdown({ setup, @@ -119,18 +120,18 @@ export const rumPageLoadDistBreakdownRoute = createRoute({ }, }); -export const rumPageViewsTrendRoute = createRoute({ +const rumPageViewsTrendRoute = createApmServerRoute({ endpoint: 'GET /api/apm/rum-client/page-view-trends', params: t.type({ query: t.intersection([uxQueryRt, t.partial({ breakdowns: t.string })]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const { query: { breakdowns, urlQuery }, - } = context.params; + } = resources.params; return getPageViewTrends({ setup, @@ -140,32 +141,32 @@ export const rumPageViewsTrendRoute = createRoute({ }, }); -export const rumServicesRoute = createRoute({ +const rumServicesRoute = createApmServerRoute({ endpoint: 'GET /api/apm/rum-client/services', params: t.type({ query: t.intersection([uiFiltersRt, rangeRt]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const rumServices = await getRumServices({ setup }); return { rumServices }; }, }); -export const rumVisitorsBreakdownRoute = createRoute({ +const rumVisitorsBreakdownRoute = createApmServerRoute({ endpoint: 'GET /api/apm/rum-client/visitor-breakdown', params: t.type({ query: uxQueryRt, }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const { query: { urlQuery }, - } = context.params; + } = resources.params; return getVisitorBreakdown({ setup, @@ -174,18 +175,18 @@ export const rumVisitorsBreakdownRoute = createRoute({ }, }); -export const rumWebCoreVitals = createRoute({ +const rumWebCoreVitals = createApmServerRoute({ endpoint: 'GET /api/apm/rum-client/web-core-vitals', params: t.type({ query: uxQueryRt, }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const { query: { urlQuery, percentile }, - } = context.params; + } = resources.params; return getWebCoreVitals({ setup, @@ -195,18 +196,18 @@ export const rumWebCoreVitals = createRoute({ }, }); -export const rumLongTaskMetrics = createRoute({ +const rumLongTaskMetrics = createApmServerRoute({ endpoint: 'GET /api/apm/rum-client/long-task-metrics', params: t.type({ query: uxQueryRt, }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const { query: { urlQuery, percentile }, - } = context.params; + } = resources.params; return getLongTaskMetrics({ setup, @@ -216,24 +217,24 @@ export const rumLongTaskMetrics = createRoute({ }, }); -export const rumUrlSearch = createRoute({ +const rumUrlSearch = createApmServerRoute({ endpoint: 'GET /api/apm/rum-client/url-search', params: t.type({ query: uxQueryRt, }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const { query: { urlQuery, percentile }, - } = context.params; + } = resources.params; return getUrlSearch({ setup, urlQuery, percentile: Number(percentile) }); }, }); -export const rumJSErrors = createRoute({ +const rumJSErrors = createApmServerRoute({ endpoint: 'GET /api/apm/rum-client/js-errors', params: t.type({ query: t.intersection([ @@ -244,12 +245,12 @@ export const rumJSErrors = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const { query: { pageSize, pageIndex, urlQuery }, - } = context.params; + } = resources.params; return getJSErrors({ setup, @@ -260,14 +261,14 @@ export const rumJSErrors = createRoute({ }, }); -export const rumHasDataRoute = createRoute({ +const rumHasDataRoute = createApmServerRoute({ endpoint: 'GET /api/apm/observability_overview/has_rum_data', params: t.type({ query: t.intersection([uiFiltersRt, rangeRt]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); return await hasRumData({ setup }); }, }); @@ -309,21 +310,22 @@ function createLocalFiltersRoute< >; queryRt: TQueryRT; }) { - return createRoute({ + return createApmServerRoute({ endpoint, params: t.type({ query: t.intersection([localUiBaseQueryRt, queryRt]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const { uiFilters } = setup; - const { query } = context.params; + + const { query } = resources.params; const { filterNames } = query; const projection = await getProjection({ query, - context, + resources, setup, }); @@ -339,7 +341,7 @@ function createLocalFiltersRoute< }); } -export const rumOverviewLocalFiltersRoute = createLocalFiltersRoute({ +const rumOverviewLocalFiltersRoute = createLocalFiltersRoute({ endpoint: 'GET /api/apm/rum/local_filters', getProjection: async ({ setup }) => { return getRumPageLoadTransactionsProjection({ @@ -357,9 +359,23 @@ type GetProjection< > = ({ query, setup, - context, + resources, }: { query: t.TypeOf; setup: Setup & SetupTimeRange; - context: APMRequestHandlerContext; + resources: APMRouteHandlerResources; }) => Promise | TProjection; + +export const rumRouteRepository = createApmServerRouteRepository() + .add(rumClientMetricsRoute) + .add(rumPageLoadDistributionRoute) + .add(rumPageLoadDistBreakdownRoute) + .add(rumPageViewsTrendRoute) + .add(rumServicesRoute) + .add(rumVisitorsBreakdownRoute) + .add(rumWebCoreVitals) + .add(rumLongTaskMetrics) + .add(rumUrlSearch) + .add(rumJSErrors) + .add(rumHasDataRoute) + .add(rumOverviewLocalFiltersRoute); diff --git a/x-pack/plugins/apm/server/routes/service_map.ts b/x-pack/plugins/apm/server/routes/service_map.ts index 33943d6e05d0..267479de4c10 100644 --- a/x-pack/plugins/apm/server/routes/service_map.ts +++ b/x-pack/plugins/apm/server/routes/service_map.ts @@ -11,13 +11,14 @@ import { invalidLicenseMessage } from '../../common/service_map'; import { setupRequest } from '../lib/helpers/setup_request'; import { getServiceMap } from '../lib/service_map/get_service_map'; import { getServiceMapServiceNodeInfo } from '../lib/service_map/get_service_map_service_node_info'; -import { createRoute } from './create_route'; +import { createApmServerRoute } from './create_apm_server_route'; import { environmentRt, rangeRt } from './default_api_types'; import { notifyFeatureUsage } from '../feature'; import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; import { isActivePlatinumLicense } from '../../common/license_check'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; -export const serviceMapRoute = createRoute({ +const serviceMapRoute = createApmServerRoute({ endpoint: 'GET /api/apm/service-map', params: t.type({ query: t.intersection([ @@ -29,8 +30,9 @@ export const serviceMapRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - if (!context.config['xpack.apm.serviceMapEnabled']) { + handler: async (resources) => { + const { config, context, params, logger } = resources; + if (!config['xpack.apm.serviceMapEnabled']) { throw Boom.notFound(); } if (!isActivePlatinumLicense(context.licensing.license)) { @@ -42,11 +44,10 @@ export const serviceMapRoute = createRoute({ featureName: 'serviceMaps', }); - const logger = context.logger; - const setup = await setupRequest(context, request); + const setup = await setupRequest(resources); const { query: { serviceName, environment }, - } = context.params; + } = params; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup @@ -61,7 +62,7 @@ export const serviceMapRoute = createRoute({ }, }); -export const serviceMapServiceNodeRoute = createRoute({ +const serviceMapServiceNodeRoute = createApmServerRoute({ endpoint: 'GET /api/apm/service-map/service/{serviceName}', params: t.type({ path: t.type({ @@ -70,19 +71,21 @@ export const serviceMapServiceNodeRoute = createRoute({ query: t.intersection([environmentRt, rangeRt]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - if (!context.config['xpack.apm.serviceMapEnabled']) { + handler: async (resources) => { + const { config, context, params } = resources; + + if (!config['xpack.apm.serviceMapEnabled']) { throw Boom.notFound(); } if (!isActivePlatinumLicense(context.licensing.license)) { throw Boom.forbidden(invalidLicenseMessage); } - const setup = await setupRequest(context, request); + const setup = await setupRequest(resources); const { path: { serviceName }, query: { environment }, - } = context.params; + } = params; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup @@ -96,3 +99,7 @@ export const serviceMapServiceNodeRoute = createRoute({ }); }, }); + +export const serviceMapRouteRepository = createApmServerRouteRepository() + .add(serviceMapRoute) + .add(serviceMapServiceNodeRoute); diff --git a/x-pack/plugins/apm/server/routes/service_nodes.ts b/x-pack/plugins/apm/server/routes/service_nodes.ts index e9060688c63a..a2eb12662cbc 100644 --- a/x-pack/plugins/apm/server/routes/service_nodes.ts +++ b/x-pack/plugins/apm/server/routes/service_nodes.ts @@ -6,12 +6,13 @@ */ import * as t from 'io-ts'; -import { createRoute } from './create_route'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; +import { createApmServerRoute } from './create_apm_server_route'; import { setupRequest } from '../lib/helpers/setup_request'; import { getServiceNodes } from '../lib/service_nodes'; import { rangeRt, kueryRt } from './default_api_types'; -export const serviceNodesRoute = createRoute({ +const serviceNodesRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/serviceNodes', params: t.type({ path: t.type({ @@ -20,9 +21,9 @@ export const serviceNodesRoute = createRoute({ query: t.intersection([kueryRt, rangeRt]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { params } = context; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; const { serviceName } = params.path; const { kuery } = params.query; @@ -30,3 +31,7 @@ export const serviceNodesRoute = createRoute({ return { serviceNodes }; }, }); + +export const serviceNodeRouteRepository = createApmServerRouteRepository().add( + serviceNodesRoute +); diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services.ts index b4d25ca8b2a0..800a5bdcc5d5 100644 --- a/x-pack/plugins/apm/server/routes/services.ts +++ b/x-pack/plugins/apm/server/routes/services.ts @@ -6,15 +6,12 @@ */ import Boom from '@hapi/boom'; +import { jsonRt } from '@kbn/io-ts-utils'; import * as t from 'io-ts'; import { uniq } from 'lodash'; -import { - LatencyAggregationType, - latencyAggregationTypeRt, -} from '../../common/latency_aggregation_types'; +import { latencyAggregationTypeRt } from '../../common/latency_aggregation_types'; import { ProfilingValueType } from '../../common/profiling'; import { isoToEpochRt } from '../../common/runtime_types/iso_to_epoch_rt'; -import { jsonRt } from '../../common/runtime_types/json_rt'; import { toNumberRt } from '../../common/runtime_types/to_number_rt'; import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; import { setupRequest } from '../lib/helpers/setup_request'; @@ -35,7 +32,8 @@ import { getServiceProfilingStatistics } from '../lib/services/profiling/get_ser import { getServiceProfilingTimeline } from '../lib/services/profiling/get_service_profiling_timeline'; import { offsetPreviousPeriodCoordinates } from '../utils/offset_previous_period_coordinate'; import { withApmSpan } from '../utils/with_apm_span'; -import { createRoute } from './create_route'; +import { createApmServerRoute } from './create_apm_server_route'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; import { comparisonRangeRt, environmentRt, @@ -43,15 +41,16 @@ import { rangeRt, } from './default_api_types'; -export const servicesRoute = createRoute({ +const servicesRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services', params: t.type({ query: t.intersection([environmentRt, kueryRt, rangeRt]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { environment, kuery } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params, logger } = resources; + const { environment, kuery } = params.query; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup ); @@ -61,21 +60,22 @@ export const servicesRoute = createRoute({ kuery, setup, searchAggregatedTransactions, - logger: context.logger, + logger, }); }, }); -export const serviceMetadataDetailsRoute = createRoute({ +const serviceMetadataDetailsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/metadata/details', params: t.type({ path: t.type({ serviceName: t.string }), query: rangeRt, }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.path; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup @@ -89,16 +89,17 @@ export const serviceMetadataDetailsRoute = createRoute({ }, }); -export const serviceMetadataIconsRoute = createRoute({ +const serviceMetadataIconsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/metadata/icons', params: t.type({ path: t.type({ serviceName: t.string }), query: rangeRt, }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.path; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup @@ -112,7 +113,7 @@ export const serviceMetadataIconsRoute = createRoute({ }, }); -export const serviceAgentNameRoute = createRoute({ +const serviceAgentNameRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/agent_name', params: t.type({ path: t.type({ @@ -121,9 +122,10 @@ export const serviceAgentNameRoute = createRoute({ query: rangeRt, }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.path; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup ); @@ -136,7 +138,7 @@ export const serviceAgentNameRoute = createRoute({ }, }); -export const serviceTransactionTypesRoute = createRoute({ +const serviceTransactionTypesRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/transaction_types', params: t.type({ path: t.type({ @@ -145,9 +147,11 @@ export const serviceTransactionTypesRoute = createRoute({ query: rangeRt, }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.path; + return getServiceTransactionTypes({ serviceName, setup, @@ -158,7 +162,7 @@ export const serviceTransactionTypesRoute = createRoute({ }, }); -export const serviceNodeMetadataRoute = createRoute({ +const serviceNodeMetadataRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/node/{serviceNodeName}/metadata', params: t.type({ @@ -169,10 +173,11 @@ export const serviceNodeMetadataRoute = createRoute({ query: t.intersection([kueryRt, rangeRt]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName, serviceNodeName } = context.params.path; - const { kuery } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName, serviceNodeName } = params.path; + const { kuery } = params.query; return getServiceNodeMetadata({ kuery, @@ -183,7 +188,7 @@ export const serviceNodeMetadataRoute = createRoute({ }, }); -export const serviceAnnotationsRoute = createRoute({ +const serviceAnnotationsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/annotation/search', params: t.type({ path: t.type({ @@ -192,12 +197,13 @@ export const serviceAnnotationsRoute = createRoute({ query: t.intersection([environmentRt, rangeRt]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; - const { environment } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params, plugins, context, request, logger } = resources; + const { serviceName } = params.path; + const { environment } = params.query; - const { observability } = context.plugins; + const { observability } = plugins; const [ annotationsClient, @@ -205,7 +211,7 @@ export const serviceAnnotationsRoute = createRoute({ ] = await Promise.all([ observability ? withApmSpan('get_scoped_annotations_client', () => - observability.getScopedAnnotationsClient(context, request) + observability.setup.getScopedAnnotationsClient(context, request) ) : undefined, getSearchAggregatedTransactions(setup), @@ -218,12 +224,12 @@ export const serviceAnnotationsRoute = createRoute({ serviceName, annotationsClient, client: context.core.elasticsearch.client.asCurrentUser, - logger: context.logger, + logger, }); }, }); -export const serviceAnnotationsCreateRoute = createRoute({ +const serviceAnnotationsCreateRoute = createApmServerRoute({ endpoint: 'POST /api/apm/services/{serviceName}/annotation', options: { tags: ['access:apm', 'access:apm_write'], @@ -250,12 +256,17 @@ export const serviceAnnotationsCreateRoute = createRoute({ }), ]), }), - handler: async ({ request, context }) => { - const { observability } = context.plugins; + handler: async (resources) => { + const { + request, + context, + plugins: { observability }, + params, + } = resources; const annotationsClient = observability ? await withApmSpan('get_scoped_annotations_client', () => - observability.getScopedAnnotationsClient(context, request) + observability.setup.getScopedAnnotationsClient(context, request) ) : undefined; @@ -263,7 +274,7 @@ export const serviceAnnotationsCreateRoute = createRoute({ throw Boom.notFound(); } - const { body, path } = context.params; + const { body, path } = params; return withApmSpan('create_annotation', () => annotationsClient.create({ @@ -283,7 +294,7 @@ export const serviceAnnotationsCreateRoute = createRoute({ }, }); -export const serviceErrorGroupsPrimaryStatisticsRoute = createRoute({ +const serviceErrorGroupsPrimaryStatisticsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/error_groups/primary_statistics', params: t.type({ @@ -300,13 +311,14 @@ export const serviceErrorGroupsPrimaryStatisticsRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; const { path: { serviceName }, query: { kuery, transactionType, environment }, - } = context.params; + } = params; return getServiceErrorGroupPrimaryStatistics({ kuery, serviceName, @@ -317,7 +329,7 @@ export const serviceErrorGroupsPrimaryStatisticsRoute = createRoute({ }, }); -export const serviceErrorGroupsComparisonStatisticsRoute = createRoute({ +const serviceErrorGroupsComparisonStatisticsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/error_groups/comparison_statistics', params: t.type({ @@ -337,8 +349,9 @@ export const serviceErrorGroupsComparisonStatisticsRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; const { path: { serviceName }, @@ -351,7 +364,7 @@ export const serviceErrorGroupsComparisonStatisticsRoute = createRoute({ comparisonStart, comparisonEnd, }, - } = context.params; + } = params; return getServiceErrorGroupPeriods({ environment, @@ -367,7 +380,7 @@ export const serviceErrorGroupsComparisonStatisticsRoute = createRoute({ }, }); -export const serviceThroughputRoute = createRoute({ +const serviceThroughputRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/throughput', params: t.type({ path: t.type({ @@ -382,16 +395,17 @@ export const serviceThroughputRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.path; const { environment, kuery, transactionType, comparisonStart, comparisonEnd, - } = context.params.query; + } = params.query; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup ); @@ -432,7 +446,7 @@ export const serviceThroughputRoute = createRoute({ }, }); -export const serviceInstancesPrimaryStatisticsRoute = createRoute({ +const serviceInstancesPrimaryStatisticsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/service_overview_instances/primary_statistics', params: t.type({ @@ -450,12 +464,16 @@ export const serviceInstancesPrimaryStatisticsRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; - const { environment, kuery, transactionType } = context.params.query; - const latencyAggregationType = (context.params.query - .latencyAggregationType as unknown) as LatencyAggregationType; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.path; + const { + environment, + kuery, + transactionType, + latencyAggregationType, + } = params.query; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup @@ -479,7 +497,7 @@ export const serviceInstancesPrimaryStatisticsRoute = createRoute({ }, }); -export const serviceInstancesComparisonStatisticsRoute = createRoute({ +const serviceInstancesComparisonStatisticsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/service_overview_instances/comparison_statistics', params: t.type({ @@ -500,9 +518,10 @@ export const serviceInstancesComparisonStatisticsRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.path; const { environment, kuery, @@ -511,9 +530,8 @@ export const serviceInstancesComparisonStatisticsRoute = createRoute({ comparisonEnd, serviceNodeIds, numBuckets, - } = context.params.query; - const latencyAggregationType = (context.params.query - .latencyAggregationType as unknown) as LatencyAggregationType; + latencyAggregationType, + } = params.query; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup @@ -535,7 +553,7 @@ export const serviceInstancesComparisonStatisticsRoute = createRoute({ }, }); -export const serviceDependenciesRoute = createRoute({ +const serviceDependenciesRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/dependencies', params: t.type({ path: t.type({ @@ -552,11 +570,11 @@ export const serviceDependenciesRoute = createRoute({ options: { tags: ['access:apm'], }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - - const { serviceName } = context.params.path; - const { environment, numBuckets } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.path; + const { environment, numBuckets } = params.query; const serviceDependencies = await getServiceDependencies({ serviceName, @@ -569,7 +587,7 @@ export const serviceDependenciesRoute = createRoute({ }, }); -export const serviceProfilingTimelineRoute = createRoute({ +const serviceProfilingTimelineRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/profiling/timeline', params: t.type({ path: t.type({ @@ -580,13 +598,13 @@ export const serviceProfilingTimelineRoute = createRoute({ options: { tags: ['access:apm'], }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; const { path: { serviceName }, query: { environment, kuery }, - } = context.params; + } = params; const profilingTimeline = await getServiceProfilingTimeline({ kuery, @@ -599,7 +617,7 @@ export const serviceProfilingTimelineRoute = createRoute({ }, }); -export const serviceProfilingStatisticsRoute = createRoute({ +const serviceProfilingStatisticsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/profiling/statistics', params: t.type({ path: t.type({ @@ -625,13 +643,15 @@ export const serviceProfilingStatisticsRoute = createRoute({ options: { tags: ['access:apm'], }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); + + const { params, logger } = resources; const { path: { serviceName }, query: { environment, kuery, valueType }, - } = context.params; + } = params; return getServiceProfilingStatistics({ kuery, @@ -639,7 +659,25 @@ export const serviceProfilingStatisticsRoute = createRoute({ environment, valueType, setup, - logger: context.logger, + logger, }); }, }); + +export const serviceRouteRepository = createApmServerRouteRepository() + .add(servicesRoute) + .add(serviceMetadataDetailsRoute) + .add(serviceMetadataIconsRoute) + .add(serviceAgentNameRoute) + .add(serviceTransactionTypesRoute) + .add(serviceNodeMetadataRoute) + .add(serviceAnnotationsRoute) + .add(serviceAnnotationsCreateRoute) + .add(serviceErrorGroupsPrimaryStatisticsRoute) + .add(serviceErrorGroupsComparisonStatisticsRoute) + .add(serviceThroughputRoute) + .add(serviceInstancesPrimaryStatisticsRoute) + .add(serviceInstancesComparisonStatisticsRoute) + .add(serviceDependenciesRoute) + .add(serviceProfilingTimelineRoute) + .add(serviceProfilingStatisticsRoute); diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration.ts index 31e8d6cc1e9f..111e0a18c860 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration.ts @@ -16,7 +16,7 @@ import { findExactConfiguration } from '../../lib/settings/agent_configuration/f import { listConfigurations } from '../../lib/settings/agent_configuration/list_configurations'; import { getEnvironments } from '../../lib/settings/agent_configuration/get_environments'; import { deleteConfiguration } from '../../lib/settings/agent_configuration/delete_configuration'; -import { createRoute } from '../create_route'; +import { createApmServerRoute } from '../create_apm_server_route'; import { getAgentNameByService } from '../../lib/settings/agent_configuration/get_agent_name_by_service'; import { markAppliedByAgent } from '../../lib/settings/agent_configuration/mark_applied_by_agent'; import { @@ -24,34 +24,37 @@ import { agentConfigurationIntakeRt, } from '../../../common/agent_configuration/runtime_types/agent_configuration_intake_rt'; import { getSearchAggregatedTransactions } from '../../lib/helpers/aggregated_transactions'; +import { createApmServerRouteRepository } from '../create_apm_server_route_repository'; // get list of configurations -export const agentConfigurationRoute = createRoute({ +const agentConfigurationRoute = createApmServerRoute({ endpoint: 'GET /api/apm/settings/agent-configuration', options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const configurations = await listConfigurations({ setup }); return { configurations }; }, }); // get a single configuration -export const getSingleAgentConfigurationRoute = createRoute({ +const getSingleAgentConfigurationRoute = createApmServerRoute({ endpoint: 'GET /api/apm/settings/agent-configuration/view', params: t.partial({ query: serviceRt, }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { name, environment } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params, logger } = resources; + + const { name, environment } = params.query; const service = { name, environment }; const config = await findExactConfiguration({ service, setup }); if (!config) { - context.logger.info( + logger.info( `Config was not found for ${service.name}/${service.environment}` ); @@ -63,7 +66,7 @@ export const getSingleAgentConfigurationRoute = createRoute({ }); // delete configuration -export const deleteAgentConfigurationRoute = createRoute({ +const deleteAgentConfigurationRoute = createApmServerRoute({ endpoint: 'DELETE /api/apm/settings/agent-configuration', options: { tags: ['access:apm', 'access:apm_write'], @@ -73,20 +76,22 @@ export const deleteAgentConfigurationRoute = createRoute({ service: serviceRt, }), }), - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { service } = context.params.body; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params, logger } = resources; + + const { service } = params.body; const config = await findExactConfiguration({ service, setup }); if (!config) { - context.logger.info( + logger.info( `Config was not found for ${service.name}/${service.environment}` ); throw Boom.notFound(); } - context.logger.info( + logger.info( `Deleting config ${service.name}/${service.environment} (${config._id})` ); @@ -98,7 +103,7 @@ export const deleteAgentConfigurationRoute = createRoute({ }); // create/update configuration -export const createOrUpdateAgentConfigurationRoute = createRoute({ +const createOrUpdateAgentConfigurationRoute = createApmServerRoute({ endpoint: 'PUT /api/apm/settings/agent-configuration', options: { tags: ['access:apm', 'access:apm_write'], @@ -107,9 +112,10 @@ export const createOrUpdateAgentConfigurationRoute = createRoute({ t.partial({ query: t.partial({ overwrite: toBooleanRt }) }), t.type({ body: agentConfigurationIntakeRt }), ]), - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { body, query } = context.params; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params, logger } = resources; + const { body, query } = params; // if the config already exists, it is fetched and updated // this is to avoid creating two configs with identical service params @@ -125,13 +131,13 @@ export const createOrUpdateAgentConfigurationRoute = createRoute({ ); } - context.logger.info( + logger.info( `${config ? 'Updating' : 'Creating'} config ${body.service.name}/${ body.service.environment }` ); - return await createOrUpdateConfiguration({ + await createOrUpdateConfiguration({ configurationId: config?._id, configurationIntake: body, setup, @@ -147,35 +153,35 @@ const searchParamsRt = t.intersection([ export type AgentConfigSearchParams = t.TypeOf; // Lookup single configuration (used by APM Server) -export const agentConfigurationSearchRoute = createRoute({ +const agentConfigurationSearchRoute = createApmServerRoute({ endpoint: 'POST /api/apm/settings/agent-configuration/search', params: t.type({ body: searchParamsRt, }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { + handler: async (resources) => { + const { params, logger } = resources; + const { service, etag, mark_as_applied_by_agent: markAsAppliedByAgent, - } = context.params.body; + } = params.body; - const setup = await setupRequest(context, request); + const setup = await setupRequest(resources); const config = await searchConfigurations({ service, setup, }); if (!config) { - context.logger.debug( + logger.debug( `[Central configuration] Config was not found for ${service.name}/${service.environment}` ); throw Boom.notFound(); } - context.logger.info( - `Config was found for ${service.name}/${service.environment}` - ); + logger.info(`Config was found for ${service.name}/${service.environment}`); // update `applied_by_agent` field // when `markAsAppliedByAgent` is true (Jaeger agent doesn't have etags) @@ -197,11 +203,11 @@ export const agentConfigurationSearchRoute = createRoute({ */ // get list of services -export const listAgentConfigurationServicesRoute = createRoute({ +const listAgentConfigurationServicesRoute = createApmServerRoute({ endpoint: 'GET /api/apm/settings/agent-configuration/services', options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup ); @@ -215,15 +221,17 @@ export const listAgentConfigurationServicesRoute = createRoute({ }); // get environments for service -export const listAgentConfigurationEnvironmentsRoute = createRoute({ +const listAgentConfigurationEnvironmentsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/settings/agent-configuration/environments', params: t.partial({ query: t.partial({ serviceName: t.string }), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + + const { serviceName } = params.query; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup ); @@ -239,16 +247,27 @@ export const listAgentConfigurationEnvironmentsRoute = createRoute({ }); // get agentName for service -export const agentConfigurationAgentNameRoute = createRoute({ +const agentConfigurationAgentNameRoute = createApmServerRoute({ endpoint: 'GET /api/apm/settings/agent-configuration/agent_name', params: t.type({ query: t.type({ serviceName: t.string }), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.query; const agentName = await getAgentNameByService({ serviceName, setup }); return { agentName }; }, }); + +export const agentConfigurationRouteRepository = createApmServerRouteRepository() + .add(agentConfigurationRoute) + .add(getSingleAgentConfigurationRoute) + .add(deleteAgentConfigurationRoute) + .add(createOrUpdateAgentConfigurationRoute) + .add(agentConfigurationSearchRoute) + .add(listAgentConfigurationServicesRoute) + .add(listAgentConfigurationEnvironmentsRoute) + .add(agentConfigurationAgentNameRoute); diff --git a/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts b/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts index de7f35c4081b..98467e1a4a0d 100644 --- a/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts +++ b/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts @@ -9,7 +9,7 @@ import * as t from 'io-ts'; import Boom from '@hapi/boom'; import { isActivePlatinumLicense } from '../../../common/license_check'; import { ML_ERRORS } from '../../../common/anomaly_detection'; -import { createRoute } from '../create_route'; +import { createApmServerRoute } from '../create_apm_server_route'; import { getAnomalyDetectionJobs } from '../../lib/anomaly_detection/get_anomaly_detection_jobs'; import { createAnomalyDetectionJobs } from '../../lib/anomaly_detection/create_anomaly_detection_jobs'; import { setupRequest } from '../../lib/helpers/setup_request'; @@ -18,15 +18,17 @@ import { hasLegacyJobs } from '../../lib/anomaly_detection/has_legacy_jobs'; import { getSearchAggregatedTransactions } from '../../lib/helpers/aggregated_transactions'; import { notifyFeatureUsage } from '../../feature'; import { withApmSpan } from '../../utils/with_apm_span'; +import { createApmServerRouteRepository } from '../create_apm_server_route_repository'; // get ML anomaly detection jobs for each environment -export const anomalyDetectionJobsRoute = createRoute({ +const anomalyDetectionJobsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/settings/anomaly-detection/jobs', options: { tags: ['access:apm', 'access:ml:canGetJobs'], }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); + const { context, logger } = resources; if (!isActivePlatinumLicense(context.licensing.license)) { throw Boom.forbidden(ML_ERRORS.INVALID_LICENSE); @@ -34,7 +36,7 @@ export const anomalyDetectionJobsRoute = createRoute({ const [jobs, legacyJobs] = await withApmSpan('get_available_ml_jobs', () => Promise.all([ - getAnomalyDetectionJobs(setup, context.logger), + getAnomalyDetectionJobs(setup, logger), hasLegacyJobs(setup), ]) ); @@ -47,7 +49,7 @@ export const anomalyDetectionJobsRoute = createRoute({ }); // create new ML anomaly detection jobs for each given environment -export const createAnomalyDetectionJobsRoute = createRoute({ +const createAnomalyDetectionJobsRoute = createApmServerRoute({ endpoint: 'POST /api/apm/settings/anomaly-detection/jobs', options: { tags: ['access:apm', 'access:apm_write', 'access:ml:canCreateJob'], @@ -57,15 +59,17 @@ export const createAnomalyDetectionJobsRoute = createRoute({ environments: t.array(t.string), }), }), - handler: async ({ context, request }) => { - const { environments } = context.params.body; - const setup = await setupRequest(context, request); + handler: async (resources) => { + const { params, context, logger } = resources; + const { environments } = params.body; + + const setup = await setupRequest(resources); if (!isActivePlatinumLicense(context.licensing.license)) { throw Boom.forbidden(ML_ERRORS.INVALID_LICENSE); } - await createAnomalyDetectionJobs(setup, environments, context.logger); + await createAnomalyDetectionJobs(setup, environments, logger); notifyFeatureUsage({ licensingPlugin: context.licensing, @@ -77,11 +81,11 @@ export const createAnomalyDetectionJobsRoute = createRoute({ }); // get all available environments to create anomaly detection jobs for -export const anomalyDetectionEnvironmentsRoute = createRoute({ +const anomalyDetectionEnvironmentsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/settings/anomaly-detection/environments', options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup @@ -96,3 +100,8 @@ export const anomalyDetectionEnvironmentsRoute = createRoute({ return { environments }; }, }); + +export const anomalyDetectionRouteRepository = createApmServerRouteRepository() + .add(anomalyDetectionJobsRoute) + .add(createAnomalyDetectionJobsRoute) + .add(anomalyDetectionEnvironmentsRoute); diff --git a/x-pack/plugins/apm/server/routes/settings/apm_indices.ts b/x-pack/plugins/apm/server/routes/settings/apm_indices.ts index 91057c97579e..003471aa89f3 100644 --- a/x-pack/plugins/apm/server/routes/settings/apm_indices.ts +++ b/x-pack/plugins/apm/server/routes/settings/apm_indices.ts @@ -6,7 +6,8 @@ */ import * as t from 'io-ts'; -import { createRoute } from '../create_route'; +import { createApmServerRouteRepository } from '../create_apm_server_route_repository'; +import { createApmServerRoute } from '../create_apm_server_route'; import { getApmIndices, getApmIndexSettings, @@ -14,29 +15,30 @@ import { import { saveApmIndices } from '../../lib/settings/apm_indices/save_apm_indices'; // get list of apm indices and values -export const apmIndexSettingsRoute = createRoute({ +const apmIndexSettingsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/settings/apm-index-settings', options: { tags: ['access:apm'] }, - handler: async ({ context }) => { - const apmIndexSettings = await getApmIndexSettings({ context }); + handler: async ({ config, context }) => { + const apmIndexSettings = await getApmIndexSettings({ config, context }); return { apmIndexSettings }; }, }); // get apm indices configuration object -export const apmIndicesRoute = createRoute({ +const apmIndicesRoute = createApmServerRoute({ endpoint: 'GET /api/apm/settings/apm-indices', options: { tags: ['access:apm'] }, - handler: async ({ context }) => { + handler: async (resources) => { + const { context, config } = resources; return await getApmIndices({ savedObjectsClient: context.core.savedObjects.client, - config: context.config, + config, }); }, }); // save ui indices -export const saveApmIndicesRoute = createRoute({ +const saveApmIndicesRoute = createApmServerRoute({ endpoint: 'POST /api/apm/settings/apm-indices/save', options: { tags: ['access:apm', 'access:apm_write'], @@ -53,9 +55,15 @@ export const saveApmIndicesRoute = createRoute({ /* eslint-enable @typescript-eslint/naming-convention */ }), }), - handler: async ({ context }) => { - const { body } = context.params; + handler: async (resources) => { + const { params, context } = resources; + const { body } = params; const savedObjectsClient = context.core.savedObjects.client; return await saveApmIndices(savedObjectsClient, body); }, }); + +export const apmIndicesRouteRepository = createApmServerRouteRepository() + .add(apmIndexSettingsRoute) + .add(apmIndicesRoute) + .add(saveApmIndicesRoute); diff --git a/x-pack/plugins/apm/server/routes/settings/custom_link.ts b/x-pack/plugins/apm/server/routes/settings/custom_link.ts index a6ab553f0941..c9c5d236c14f 100644 --- a/x-pack/plugins/apm/server/routes/settings/custom_link.ts +++ b/x-pack/plugins/apm/server/routes/settings/custom_link.ts @@ -21,35 +21,40 @@ import { import { deleteCustomLink } from '../../lib/settings/custom_link/delete_custom_link'; import { getTransaction } from '../../lib/settings/custom_link/get_transaction'; import { listCustomLinks } from '../../lib/settings/custom_link/list_custom_links'; -import { createRoute } from '../create_route'; +import { createApmServerRoute } from '../create_apm_server_route'; +import { createApmServerRouteRepository } from '../create_apm_server_route_repository'; -export const customLinkTransactionRoute = createRoute({ +const customLinkTransactionRoute = createApmServerRoute({ endpoint: 'GET /api/apm/settings/custom_links/transaction', options: { tags: ['access:apm'] }, params: t.partial({ query: filterOptionsRt, }), - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { query } = context.params; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { query } = params; // picks only the items listed in FILTER_OPTIONS const filters = pick(query, FILTER_OPTIONS); return await getTransaction({ setup, filters }); }, }); -export const listCustomLinksRoute = createRoute({ +const listCustomLinksRoute = createApmServerRoute({ endpoint: 'GET /api/apm/settings/custom_links', options: { tags: ['access:apm'] }, params: t.partial({ query: filterOptionsRt, }), - handler: async ({ context, request }) => { + handler: async (resources) => { + const { context, params } = resources; if (!isActiveGoldLicense(context.licensing.license)) { throw Boom.forbidden(INVALID_LICENSE); } - const setup = await setupRequest(context, request); - const { query } = context.params; + const setup = await setupRequest(resources); + + const { query } = params; + // picks only the items listed in FILTER_OPTIONS const filters = pick(query, FILTER_OPTIONS); const customLinks = await listCustomLinks({ setup, filters }); @@ -57,29 +62,30 @@ export const listCustomLinksRoute = createRoute({ }, }); -export const createCustomLinkRoute = createRoute({ +const createCustomLinkRoute = createApmServerRoute({ endpoint: 'POST /api/apm/settings/custom_links', params: t.type({ body: payloadRt, }), options: { tags: ['access:apm', 'access:apm_write'] }, - handler: async ({ context, request }) => { + handler: async (resources) => { + const { context, params } = resources; if (!isActiveGoldLicense(context.licensing.license)) { throw Boom.forbidden(INVALID_LICENSE); } - const setup = await setupRequest(context, request); - const customLink = context.params.body; - const res = await createOrUpdateCustomLink({ customLink, setup }); + const setup = await setupRequest(resources); + const customLink = params.body; notifyFeatureUsage({ licensingPlugin: context.licensing, featureName: 'customLinks', }); - return res; + + await createOrUpdateCustomLink({ customLink, setup }); }, }); -export const updateCustomLinkRoute = createRoute({ +const updateCustomLinkRoute = createApmServerRoute({ endpoint: 'PUT /api/apm/settings/custom_links/{id}', params: t.type({ path: t.type({ @@ -90,23 +96,26 @@ export const updateCustomLinkRoute = createRoute({ options: { tags: ['access:apm', 'access:apm_write'], }, - handler: async ({ context, request }) => { + handler: async (resources) => { + const { params, context } = resources; + if (!isActiveGoldLicense(context.licensing.license)) { throw Boom.forbidden(INVALID_LICENSE); } - const setup = await setupRequest(context, request); - const { id } = context.params.path; - const customLink = context.params.body; - const res = await createOrUpdateCustomLink({ + const setup = await setupRequest(resources); + + const { id } = params.path; + const customLink = params.body; + + await createOrUpdateCustomLink({ customLinkId: id, customLink, setup, }); - return res; }, }); -export const deleteCustomLinkRoute = createRoute({ +const deleteCustomLinkRoute = createApmServerRoute({ endpoint: 'DELETE /api/apm/settings/custom_links/{id}', params: t.type({ path: t.type({ @@ -116,12 +125,14 @@ export const deleteCustomLinkRoute = createRoute({ options: { tags: ['access:apm', 'access:apm_write'], }, - handler: async ({ context, request }) => { + handler: async (resources) => { + const { context, params } = resources; + if (!isActiveGoldLicense(context.licensing.license)) { throw Boom.forbidden(INVALID_LICENSE); } - const setup = await setupRequest(context, request); - const { id } = context.params.path; + const setup = await setupRequest(resources); + const { id } = params.path; const res = await deleteCustomLink({ customLinkId: id, setup, @@ -129,3 +140,10 @@ export const deleteCustomLinkRoute = createRoute({ return res; }, }); + +export const customLinkRouteRepository = createApmServerRouteRepository() + .add(customLinkTransactionRoute) + .add(listCustomLinksRoute) + .add(createCustomLinkRoute) + .add(updateCustomLinkRoute) + .add(deleteCustomLinkRoute); diff --git a/x-pack/plugins/apm/server/routes/traces.ts b/x-pack/plugins/apm/server/routes/traces.ts index 6287ffbf0c75..dd392982b02f 100644 --- a/x-pack/plugins/apm/server/routes/traces.ts +++ b/x-pack/plugins/apm/server/routes/traces.ts @@ -9,20 +9,22 @@ import * as t from 'io-ts'; import { setupRequest } from '../lib/helpers/setup_request'; import { getTrace } from '../lib/traces/get_trace'; import { getTransactionGroupList } from '../lib/transaction_groups'; -import { createRoute } from './create_route'; +import { createApmServerRoute } from './create_apm_server_route'; import { environmentRt, kueryRt, rangeRt } from './default_api_types'; import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; import { getRootTransactionByTraceId } from '../lib/transactions/get_transaction_by_trace'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; -export const tracesRoute = createRoute({ +const tracesRoute = createApmServerRoute({ endpoint: 'GET /api/apm/traces', params: t.type({ query: t.intersection([environmentRt, kueryRt, rangeRt]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { environment, kuery } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { environment, kuery } = params.query; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup ); @@ -34,7 +36,7 @@ export const tracesRoute = createRoute({ }, }); -export const tracesByIdRoute = createRoute({ +const tracesByIdRoute = createApmServerRoute({ endpoint: 'GET /api/apm/traces/{traceId}', params: t.type({ path: t.type({ @@ -43,13 +45,16 @@ export const tracesByIdRoute = createRoute({ query: rangeRt, }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - return getTrace(context.params.path.traceId, setup); + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + + const { traceId } = params.path; + return getTrace(traceId, setup); }, }); -export const rootTransactionByTraceIdRoute = createRoute({ +const rootTransactionByTraceIdRoute = createApmServerRoute({ endpoint: 'GET /api/apm/traces/{traceId}/root_transaction', params: t.type({ path: t.type({ @@ -57,9 +62,15 @@ export const rootTransactionByTraceIdRoute = createRoute({ }), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const { traceId } = context.params.path; - const setup = await setupRequest(context, request); + handler: async (resources) => { + const { params } = resources; + const { traceId } = params.path; + const setup = await setupRequest(resources); return getRootTransactionByTraceId(traceId, setup); }, }); + +export const traceRouteRepository = createApmServerRouteRepository() + .add(tracesByIdRoute) + .add(tracesRoute) + .add(rootTransactionByTraceIdRoute); diff --git a/x-pack/plugins/apm/server/routes/transactions.ts b/x-pack/plugins/apm/server/routes/transactions.ts index f3424a252e40..ebca374db86d 100644 --- a/x-pack/plugins/apm/server/routes/transactions.ts +++ b/x-pack/plugins/apm/server/routes/transactions.ts @@ -5,12 +5,12 @@ * 2.0. */ +import { jsonRt } from '@kbn/io-ts-utils'; import * as t from 'io-ts'; import { LatencyAggregationType, latencyAggregationTypeRt, } from '../../common/latency_aggregation_types'; -import { jsonRt } from '../../common/runtime_types/json_rt'; import { toNumberRt } from '../../common/runtime_types/to_number_rt'; import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; import { setupRequest } from '../lib/helpers/setup_request'; @@ -23,7 +23,8 @@ import { getLatencyPeriods } from '../lib/transactions/get_latency_charts'; import { getThroughputCharts } from '../lib/transactions/get_throughput_charts'; import { getTransactionGroupList } from '../lib/transaction_groups'; import { getErrorRatePeriods } from '../lib/transaction_groups/get_error_rate'; -import { createRoute } from './create_route'; +import { createApmServerRoute } from './create_apm_server_route'; +import { createApmServerRouteRepository } from './create_apm_server_route_repository'; import { comparisonRangeRt, environmentRt, @@ -35,7 +36,7 @@ import { * Returns a list of transactions grouped by name * //TODO: delete this once we moved away from the old table in the transaction overview page. It should be replaced by /transactions/groups/primary_statistics/ */ -export const transactionGroupsRoute = createRoute({ +const transactionGroupsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/transactions/groups', params: t.type({ path: t.type({ @@ -49,10 +50,11 @@ export const transactionGroupsRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; - const { environment, kuery, transactionType } = context.params.query; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.path; + const { environment, kuery, transactionType } = params.query; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup @@ -72,7 +74,7 @@ export const transactionGroupsRoute = createRoute({ }, }); -export const transactionGroupsPrimaryStatisticsRoute = createRoute({ +const transactionGroupsPrimaryStatisticsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/transactions/groups/primary_statistics', params: t.type({ @@ -90,8 +92,9 @@ export const transactionGroupsPrimaryStatisticsRoute = createRoute({ options: { tags: ['access:apm'], }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const { params } = resources; + const setup = await setupRequest(resources); const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup @@ -100,7 +103,7 @@ export const transactionGroupsPrimaryStatisticsRoute = createRoute({ const { path: { serviceName }, query: { environment, kuery, latencyAggregationType, transactionType }, - } = context.params; + } = params; return getServiceTransactionGroups({ environment, @@ -109,12 +112,12 @@ export const transactionGroupsPrimaryStatisticsRoute = createRoute({ serviceName, searchAggregatedTransactions, transactionType, - latencyAggregationType: latencyAggregationType as LatencyAggregationType, + latencyAggregationType, }); }, }); -export const transactionGroupsComparisonStatisticsRoute = createRoute({ +const transactionGroupsComparisonStatisticsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/transactions/groups/comparison_statistics', params: t.type({ @@ -135,13 +138,15 @@ export const transactionGroupsComparisonStatisticsRoute = createRoute({ options: { tags: ['access:apm'], }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); + handler: async (resources) => { + const setup = await setupRequest(resources); const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup ); + const { params } = resources; + const { path: { serviceName }, query: { @@ -154,7 +159,7 @@ export const transactionGroupsComparisonStatisticsRoute = createRoute({ comparisonStart, comparisonEnd, }, - } = context.params; + } = params; return await getServiceTransactionGroupComparisonStatisticsPeriods({ environment, @@ -165,14 +170,14 @@ export const transactionGroupsComparisonStatisticsRoute = createRoute({ searchAggregatedTransactions, transactionType, numBuckets, - latencyAggregationType: latencyAggregationType as LatencyAggregationType, + latencyAggregationType, comparisonStart, comparisonEnd, }); }, }); -export const transactionLatencyChartsRoute = createRoute({ +const transactionLatencyChartsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/transactions/charts/latency', params: t.type({ path: t.type({ @@ -188,10 +193,11 @@ export const transactionLatencyChartsRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const logger = context.logger; - const { serviceName } = context.params.path; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params, logger } = resources; + + const { serviceName } = params.path; const { environment, kuery, @@ -200,7 +206,7 @@ export const transactionLatencyChartsRoute = createRoute({ latencyAggregationType, comparisonStart, comparisonEnd, - } = context.params.query; + } = params.query; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup @@ -242,7 +248,7 @@ export const transactionLatencyChartsRoute = createRoute({ }, }); -export const transactionThroughputChartsRoute = createRoute({ +const transactionThroughputChartsRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/transactions/charts/throughput', params: t.type({ @@ -258,15 +264,17 @@ export const transactionThroughputChartsRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + + const { serviceName } = params.path; const { environment, kuery, transactionType, transactionName, - } = context.params.query; + } = params.query; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup @@ -284,7 +292,7 @@ export const transactionThroughputChartsRoute = createRoute({ }, }); -export const transactionChartsDistributionRoute = createRoute({ +const transactionChartsDistributionRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/transactions/charts/distribution', params: t.type({ @@ -306,9 +314,10 @@ export const transactionChartsDistributionRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.path; const { environment, kuery, @@ -316,7 +325,7 @@ export const transactionChartsDistributionRoute = createRoute({ transactionName, transactionId = '', traceId = '', - } = context.params.query; + } = params.query; const searchAggregatedTransactions = await getSearchAggregatedTransactions( setup @@ -336,7 +345,7 @@ export const transactionChartsDistributionRoute = createRoute({ }, }); -export const transactionChartsBreakdownRoute = createRoute({ +const transactionChartsBreakdownRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/transaction/charts/breakdown', params: t.type({ path: t.type({ @@ -351,15 +360,17 @@ export const transactionChartsBreakdownRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; + handler: async (resources) => { + const setup = await setupRequest(resources); + const { params } = resources; + + const { serviceName } = params.path; const { environment, kuery, transactionName, transactionType, - } = context.params.query; + } = params.query; return getTransactionBreakdown({ environment, @@ -372,7 +383,7 @@ export const transactionChartsBreakdownRoute = createRoute({ }, }); -export const transactionChartsErrorRateRoute = createRoute({ +const transactionChartsErrorRateRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services/{serviceName}/transactions/charts/error_rate', params: t.type({ @@ -386,9 +397,10 @@ export const transactionChartsErrorRateRoute = createRoute({ ]), }), options: { tags: ['access:apm'] }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { params } = context; + handler: async (resources) => { + const setup = await setupRequest(resources); + + const { params } = resources; const { serviceName } = params.path; const { environment, @@ -416,3 +428,13 @@ export const transactionChartsErrorRateRoute = createRoute({ }); }, }); + +export const transactionRouteRepository = createApmServerRouteRepository() + .add(transactionGroupsRoute) + .add(transactionGroupsPrimaryStatisticsRoute) + .add(transactionGroupsComparisonStatisticsRoute) + .add(transactionLatencyChartsRoute) + .add(transactionThroughputChartsRoute) + .add(transactionChartsDistributionRoute) + .add(transactionChartsBreakdownRoute) + .add(transactionChartsErrorRateRoute); diff --git a/x-pack/plugins/apm/server/routes/typings.ts b/x-pack/plugins/apm/server/routes/typings.ts index 3ba24b4ed526..0fec88a4326c 100644 --- a/x-pack/plugins/apm/server/routes/typings.ts +++ b/x-pack/plugins/apm/server/routes/typings.ts @@ -5,27 +5,19 @@ * 2.0. */ -import t, { Encode, Encoder } from 'io-ts'; import { CoreSetup, - KibanaRequest, RequestHandlerContext, Logger, + KibanaRequest, + CoreStart, } from 'src/core/server'; -import { Observable } from 'rxjs'; -import { RequiredKeys, DeepPartial } from 'utility-types'; -import { SpacesPluginStart } from '../../../spaces/server'; -import { ObservabilityPluginSetup } from '../../../observability/server'; import { LicensingApiRequestHandlerContext } from '../../../licensing/server'; -import { SecurityPluginSetup } from '../../../security/server'; -import { MlPluginSetup } from '../../../ml/server'; -import { FetchOptions } from '../../common/fetch_options'; import { APMConfig } from '..'; +import { APMPluginDependencies } from '../types'; -export type HandlerReturn = Record; - -interface InspectQueryParam { - query: { _inspect: boolean }; +export interface ApmPluginRequestHandlerContext extends RequestHandlerContext { + licensing: LicensingApiRequestHandlerContext; } export type InspectResponse = Array<{ @@ -36,141 +28,53 @@ export type InspectResponse = Array<{ esError: Error; }>; -export interface RouteParams { - path?: Record; - query?: Record; - body?: any; +export interface APMRouteCreateOptions { + options: { + tags: Array< + | 'access:apm' + | 'access:apm_write' + | 'access:ml:canGetJobs' + | 'access:ml:canCreateJob' + >; + }; } -type WithoutIncompatibleMethods = Omit< - T, - 'encode' | 'asEncoder' -> & { encode: Encode; asEncoder: () => Encoder }; - -export type RouteParamsRT = WithoutIncompatibleMethods>; - -export type RouteHandler< - TParamsRT extends RouteParamsRT | undefined, - TReturn extends HandlerReturn -> = (kibanaContext: { - context: APMRequestHandlerContext< - (TParamsRT extends RouteParamsRT ? t.TypeOf : {}) & - InspectQueryParam - >; +export interface APMRouteHandlerResources { request: KibanaRequest; -}) => Promise; - -interface RouteOptions { - tags: Array< - | 'access:apm' - | 'access:apm_write' - | 'access:ml:canGetJobs' - | 'access:ml:canCreateJob' - >; -} - -export interface Route< - TEndpoint extends string, - TRouteParamsRT extends RouteParamsRT | undefined, - TReturn extends HandlerReturn -> { - endpoint: TEndpoint; - options: RouteOptions; - params?: TRouteParamsRT; - handler: RouteHandler; -} - -/** - * @internal - */ -export interface ApmPluginRequestHandlerContext extends RequestHandlerContext { - licensing: LicensingApiRequestHandlerContext; -} - -export type APMRequestHandlerContext< - TRouteParams = {} -> = ApmPluginRequestHandlerContext & { - params: TRouteParams & InspectQueryParam; + context: ApmPluginRequestHandlerContext; + params: { + query: { + _inspect: boolean; + }; + }; config: APMConfig; logger: Logger; - plugins: { - spaces?: SpacesPluginStart; - observability?: ObservabilityPluginSetup; - security?: SecurityPluginSetup; - ml?: MlPluginSetup; + core: { + setup: CoreSetup; + start: () => Promise; }; -}; - -export interface RouteState { - [endpoint: string]: { - params?: RouteParams; - ret: any; + plugins: { + [key in keyof APMPluginDependencies]: { + setup: Required[key]['setup']; + start: () => Promise[key]['start']>; + }; }; } -export interface ServerAPI { - _S: TRouteState; - add< - TEndpoint extends string, - TReturn extends HandlerReturn, - TRouteParamsRT extends RouteParamsRT | undefined = undefined - >( - route: - | Route - | ((core: CoreSetup) => Route) - ): ServerAPI< - TRouteState & - { - [key in TEndpoint]: { - params: TRouteParamsRT; - ret: TReturn & { _inspect?: InspectResponse }; - }; - } - >; - init: ( - core: CoreSetup, - context: { - config$: Observable; - logger: Logger; - plugins: { - observability?: ObservabilityPluginSetup; - security?: SecurityPluginSetup; - ml?: MlPluginSetup; - }; - } - ) => void; -} - -type MaybeOptional }> = RequiredKeys< - T['params'] -> extends never - ? { params?: T['params'] } - : { params: T['params'] }; - -export type MaybeParams< - TRouteState, - TEndpoint extends keyof TRouteState & string -> = TRouteState[TEndpoint] extends { params: t.Any } - ? MaybeOptional<{ - params: t.OutputOf & - DeepPartial; - }> - : {}; - -export type Client< - TRouteState, - TOptions extends { abortable: boolean } = { abortable: true } -> = ( - options: Omit< - FetchOptions, - 'query' | 'body' | 'pathname' | 'method' | 'signal' - > & { - forceCache?: boolean; - endpoint: TEndpoint; - } & MaybeParams & - (TOptions extends { abortable: true } ? { signal: AbortSignal | null } : {}) -) => Promise< - TRouteState[TEndpoint] extends { ret: any } - ? TRouteState[TEndpoint]['ret'] - : unknown ->; +// export type Client< +// TRouteState, +// TOptions extends { abortable: boolean } = { abortable: true } +// > = ( +// options: Omit< +// FetchOptions, +// 'query' | 'body' | 'pathname' | 'method' | 'signal' +// > & { +// forceCache?: boolean; +// endpoint: TEndpoint; +// } & MaybeParams & +// (TOptions extends { abortable: true } ? { signal: AbortSignal | null } : {}) +// ) => Promise< +// TRouteState[TEndpoint] extends { ret: any } +// ? TRouteState[TEndpoint]['ret'] +// : unknown +// >; diff --git a/x-pack/plugins/apm/server/types.ts b/x-pack/plugins/apm/server/types.ts new file mode 100644 index 000000000000..cef9eaf2f4fc --- /dev/null +++ b/x-pack/plugins/apm/server/types.ts @@ -0,0 +1,164 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { ValuesType } from 'utility-types'; +import { Observable } from 'rxjs'; +import { CoreSetup, CoreStart, KibanaRequest } from 'kibana/server'; +import { + PluginSetup as DataPluginSetup, + PluginStart as DataPluginStart, +} from '../../../../src/plugins/data/server'; +import { SpacesPluginSetup, SpacesPluginStart } from '../../spaces/server'; +import { APMOSSPluginSetup } from '../../../../src/plugins/apm_oss/server'; +import { + HomeServerPluginSetup, + HomeServerPluginStart, +} from '../../../../src/plugins/home/server'; +import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; +import { ActionsPlugin } from '../../actions/server'; +import { AlertingPlugin } from '../../alerting/server'; +import { CloudSetup } from '../../cloud/server'; +import { + PluginSetupContract as FeaturesPluginSetup, + PluginStartContract as FeaturesPluginStart, +} from '../../features/server'; +import { + LicensingPluginSetup, + LicensingPluginStart, +} from '../../licensing/server'; +import { MlPluginSetup, MlPluginStart } from '../../ml/server'; +import { ObservabilityPluginSetup } from '../../observability/server'; +import { + SecurityPluginSetup, + SecurityPluginStart, +} from '../../security/server'; +import { + TaskManagerSetupContract, + TaskManagerStartContract, +} from '../../task_manager/server'; +import { APMConfig } from '.'; +import { getApmIndices } from './lib/settings/apm_indices/get_apm_indices'; +import { createApmEventClient } from './lib/helpers/create_es_client/create_apm_event_client'; +import { ApmPluginRequestHandlerContext } from './routes/typings'; + +export interface APMPluginSetup { + config$: Observable; + getApmIndices: () => ReturnType; + createApmEventClient: (params: { + debug?: boolean; + request: KibanaRequest; + context: ApmPluginRequestHandlerContext; + }) => Promise>; +} + +interface DependencyMap { + core: { + setup: CoreSetup; + start: CoreStart; + }; + spaces: { + setup: SpacesPluginSetup; + start: SpacesPluginStart; + }; + apmOss: { + setup: APMOSSPluginSetup; + start: undefined; + }; + home: { + setup: HomeServerPluginSetup; + start: HomeServerPluginStart; + }; + licensing: { + setup: LicensingPluginSetup; + start: LicensingPluginStart; + }; + cloud: { + setup: CloudSetup; + start: undefined; + }; + usageCollection: { + setup: UsageCollectionSetup; + start: undefined; + }; + taskManager: { + setup: TaskManagerSetupContract; + start: TaskManagerStartContract; + }; + alerting: { + setup: AlertingPlugin['setup']; + start: AlertingPlugin['start']; + }; + actions: { + setup: ActionsPlugin['setup']; + start: ActionsPlugin['start']; + }; + observability: { + setup: ObservabilityPluginSetup; + start: undefined; + }; + features: { + setup: FeaturesPluginSetup; + start: FeaturesPluginStart; + }; + security: { + setup: SecurityPluginSetup; + start: SecurityPluginStart; + }; + ml: { + setup: MlPluginSetup; + start: MlPluginStart; + }; + data: { + setup: DataPluginSetup; + start: DataPluginStart; + }; +} + +const requiredDependencies = [ + 'features', + 'apmOss', + 'data', + 'licensing', + 'triggersActionsUi', + 'embeddable', + 'infra', +] as const; + +const optionalDependencies = [ + 'spaces', + 'cloud', + 'usageCollection', + 'taskManager', + 'actions', + 'alerting', + 'observability', + 'security', + 'ml', + 'home', + 'maps', +] as const; + +type RequiredDependencies = Pick< + DependencyMap, + ValuesType & keyof DependencyMap +>; + +type OptionalDependencies = Partial< + Pick< + DependencyMap, + ValuesType & keyof DependencyMap + > +>; + +export type APMPluginDependencies = RequiredDependencies & OptionalDependencies; + +export type APMPluginSetupDependencies = { + [key in keyof APMPluginDependencies]: Required[key]['setup']; +}; + +export type APMPluginStartDependencies = { + [key in keyof APMPluginDependencies]: Required[key]['start']; +}; diff --git a/x-pack/test/apm_api_integration/common/apm_api_supertest.ts b/x-pack/test/apm_api_integration/common/apm_api_supertest.ts index 542982778dff..ed104a6fdf06 100644 --- a/x-pack/test/apm_api_integration/common/apm_api_supertest.ts +++ b/x-pack/test/apm_api_integration/common/apm_api_supertest.ts @@ -8,24 +8,25 @@ import { format } from 'url'; import supertest from 'supertest'; import request from 'superagent'; -import { MaybeParams } from '../../../plugins/apm/server/routes/typings'; import { parseEndpoint } from '../../../plugins/apm/common/apm_api/parse_endpoint'; -import { APMAPI } from '../../../plugins/apm/server/routes/create_apm_api'; -import type { APIReturnType } from '../../../plugins/apm/public/services/rest/createCallApmApi'; +import type { + APIReturnType, + APIEndpoint, + APIClientRequestParamsOf, +} from '../../../plugins/apm/public/services/rest/createCallApmApi'; export function createApmApiSupertest(st: supertest.SuperTest) { - return async ( + return async ( options: { - endpoint: TPath; - } & MaybeParams + endpoint: TEndpoint; + } & APIClientRequestParamsOf & { params?: { query?: { _inspect?: boolean } } } ): Promise<{ status: number; - body: APIReturnType; + body: APIReturnType; }> => { const { endpoint } = options; - // @ts-expect-error - const params = 'params' in options ? options.params : {}; + const params = 'params' in options ? (options.params as Record) : {}; const { method, pathname } = parseEndpoint(endpoint, params?.path); const url = format({ pathname, query: params?.query }); diff --git a/x-pack/test/apm_api_integration/tests/inspect/inspect.ts b/x-pack/test/apm_api_integration/tests/inspect/inspect.ts index aae2e38e8ec8..4f65808de820 100644 --- a/x-pack/test/apm_api_integration/tests/inspect/inspect.ts +++ b/x-pack/test/apm_api_integration/tests/inspect/inspect.ts @@ -81,7 +81,6 @@ export default function customLinksTests({ getService }: FtrProviderContext) { it('for agent configs', async () => { const { status, body } = await supertestRead({ endpoint: 'GET /api/apm/settings/agent-configuration', - // @ts-expect-error params: { query: { _inspect: true, diff --git a/x-pack/test/apm_api_integration/tests/service_overview/instances_primary_statistics.ts b/x-pack/test/apm_api_integration/tests/service_overview/instances_primary_statistics.ts index aac92685a3c3..baa95eb56a12 100644 --- a/x-pack/test/apm_api_integration/tests/service_overview/instances_primary_statistics.ts +++ b/x-pack/test/apm_api_integration/tests/service_overview/instances_primary_statistics.ts @@ -13,6 +13,7 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; import archives from '../../common/fixtures/es_archiver/archives_metadata'; import { registry } from '../../common/registry'; import { createApmApiSupertest } from '../../common/apm_api_supertest'; +import { LatencyAggregationType } from '../../../../plugins/apm/common/latency_aggregation_types'; export default function ApiTest({ getService }: FtrProviderContext) { const apmApiSupertest = createApmApiSupertest(getService('supertest')); @@ -31,7 +32,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { params: { path: { serviceName: 'opbeans-java' }, query: { - latencyAggregationType: 'avg', + latencyAggregationType: LatencyAggregationType.avg, start, end, transactionType: 'request', @@ -61,7 +62,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { params: { path: { serviceName: 'opbeans-java' }, query: { - latencyAggregationType: 'avg', + latencyAggregationType: LatencyAggregationType.avg, start, end, transactionType: 'request', @@ -130,7 +131,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { params: { path: { serviceName: 'opbeans-ruby' }, query: { - latencyAggregationType: 'avg', + latencyAggregationType: LatencyAggregationType.avg, start, end, transactionType: 'request', diff --git a/yarn.lock b/yarn.lock index 546fe439f56d..e1118cf0b74f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2680,6 +2680,10 @@ version "0.0.0" uid "" +"@kbn/io-ts-utils@link:packages/kbn-io-ts-utils": + version "0.0.0" + uid "" + "@kbn/legacy-logging@link:packages/kbn-legacy-logging": version "0.0.0" uid "" @@ -2712,6 +2716,10 @@ version "0.0.0" uid "" +"@kbn/server-route-repository@link:packages/kbn-server-route-repository": + version "0.0.0" + uid "" + "@kbn/std@link:packages/kbn-std": version "0.0.0" uid "" From 92da416341fa8377da893c44e16740e4a5f4c1d5 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Thu, 8 Apr 2021 16:04:30 +0200 Subject: [PATCH 21/49] Don't trigger auto-refresh until previous refresh completes (#93410) (#96547) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- ...n-plugins-data-public.autorefreshdonefn.md | 11 + .../kibana-plugin-plugins-data-public.md | 3 + ...a-public.waituntilnextsessioncompletes_.md | 25 +++ ...ic.waituntilnextsessioncompletesoptions.md | 20 ++ ...nextsessioncompletesoptions.waitforidle.md | 13 ++ .../public/application/dashboard_app.tsx | 24 +- src/plugins/data/README.mdx | 159 ++++++++------ src/plugins/data/public/index.ts | 3 + src/plugins/data/public/public.api.md | 47 ++-- .../data/public/query/timefilter/index.ts | 2 +- .../timefilter/lib/auto_refresh_loop.test.ts | 205 ++++++++++++++++++ .../query/timefilter/lib/auto_refresh_loop.ts | 80 +++++++ .../query/timefilter/timefilter.test.ts | 45 +++- .../public/query/timefilter/timefilter.ts | 30 +-- .../timefilter/timefilter_service.mock.ts | 2 +- src/plugins/data/public/search/index.ts | 2 + .../data/public/search/session/index.ts | 4 + .../search/session/session_helpers.test.ts | 88 ++++++++ .../public/search/session/session_helpers.ts | 48 ++++ .../public/application/angular/discover.js | 26 ++- src/plugins/expressions/public/loader.ts | 7 +- .../public/embeddable/visualize_embeddable.ts | 8 +- .../components/visualize_top_nav.tsx | 8 +- .../lens/public/app_plugin/app.test.tsx | 6 +- x-pack/plugins/lens/public/app_plugin/app.tsx | 15 +- 25 files changed, 755 insertions(+), 126 deletions(-) create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.autorefreshdonefn.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.waituntilnextsessioncompletes_.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.waitforidle.md create mode 100644 src/plugins/data/public/query/timefilter/lib/auto_refresh_loop.test.ts create mode 100644 src/plugins/data/public/query/timefilter/lib/auto_refresh_loop.ts create mode 100644 src/plugins/data/public/search/session/session_helpers.test.ts create mode 100644 src/plugins/data/public/search/session/session_helpers.ts diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.autorefreshdonefn.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.autorefreshdonefn.md new file mode 100644 index 000000000000..a5694ea2d1af --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.autorefreshdonefn.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [AutoRefreshDoneFn](./kibana-plugin-plugins-data-public.autorefreshdonefn.md) + +## AutoRefreshDoneFn type + +Signature: + +```typescript +export declare type AutoRefreshDoneFn = () => void; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md index d2e7ef9db05e..4429f45f5564 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md @@ -47,6 +47,7 @@ | [getSearchParamsFromRequest(searchRequest, dependencies)](./kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md) | | | [getTime(indexPattern, timeRange, options)](./kibana-plugin-plugins-data-public.gettime.md) | | | [plugin(initializerContext)](./kibana-plugin-plugins-data-public.plugin.md) | | +| [waitUntilNextSessionCompletes$(sessionService, { waitForIdle })](./kibana-plugin-plugins-data-public.waituntilnextsessioncompletes_.md) | Creates an observable that emits when next search session completes. This utility is helpful to use in the application to delay some tasks until next session completes. | ## Interfaces @@ -92,6 +93,7 @@ | [SearchInterceptorDeps](./kibana-plugin-plugins-data-public.searchinterceptordeps.md) | | | [SearchSessionInfoProvider](./kibana-plugin-plugins-data-public.searchsessioninfoprovider.md) | Provide info about current search session to be stored in the Search Session saved object | | [SearchSourceFields](./kibana-plugin-plugins-data-public.searchsourcefields.md) | search source fields | +| [WaitUntilNextSessionCompletesOptions](./kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.md) | Options for [waitUntilNextSessionCompletes$()](./kibana-plugin-plugins-data-public.waituntilnextsessioncompletes_.md) | ## Variables @@ -141,6 +143,7 @@ | [AggParam](./kibana-plugin-plugins-data-public.aggparam.md) | | | [AggsStart](./kibana-plugin-plugins-data-public.aggsstart.md) | AggsStart represents the actual external contract as AggsCommonStart is only used internally. The difference is that AggsStart includes the typings for the registry with initialized agg types. | | [AutocompleteStart](./kibana-plugin-plugins-data-public.autocompletestart.md) | \* | +| [AutoRefreshDoneFn](./kibana-plugin-plugins-data-public.autorefreshdonefn.md) | | | [CustomFilter](./kibana-plugin-plugins-data-public.customfilter.md) | | | [EsaggsExpressionFunctionDefinition](./kibana-plugin-plugins-data-public.esaggsexpressionfunctiondefinition.md) | | | [EsdslExpressionFunctionDefinition](./kibana-plugin-plugins-data-public.esdslexpressionfunctiondefinition.md) | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.waituntilnextsessioncompletes_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.waituntilnextsessioncompletes_.md new file mode 100644 index 000000000000..a4b294fb1dec --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.waituntilnextsessioncompletes_.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [waitUntilNextSessionCompletes$](./kibana-plugin-plugins-data-public.waituntilnextsessioncompletes_.md) + +## waitUntilNextSessionCompletes$() function + +Creates an observable that emits when next search session completes. This utility is helpful to use in the application to delay some tasks until next session completes. + +Signature: + +```typescript +export declare function waitUntilNextSessionCompletes$(sessionService: ISessionService, { waitForIdle }?: WaitUntilNextSessionCompletesOptions): import("rxjs").Observable; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| sessionService | ISessionService | [ISessionService](./kibana-plugin-plugins-data-public.isessionservice.md) | +| { waitForIdle } | WaitUntilNextSessionCompletesOptions | | + +Returns: + +`import("rxjs").Observable` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.md new file mode 100644 index 000000000000..d575722a2245 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [WaitUntilNextSessionCompletesOptions](./kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.md) + +## WaitUntilNextSessionCompletesOptions interface + +Options for [waitUntilNextSessionCompletes$()](./kibana-plugin-plugins-data-public.waituntilnextsessioncompletes_.md) + +Signature: + +```typescript +export interface WaitUntilNextSessionCompletesOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [waitForIdle](./kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.waitforidle.md) | number | For how long to wait between session state transitions before considering that session completed | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.waitforidle.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.waitforidle.md new file mode 100644 index 000000000000..60d3df778385 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.waitforidle.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [WaitUntilNextSessionCompletesOptions](./kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.md) > [waitForIdle](./kibana-plugin-plugins-data-public.waituntilnextsessioncompletesoptions.waitforidle.md) + +## WaitUntilNextSessionCompletesOptions.waitForIdle property + +For how long to wait between session state transitions before considering that session completed + +Signature: + +```typescript +waitForIdle?: number; +``` diff --git a/src/plugins/dashboard/public/application/dashboard_app.tsx b/src/plugins/dashboard/public/application/dashboard_app.tsx index 3d6f08f32197..e7e2ccfd46b9 100644 --- a/src/plugins/dashboard/public/application/dashboard_app.tsx +++ b/src/plugins/dashboard/public/application/dashboard_app.tsx @@ -10,7 +10,7 @@ import { History } from 'history'; import { merge, Subject, Subscription } from 'rxjs'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { debounceTime, tap } from 'rxjs/operators'; +import { debounceTime, finalize, switchMap, tap } from 'rxjs/operators'; import { useKibana } from '../../../kibana_react/public'; import { DashboardConstants } from '../dashboard_constants'; import { DashboardTopNav } from './top_nav/dashboard_top_nav'; @@ -30,7 +30,7 @@ import { useSavedDashboard, } from './hooks'; -import { IndexPattern } from '../services/data'; +import { IndexPattern, waitUntilNextSessionCompletes$ } from '../services/data'; import { EmbeddableRenderer } from '../services/embeddable'; import { DashboardContainerInput } from '.'; import { leaveConfirmStrings } from '../dashboard_strings'; @@ -209,14 +209,26 @@ export function DashboardApp({ ); subscriptions.add( - merge( - data.query.timefilter.timefilter.getAutoRefreshFetch$(), - searchSessionIdQuery$ - ).subscribe(() => { + searchSessionIdQuery$.subscribe(() => { triggerRefresh$.next({ force: true }); }) ); + subscriptions.add( + data.query.timefilter.timefilter + .getAutoRefreshFetch$() + .pipe( + tap(() => { + triggerRefresh$.next({ force: true }); + }), + switchMap((done) => + // best way on a dashboard to estimate that panels are updated is to rely on search session service state + waitUntilNextSessionCompletes$(data.search.session).pipe(finalize(done)) + ) + ) + .subscribe() + ); + dashboardStateManager.registerChangeListener(() => { setUnsavedChanges(dashboardStateManager.getIsDirty(data.query.timefilter.timefilter)); // we aren't checking dirty state because there are changes the container needs to know about diff --git a/src/plugins/data/README.mdx b/src/plugins/data/README.mdx index 60e74a3fa126..30006e2b497b 100644 --- a/src/plugins/data/README.mdx +++ b/src/plugins/data/README.mdx @@ -5,7 +5,7 @@ title: Data services image: https://source.unsplash.com/400x175/?Search summary: The data plugin contains services for searching, querying and filtering. date: 2020-12-02 -tags: ['kibana','dev', 'contributor', 'api docs'] +tags: ['kibana', 'dev', 'contributor', 'api docs'] --- # data @@ -149,7 +149,6 @@ Index patterns provide Rest-like HTTP CRUD+ API with the following endpoints: - Remove a scripted field — `DELETE /api/index_patterns/index_pattern/{id}/scripted_field/{name}` - Update a scripted field — `POST /api/index_patterns/index_pattern/{id}/scripted_field/{name}` - ### Index Patterns API Index Patterns REST API allows you to create, retrieve and delete index patterns. I also @@ -212,11 +211,10 @@ The endpoint returns the created index pattern object. ```json { - "index_pattern": {} + "index_pattern": {} } ``` - #### Fetch an index pattern by ID Retrieve an index pattern by its ID. @@ -229,23 +227,22 @@ Returns an index pattern object. ```json { - "index_pattern": { - "id": "...", - "version": "...", - "title": "...", - "type": "...", - "intervalName": "...", - "timeFieldName": "...", - "sourceFilters": [], - "fields": {}, - "typeMeta": {}, - "fieldFormats": {}, - "fieldAttrs": {} - } + "index_pattern": { + "id": "...", + "version": "...", + "title": "...", + "type": "...", + "intervalName": "...", + "timeFieldName": "...", + "sourceFilters": [], + "fields": {}, + "typeMeta": {}, + "fieldFormats": {}, + "fieldAttrs": {} + } } ``` - #### Delete an index pattern by ID Delete and index pattern by its ID. @@ -256,21 +253,21 @@ DELETE /api/index_patterns/index_pattern/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Returns an '200 OK` response with empty body on success. - #### Partially update an index pattern by ID Update part of an index pattern. Only provided fields will be updated on the index pattern, missing fields will stay as they are persisted. These fields can be update partially: - - `title` - - `timeFieldName` - - `intervalName` - - `fields` (optionally refresh fields) - - `sourceFilters` - - `fieldFormatMap` - - `type` - - `typeMeta` + +- `title` +- `timeFieldName` +- `intervalName` +- `fields` (optionally refresh fields) +- `sourceFilters` +- `fieldFormatMap` +- `type` +- `typeMeta` Update a title of an index pattern. @@ -318,18 +315,14 @@ This endpoint returns the updated index pattern object. ```json { - "index_pattern": { - - } + "index_pattern": {} } ``` - ### Fields API Fields API allows to change field metadata, such as `count`, `customLabel`, and `format`. - #### Update fields Update endpoint allows you to update fields presentation metadata, such as `count`, @@ -383,13 +376,10 @@ This endpoint returns the updated index pattern object. ```json { - "index_pattern": { - - } + "index_pattern": {} } ``` - ### Scripted Fields API Scripted Fields API provides CRUD API for scripted fields of an index pattern. @@ -487,7 +477,7 @@ Returns the field object. ```json { - "field": {} + "field": {} } ``` @@ -529,47 +519,86 @@ POST /api/index_patterns/index_pattern/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/scri } ``` - ## Query The query service is responsible for managing the configuration of a search query (`QueryState`): filters, time range, query string, and settings such as the auto refresh behavior and saved queries. It contains sub-services for each of those configurations: - - `data.query.filterManager` - Manages the `filters` component of a `QueryState`. The global filter state (filters that are persisted between applications) are owned by this service. - - `data.query.timefilter` - Responsible for the time range filter and the auto refresh behavior settings. - - `data.query.queryString` - Responsible for the query string and query language settings. - - `data.query.savedQueries` - Responsible for persisting a `QueryState` into a `SavedObject`, so it can be restored and used by other applications. - Any changes to the `QueryState` are published on the `data.query.state$`, which is useful when wanting to persist global state or run a search upon data changes. +- `data.query.filterManager` - Manages the `filters` component of a `QueryState`. The global filter state (filters that are persisted between applications) are owned by this service. +- `data.query.timefilter` - Responsible for the time range filter and the auto refresh behavior settings. +- `data.query.queryString` - Responsible for the query string and query language settings. +- `data.query.savedQueries` - Responsible for persisting a `QueryState` into a `SavedObject`, so it can be restored and used by other applications. - A simple use case is: +Any changes to the `QueryState` are published on the `data.query.state$`, which is useful when wanting to persist global state or run a search upon data changes. - ```.ts - function searchOnChange(indexPattern: IndexPattern, aggConfigs: AggConfigs) { - data.query.state$.subscribe(() => { +A simple use case is: - // Constuct the query portion of the search request - const query = data.query.getEsQuery(indexPattern); +```.ts +function searchOnChange(indexPattern: IndexPattern, aggConfigs: AggConfigs) { + data.query.state$.subscribe(() => { + + // Constuct the query portion of the search request + const query = data.query.getEsQuery(indexPattern); + + // Construct a request + const request = { + params: { + index: indexPattern.title, + body: { + aggs: aggConfigs.toDsl(), + query, + }, + }, + }; + + // Search with the `data.query` config + const search$ = data.search.search(request); + + ... + }); +} - // Construct a request - const request = { - params: { - index: indexPattern.title, - body: { - aggs: aggConfigs.toDsl(), - query, - }, - }, - }; +``` - // Search with the `data.query` config - const search$ = data.search.search(request); +### Timefilter - ... - }); - } +`data.query.timefilter` is responsible for the time range filter and the auto refresh behavior settings. + +#### Autorefresh - ``` +Timefilter provides an API for setting and getting current auto refresh state: + +```ts +const { pause, value } = data.query.timefilter.timefilter.getRefreshInterval(); + +data.query.timefilter.timefilter.setRefreshInterval({ pause: false, value: 5000 }); // start auto refresh with 5 seconds interval +``` + +Timefilter API also provides an `autoRefreshFetch$` observables that apps should use to get notified +when it is time to refresh data because of auto refresh. +This API expects apps to confirm when they are done with reloading the data. +The confirmation mechanism is needed to prevent excessive queue of fetches. + +``` +import { refetchData } from '../my-app' + +const autoRefreshFetch$ = data.query.timefilter.timefilter.getAutoRefreshFetch$() +autoRefreshFetch$.subscribe((done) => { + try { + await refetchData(); + } finally { + // confirm that data fetching was finished + done(); + } +}) + +function unmount() { + // don't forget to unsubscribe when leaving the app + autoRefreshFetch$.unsubscribe() +} + +``` ## Search diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index c47cd6cd9740..d2683e248b7b 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -388,6 +388,8 @@ export { PainlessError, noSearchSessionStorageCapabilityMessage, SEARCH_SESSIONS_MANAGEMENT_ID, + waitUntilNextSessionCompletes$, + WaitUntilNextSessionCompletesOptions, } from './search'; export type { @@ -467,6 +469,7 @@ export { TimeHistoryContract, QueryStateChange, QueryStart, + AutoRefreshDoneFn, } from './query'; export { AggsStart } from './search/aggs'; diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 415d91f0bcdc..f6a7d032c701 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -504,6 +504,11 @@ export interface ApplyGlobalFilterActionContext { // @public (undocumented) export type AutocompleteStart = ReturnType; +// Warning: (ae-missing-release-tag) "AutoRefreshDoneFn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type AutoRefreshDoneFn = () => void; + // Warning: (ae-forgotten-export) The symbol "DateFormat" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "DateNanosFormat" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "baseFormattersPublic" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -2655,6 +2660,18 @@ export const UI_SETTINGS: { readonly AUTOCOMPLETE_USE_TIMERANGE: "autocomplete:useTimeRange"; }; +// Warning: (ae-missing-release-tag) "waitUntilNextSessionCompletes$" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export function waitUntilNextSessionCompletes$(sessionService: ISessionService, { waitForIdle }?: WaitUntilNextSessionCompletesOptions): import("rxjs").Observable; + +// Warning: (ae-missing-release-tag) "WaitUntilNextSessionCompletesOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export interface WaitUntilNextSessionCompletesOptions { + waitForIdle?: number; +} + // Warnings were encountered during analysis: // @@ -2702,21 +2719,21 @@ export const UI_SETTINGS: { // src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:404:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:404:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:404:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:404:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:407:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:416:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:417:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:418:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:419:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:423:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:424:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:427:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:428:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:431:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:406:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:406:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:406:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:406:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:408:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:418:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:419:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:420:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:421:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:425:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:426:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:429:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:430:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:433:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/public/query/state_sync/connect_to_query_state.ts:34:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts // src/plugins/data/public/search/session/session_service.ts:56:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts diff --git a/src/plugins/data/public/query/timefilter/index.ts b/src/plugins/data/public/query/timefilter/index.ts index 83e897824d86..3dfd4e0fe514 100644 --- a/src/plugins/data/public/query/timefilter/index.ts +++ b/src/plugins/data/public/query/timefilter/index.ts @@ -9,7 +9,7 @@ export { TimefilterService, TimefilterSetup } from './timefilter_service'; export * from './types'; -export { Timefilter, TimefilterContract } from './timefilter'; +export { Timefilter, TimefilterContract, AutoRefreshDoneFn } from './timefilter'; export { TimeHistory, TimeHistoryContract } from './time_history'; export { changeTimeFilter, convertRangeFilterToTimeRangeString } from './lib/change_time_filter'; export { extractTimeFilter, extractTimeRange } from './lib/extract_time_filter'; diff --git a/src/plugins/data/public/query/timefilter/lib/auto_refresh_loop.test.ts b/src/plugins/data/public/query/timefilter/lib/auto_refresh_loop.test.ts new file mode 100644 index 000000000000..3c8b316c3b87 --- /dev/null +++ b/src/plugins/data/public/query/timefilter/lib/auto_refresh_loop.test.ts @@ -0,0 +1,205 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { createAutoRefreshLoop, AutoRefreshDoneFn } from './auto_refresh_loop'; + +jest.useFakeTimers(); + +test('triggers refresh with interval', () => { + const { loop$, start, stop } = createAutoRefreshLoop(); + + const fn = jest.fn((done) => done()); + loop$.subscribe(fn); + + jest.advanceTimersByTime(5000); + expect(fn).not.toBeCalled(); + + start(1000); + + jest.advanceTimersByTime(1001); + expect(fn).toHaveBeenCalledTimes(1); + + jest.advanceTimersByTime(1001); + expect(fn).toHaveBeenCalledTimes(2); + + stop(); + + jest.advanceTimersByTime(5000); + expect(fn).toHaveBeenCalledTimes(2); +}); + +test('waits for done() to be called', () => { + const { loop$, start } = createAutoRefreshLoop(); + + let done!: AutoRefreshDoneFn; + const fn = jest.fn((_done) => { + done = _done; + }); + loop$.subscribe(fn); + start(1000); + + jest.advanceTimersByTime(1001); + expect(fn).toHaveBeenCalledTimes(1); + expect(done).toBeInstanceOf(Function); + + jest.advanceTimersByTime(1001); + expect(fn).toHaveBeenCalledTimes(1); + + done(); + + jest.advanceTimersByTime(500); + expect(fn).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(501); + expect(fn).toHaveBeenCalledTimes(2); +}); + +test('waits for done() from multiple subscribers to be called', () => { + const { loop$, start } = createAutoRefreshLoop(); + + let done1!: AutoRefreshDoneFn; + const fn1 = jest.fn((_done) => { + done1 = _done; + }); + loop$.subscribe(fn1); + + let done2!: AutoRefreshDoneFn; + const fn2 = jest.fn((_done) => { + done2 = _done; + }); + loop$.subscribe(fn2); + + start(1000); + + jest.advanceTimersByTime(1001); + expect(fn1).toHaveBeenCalledTimes(1); + expect(done1).toBeInstanceOf(Function); + + jest.advanceTimersByTime(1001); + expect(fn1).toHaveBeenCalledTimes(1); + + done1(); + + jest.advanceTimersByTime(500); + expect(fn1).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(501); + expect(fn1).toHaveBeenCalledTimes(1); + + done2(); + + jest.advanceTimersByTime(500); + expect(fn1).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(501); + expect(fn1).toHaveBeenCalledTimes(2); +}); + +test('unsubscribe() resets the state', () => { + const { loop$, start } = createAutoRefreshLoop(); + + let done1!: AutoRefreshDoneFn; + const fn1 = jest.fn((_done) => { + done1 = _done; + }); + loop$.subscribe(fn1); + + const fn2 = jest.fn(); + const sub2 = loop$.subscribe(fn2); + + start(1000); + + jest.advanceTimersByTime(1001); + expect(fn1).toHaveBeenCalledTimes(1); + expect(done1).toBeInstanceOf(Function); + + jest.advanceTimersByTime(1001); + expect(fn1).toHaveBeenCalledTimes(1); + + done1(); + + jest.advanceTimersByTime(500); + expect(fn1).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(501); + expect(fn1).toHaveBeenCalledTimes(1); + + sub2.unsubscribe(); + + jest.advanceTimersByTime(500); + expect(fn1).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(501); + expect(fn1).toHaveBeenCalledTimes(2); +}); + +test('calling done() twice is ignored', () => { + const { loop$, start } = createAutoRefreshLoop(); + + let done1!: AutoRefreshDoneFn; + const fn1 = jest.fn((_done) => { + done1 = _done; + }); + loop$.subscribe(fn1); + + const fn2 = jest.fn(); + loop$.subscribe(fn2); + + start(1000); + + jest.advanceTimersByTime(1001); + expect(fn1).toHaveBeenCalledTimes(1); + expect(done1).toBeInstanceOf(Function); + + jest.advanceTimersByTime(1001); + expect(fn1).toHaveBeenCalledTimes(1); + + done1(); + + jest.advanceTimersByTime(500); + expect(fn1).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(501); + expect(fn1).toHaveBeenCalledTimes(1); + + done1(); + + jest.advanceTimersByTime(500); + expect(fn1).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(501); + expect(fn1).toHaveBeenCalledTimes(1); +}); + +test('calling older done() is ignored', () => { + const { loop$, start } = createAutoRefreshLoop(); + + let done1!: AutoRefreshDoneFn; + const fn1 = jest.fn((_done) => { + // @ts-ignore + if (done1) return; + done1 = _done; + }); + loop$.subscribe(fn1); + + start(1000); + + jest.advanceTimersByTime(1001); + expect(fn1).toHaveBeenCalledTimes(1); + expect(done1).toBeInstanceOf(Function); + + jest.advanceTimersByTime(1001); + expect(fn1).toHaveBeenCalledTimes(1); + + done1(); + + jest.advanceTimersByTime(500); + expect(fn1).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(501); + expect(fn1).toHaveBeenCalledTimes(2); + + done1(); + + jest.advanceTimersByTime(500); + expect(fn1).toHaveBeenCalledTimes(2); + jest.advanceTimersByTime(501); + expect(fn1).toHaveBeenCalledTimes(2); +}); diff --git a/src/plugins/data/public/query/timefilter/lib/auto_refresh_loop.ts b/src/plugins/data/public/query/timefilter/lib/auto_refresh_loop.ts new file mode 100644 index 000000000000..1e213b36e1d8 --- /dev/null +++ b/src/plugins/data/public/query/timefilter/lib/auto_refresh_loop.ts @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { defer, Subject } from 'rxjs'; +import { finalize, map } from 'rxjs/operators'; +import { once } from 'lodash'; + +export type AutoRefreshDoneFn = () => void; + +/** + * Creates a loop for timepicker's auto refresh + * It has a "confirmation" mechanism: + * When auto refresh loop emits, it won't continue automatically, + * until each subscriber calls received `done` function. + * + * @internal + */ +export const createAutoRefreshLoop = () => { + let subscribersCount = 0; + const tick = new Subject(); + + let _timeoutHandle: number; + let _timeout: number = 0; + + function start() { + stop(); + if (_timeout === 0) return; + const timeoutHandle = window.setTimeout(() => { + let pendingDoneCount = subscribersCount; + const done = () => { + if (timeoutHandle !== _timeoutHandle) return; + + pendingDoneCount--; + if (pendingDoneCount === 0) { + start(); + } + }; + tick.next(done); + }, _timeout); + + _timeoutHandle = timeoutHandle; + } + + function stop() { + window.clearTimeout(_timeoutHandle); + _timeoutHandle = -1; + } + + return { + stop: () => { + _timeout = 0; + stop(); + }, + start: (timeout: number) => { + _timeout = timeout; + if (subscribersCount > 0) { + start(); + } + }, + loop$: defer(() => { + subscribersCount++; + start(); // restart the loop on a new subscriber + return tick.pipe(map((doneCb) => once(doneCb))); // each subscriber allowed to call done only once + }).pipe( + finalize(() => { + subscribersCount--; + if (subscribersCount === 0) { + stop(); + } else { + start(); // restart the loop to potentially unblock the interval + } + }) + ), + }; +}; diff --git a/src/plugins/data/public/query/timefilter/timefilter.test.ts b/src/plugins/data/public/query/timefilter/timefilter.test.ts index 8e1e76ed19e6..92ee6b0c3042 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.test.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.test.ts @@ -10,7 +10,7 @@ jest.useFakeTimers(); import sinon from 'sinon'; import moment from 'moment'; -import { Timefilter } from './timefilter'; +import { AutoRefreshDoneFn, Timefilter } from './timefilter'; import { Subscription } from 'rxjs'; import { TimeRange, RefreshInterval } from '../../../common'; import { createNowProviderMock } from '../../now_provider/mocks'; @@ -121,7 +121,7 @@ describe('setRefreshInterval', () => { beforeEach(() => { update = sinon.spy(); fetch = sinon.spy(); - autoRefreshFetch = sinon.spy(); + autoRefreshFetch = sinon.spy((done) => done()); timefilter.setRefreshInterval({ pause: false, value: 0, @@ -344,3 +344,44 @@ describe('calculateBounds', () => { expect(() => timefilter.calculateBounds(timeRange)).toThrowError(); }); }); + +describe('getAutoRefreshFetch$', () => { + test('next auto refresh loop starts after "done" called', () => { + const autoRefreshFetch = jest.fn(); + let doneCb: AutoRefreshDoneFn | undefined; + timefilter.getAutoRefreshFetch$().subscribe((done) => { + autoRefreshFetch(); + doneCb = done; + }); + timefilter.setRefreshInterval({ pause: false, value: 1000 }); + + expect(autoRefreshFetch).toBeCalledTimes(0); + jest.advanceTimersByTime(5000); + expect(autoRefreshFetch).toBeCalledTimes(1); + + if (doneCb) doneCb(); + + jest.advanceTimersByTime(1005); + expect(autoRefreshFetch).toBeCalledTimes(2); + }); + + test('new getAutoRefreshFetch$ subscription restarts refresh loop', () => { + const autoRefreshFetch = jest.fn(); + const fetch$ = timefilter.getAutoRefreshFetch$(); + const sub1 = fetch$.subscribe((done) => { + autoRefreshFetch(); + // this done will be never called, but loop will be reset by another subscription + }); + timefilter.setRefreshInterval({ pause: false, value: 1000 }); + + expect(autoRefreshFetch).toBeCalledTimes(0); + jest.advanceTimersByTime(5000); + expect(autoRefreshFetch).toBeCalledTimes(1); + + fetch$.subscribe(autoRefreshFetch); + expect(autoRefreshFetch).toBeCalledTimes(1); + sub1.unsubscribe(); + jest.advanceTimersByTime(1005); + expect(autoRefreshFetch).toBeCalledTimes(2); + }); +}); diff --git a/src/plugins/data/public/query/timefilter/timefilter.ts b/src/plugins/data/public/query/timefilter/timefilter.ts index 436b18f70a2f..9894010601d2 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.ts @@ -22,6 +22,9 @@ import { TimeRange, } from '../../../common'; import { TimeHistoryContract } from './time_history'; +import { createAutoRefreshLoop, AutoRefreshDoneFn } from './lib/auto_refresh_loop'; + +export { AutoRefreshDoneFn }; // TODO: remove! @@ -32,8 +35,6 @@ export class Timefilter { private timeUpdate$ = new Subject(); // Fired when a user changes the the autorefresh settings private refreshIntervalUpdate$ = new Subject(); - // Used when an auto refresh is triggered - private autoRefreshFetch$ = new Subject(); private fetch$ = new Subject(); private _time: TimeRange; @@ -45,11 +46,12 @@ export class Timefilter { private _isTimeRangeSelectorEnabled: boolean = false; private _isAutoRefreshSelectorEnabled: boolean = false; - private _autoRefreshIntervalId: number = 0; - private readonly timeDefaults: TimeRange; private readonly refreshIntervalDefaults: RefreshInterval; + // Used when an auto refresh is triggered + private readonly autoRefreshLoop = createAutoRefreshLoop(); + constructor( config: TimefilterConfig, timeHistory: TimeHistoryContract, @@ -86,9 +88,13 @@ export class Timefilter { return this.refreshIntervalUpdate$.asObservable(); }; - public getAutoRefreshFetch$ = () => { - return this.autoRefreshFetch$.asObservable(); - }; + /** + * Get an observable that emits when it is time to refetch data due to refresh interval + * Each subscription to this observable resets internal interval + * Emitted value is a callback {@link AutoRefreshDoneFn} that must be called to restart refresh interval loop + * Apps should use this callback to start next auto refresh loop when view finished updating + */ + public getAutoRefreshFetch$ = () => this.autoRefreshLoop.loop$; public getFetch$ = () => { return this.fetch$.asObservable(); @@ -166,13 +172,9 @@ export class Timefilter { } } - // Clear the previous auto refresh interval and start a new one (if not paused) - clearInterval(this._autoRefreshIntervalId); - if (!newRefreshInterval.pause) { - this._autoRefreshIntervalId = window.setInterval( - () => this.autoRefreshFetch$.next(), - newRefreshInterval.value - ); + this.autoRefreshLoop.stop(); + if (!newRefreshInterval.pause && newRefreshInterval.value !== 0) { + this.autoRefreshLoop.start(newRefreshInterval.value); } }; diff --git a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts index 0f2b01f61818..c22f62f45a70 100644 --- a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts +++ b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts @@ -20,7 +20,7 @@ const createSetupContractMock = () => { getEnabledUpdated$: jest.fn(), getTimeUpdate$: jest.fn(), getRefreshIntervalUpdate$: jest.fn(), - getAutoRefreshFetch$: jest.fn(() => new Observable()), + getAutoRefreshFetch$: jest.fn(() => new Observable<() => void>()), getFetch$: jest.fn(), getTime: jest.fn(), setTime: jest.fn(), diff --git a/src/plugins/data/public/search/index.ts b/src/plugins/data/public/search/index.ts index fded4c46992c..92a5c36202e6 100644 --- a/src/plugins/data/public/search/index.ts +++ b/src/plugins/data/public/search/index.ts @@ -45,6 +45,8 @@ export { ISessionsClient, noSearchSessionStorageCapabilityMessage, SEARCH_SESSIONS_MANAGEMENT_ID, + waitUntilNextSessionCompletes$, + WaitUntilNextSessionCompletesOptions, } from './session'; export { getEsPreference } from './es_search'; diff --git a/src/plugins/data/public/search/session/index.ts b/src/plugins/data/public/search/session/index.ts index 15410400a33e..ce578378a2fe 100644 --- a/src/plugins/data/public/search/session/index.ts +++ b/src/plugins/data/public/search/session/index.ts @@ -11,3 +11,7 @@ export { SearchSessionState } from './search_session_state'; export { SessionsClient, ISessionsClient } from './sessions_client'; export { noSearchSessionStorageCapabilityMessage } from './i18n'; export { SEARCH_SESSIONS_MANAGEMENT_ID } from './constants'; +export { + waitUntilNextSessionCompletes$, + WaitUntilNextSessionCompletesOptions, +} from './session_helpers'; diff --git a/src/plugins/data/public/search/session/session_helpers.test.ts b/src/plugins/data/public/search/session/session_helpers.test.ts new file mode 100644 index 000000000000..5b64e7b554d1 --- /dev/null +++ b/src/plugins/data/public/search/session/session_helpers.test.ts @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { waitUntilNextSessionCompletes$ } from './session_helpers'; +import { ISessionService, SessionService } from './session_service'; +import { BehaviorSubject } from 'rxjs'; +import { SearchSessionState } from './search_session_state'; +import { NowProviderInternalContract } from '../../now_provider'; +import { coreMock } from '../../../../../core/public/mocks'; +import { createNowProviderMock } from '../../now_provider/mocks'; +import { SEARCH_SESSIONS_MANAGEMENT_ID } from './constants'; +import { getSessionsClientMock } from './mocks'; + +let sessionService: ISessionService; +let state$: BehaviorSubject; +let nowProvider: jest.Mocked; +let currentAppId$: BehaviorSubject; + +beforeEach(() => { + const initializerContext = coreMock.createPluginInitializerContext(); + const startService = coreMock.createSetup().getStartServices; + nowProvider = createNowProviderMock(); + currentAppId$ = new BehaviorSubject('app'); + sessionService = new SessionService( + initializerContext, + () => + startService().then(([coreStart, ...rest]) => [ + { + ...coreStart, + application: { + ...coreStart.application, + currentAppId$, + capabilities: { + ...coreStart.application.capabilities, + management: { + kibana: { + [SEARCH_SESSIONS_MANAGEMENT_ID]: true, + }, + }, + }, + }, + }, + ...rest, + ]), + getSessionsClientMock(), + nowProvider, + { freezeState: false } // needed to use mocks inside state container + ); + state$ = new BehaviorSubject(SearchSessionState.None); + sessionService.state$.subscribe(state$); +}); + +describe('waitUntilNextSessionCompletes$', () => { + beforeEach(() => { + jest.useFakeTimers(); + }); + afterEach(() => { + jest.useRealTimers(); + }); + test('emits when next session starts', () => { + sessionService.start(); + let untrackSearch = sessionService.trackSearch({ abort: () => {} }); + untrackSearch(); + + const next = jest.fn(); + const complete = jest.fn(); + waitUntilNextSessionCompletes$(sessionService).subscribe({ next, complete }); + expect(next).not.toBeCalled(); + + sessionService.start(); + expect(next).not.toBeCalled(); + + untrackSearch = sessionService.trackSearch({ abort: () => {} }); + untrackSearch(); + + expect(next).not.toBeCalled(); + jest.advanceTimersByTime(500); + expect(next).not.toBeCalled(); + jest.advanceTimersByTime(1000); + expect(next).toBeCalledTimes(1); + expect(complete).toBeCalled(); + }); +}); diff --git a/src/plugins/data/public/search/session/session_helpers.ts b/src/plugins/data/public/search/session/session_helpers.ts new file mode 100644 index 000000000000..1f0a2da7e93f --- /dev/null +++ b/src/plugins/data/public/search/session/session_helpers.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { debounceTime, first, skipUntil } from 'rxjs/operators'; +import { ISessionService } from './session_service'; +import { SearchSessionState } from './search_session_state'; + +/** + * Options for {@link waitUntilNextSessionCompletes$} + */ +export interface WaitUntilNextSessionCompletesOptions { + /** + * For how long to wait between session state transitions before considering that session completed + */ + waitForIdle?: number; +} + +/** + * Creates an observable that emits when next search session completes. + * This utility is helpful to use in the application to delay some tasks until next session completes. + * + * @param sessionService - {@link ISessionService} + * @param opts - {@link WaitUntilNextSessionCompletesOptions} + */ +export function waitUntilNextSessionCompletes$( + sessionService: ISessionService, + { waitForIdle = 1000 }: WaitUntilNextSessionCompletesOptions = { waitForIdle: 1000 } +) { + return sessionService.state$.pipe( + // wait until new session starts + skipUntil(sessionService.state$.pipe(first((state) => state === SearchSessionState.None))), + // wait until new session starts loading + skipUntil(sessionService.state$.pipe(first((state) => state === SearchSessionState.Loading))), + // debounce to ignore quick switches from loading <-> completed. + // that could happen between sequential search requests inside a single session + debounceTime(waitForIdle), + // then wait until it finishes + first( + (state) => + state === SearchSessionState.Completed || state === SearchSessionState.BackgroundCompleted + ) + ); +} diff --git a/src/plugins/discover/public/application/angular/discover.js b/src/plugins/discover/public/application/angular/discover.js index 2c80fc111c74..3be047859d3b 100644 --- a/src/plugins/discover/public/application/angular/discover.js +++ b/src/plugins/discover/public/application/angular/discover.js @@ -8,7 +8,7 @@ import _ from 'lodash'; import { merge, Subject, Subscription } from 'rxjs'; -import { debounceTime } from 'rxjs/operators'; +import { debounceTime, tap, filter } from 'rxjs/operators'; import { i18n } from '@kbn/i18n'; import { createSearchSessionRestorationDataProvider, getState, splitState } from './discover_state'; import { RequestAdapter } from '../../../../inspector/public'; @@ -393,12 +393,11 @@ function discoverController($route, $scope) { $scope.state.index = $scope.indexPattern.id; $scope.state.sort = getSortArray($scope.state.sort, $scope.indexPattern); - $scope.opts.fetch = $scope.fetch = function () { + $scope.opts.fetch = $scope.fetch = async function () { $scope.fetchCounter++; $scope.fetchError = undefined; if (!validateTimeRange(timefilter.getTime(), toastNotifications)) { $scope.resultState = 'none'; - return; } // Abort any in-progress requests before fetching again @@ -494,11 +493,19 @@ function discoverController($route, $scope) { showUnmappedFields, }; + // handler emitted by `timefilter.getAutoRefreshFetch$()` + // to notify when data completed loading and to start a new autorefresh loop + let autoRefreshDoneCb; const fetch$ = merge( refetch$, filterManager.getFetches$(), timefilter.getFetch$(), - timefilter.getAutoRefreshFetch$(), + timefilter.getAutoRefreshFetch$().pipe( + tap((done) => { + autoRefreshDoneCb = done; + }), + filter(() => $scope.fetchStatus !== fetchStatuses.LOADING) + ), data.query.queryString.getUpdates$(), searchSessionManager.newSearchSessionIdFromURL$ ).pipe(debounceTime(100)); @@ -508,7 +515,16 @@ function discoverController($route, $scope) { $scope, fetch$, { - next: $scope.fetch, + next: async () => { + try { + await $scope.fetch(); + } finally { + // if there is a saved `autoRefreshDoneCb`, notify auto refresh service that + // the last fetch is completed so it starts the next auto refresh loop if needed + autoRefreshDoneCb?.(); + autoRefreshDoneCb = undefined; + } + }, }, (error) => addFatalError(core.fatalErrors, error) ) diff --git a/src/plugins/expressions/public/loader.ts b/src/plugins/expressions/public/loader.ts index 65925b5a2e4c..4165b8906a20 100644 --- a/src/plugins/expressions/public/loader.ts +++ b/src/plugins/expressions/public/loader.ts @@ -118,12 +118,15 @@ export class ExpressionLoader { return this.execution ? (this.execution.inspect() as Adapters) : undefined; } - update(expression?: string | ExpressionAstExpression, params?: IExpressionLoaderParams): void { + async update( + expression?: string | ExpressionAstExpression, + params?: IExpressionLoaderParams + ): Promise { this.setParams(params); this.loadingSubject.next(true); if (expression) { - this.loadData(expression, this.params); + await this.loadData(expression, this.params); } else if (this.data) { this.render(this.data); } diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts index 429dabeeef04..efb166c8975b 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -367,8 +367,8 @@ export class VisualizeEmbeddable } } - public reload = () => { - this.handleVisUpdate(); + public reload = async () => { + await this.handleVisUpdate(); }; private async updateHandler() { @@ -395,13 +395,13 @@ export class VisualizeEmbeddable }); if (this.handler && !abortController.signal.aborted) { - this.handler.update(this.expression, expressionParams); + await this.handler.update(this.expression, expressionParams); } } private handleVisUpdate = async () => { this.handleChanges(); - this.updateHandler(); + await this.updateHandler(); }; private uiStateChangeHandler = () => { diff --git a/src/plugins/visualize/public/application/components/visualize_top_nav.tsx b/src/plugins/visualize/public/application/components/visualize_top_nav.tsx index 256e634ac6c4..f6ef1caf9c9e 100644 --- a/src/plugins/visualize/public/application/components/visualize_top_nav.tsx +++ b/src/plugins/visualize/public/application/components/visualize_top_nav.tsx @@ -183,8 +183,12 @@ const TopNav = ({ useEffect(() => { const autoRefreshFetchSub = services.data.query.timefilter.timefilter .getAutoRefreshFetch$() - .subscribe(() => { - visInstance.embeddableHandler.reload(); + .subscribe(async (done) => { + try { + await visInstance.embeddableHandler.reload(); + } finally { + done(); + } }); return () => { autoRefreshFetchSub.unsubscribe(); diff --git a/x-pack/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/plugins/lens/public/app_plugin/app.test.tsx index 20bf349f6b13..b7dbf1bbe4d8 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.test.tsx @@ -155,11 +155,7 @@ function createMockTimefilter() { getBounds: jest.fn(() => timeFilter), getRefreshInterval: () => {}, getRefreshIntervalDefaults: () => {}, - getAutoRefreshFetch$: () => ({ - subscribe: ({ next }: { next: () => void }) => { - return next; - }, - }), + getAutoRefreshFetch$: () => new Observable(), }; } diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx index dbc10c751a64..39163101fc7b 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.tsx @@ -14,6 +14,7 @@ import { Toast } from 'kibana/public'; import { VisualizeFieldContext } from 'src/plugins/ui_actions/public'; import { Datatable } from 'src/plugins/expressions/public'; import { EuiBreadcrumb } from '@elastic/eui'; +import { finalize, switchMap, tap } from 'rxjs/operators'; import { downloadMultipleAs } from '../../../../../src/plugins/share/public'; import { createKbnUrlStateStorage, @@ -37,6 +38,7 @@ import { Query, SavedQuery, syncQueryStateWithUrl, + waitUntilNextSessionCompletes$, } from '../../../../../src/plugins/data/public'; import { LENS_EMBEDDABLE_TYPE, getFullPath, APP_ID } from '../../common'; import { LensAppProps, LensAppServices, LensAppState } from './types'; @@ -193,14 +195,19 @@ export function App({ const autoRefreshSubscription = data.query.timefilter.timefilter .getAutoRefreshFetch$() - .subscribe({ - next: () => { + .pipe( + tap(() => { setState((s) => ({ ...s, searchSessionId: data.search.session.start(), })); - }, - }); + }), + switchMap((done) => + // best way in lens to estimate that all panels are updated is to rely on search session service state + waitUntilNextSessionCompletes$(data.search.session).pipe(finalize(done)) + ) + ) + .subscribe(); const kbnUrlStateStorage = createKbnUrlStateStorage({ history, From 81adccd389b8c064b7a26e61f6071664b81eb8d4 Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Thu, 8 Apr 2021 10:20:43 -0400 Subject: [PATCH 22/49] [Security Solution][Endpoint] Endpoint Event Filtering List, Test Data Generator and Loader (#96263) (#96456) * Added new const to List plugin for new Endpont Event Filter list * Data Generator for event filters ++ script to load event filters (WIP) * refactor `generate_data` to use `BaseDataGenerator` class Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/lists/common/constants.ts | 9 ++ .../create_endoint_event_filters_list.ts | 79 +++++++++++++ .../data_generators/base_data_generator.ts | 94 +++++++++++++++ .../data_generators/event_filter_generator.ts | 30 +++++ .../common/endpoint/generate_data.ts | 56 ++------- .../scripts/endpoint/event_filters/index.ts | 111 ++++++++++++++++++ .../scripts/endpoint/load_event_filters.js | 11 ++ 7 files changed, 341 insertions(+), 49 deletions(-) create mode 100644 x-pack/plugins/lists/server/services/exception_lists/create_endoint_event_filters_list.ts create mode 100644 x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts create mode 100644 x-pack/plugins/security_solution/common/endpoint/data_generators/event_filter_generator.ts create mode 100644 x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts create mode 100755 x-pack/plugins/security_solution/scripts/endpoint/load_event_filters.js diff --git a/x-pack/plugins/lists/common/constants.ts b/x-pack/plugins/lists/common/constants.ts index 92d8b6f5f757..4f897c83cb41 100644 --- a/x-pack/plugins/lists/common/constants.ts +++ b/x-pack/plugins/lists/common/constants.ts @@ -60,3 +60,12 @@ export const ENDPOINT_TRUSTED_APPS_LIST_NAME = 'Endpoint Security Trusted Apps L /** Description of trusted apps agnostic list */ export const ENDPOINT_TRUSTED_APPS_LIST_DESCRIPTION = 'Endpoint Security Trusted Apps List'; + +/** ID of event filters agnostic list */ +export const ENDPOINT_EVENT_FILTERS_LIST_ID = 'endpoint_event_filters'; + +/** Name of event filters agnostic list */ +export const ENDPOINT_EVENT_FILTERS_LIST_NAME = 'Endpoint Security Event Filters List'; + +/** Description of event filters agnostic list */ +export const ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION = 'Endpoint Security Event Filters List'; diff --git a/x-pack/plugins/lists/server/services/exception_lists/create_endoint_event_filters_list.ts b/x-pack/plugins/lists/server/services/exception_lists/create_endoint_event_filters_list.ts new file mode 100644 index 000000000000..95e9df03400a --- /dev/null +++ b/x-pack/plugins/lists/server/services/exception_lists/create_endoint_event_filters_list.ts @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SavedObjectsClientContract } from 'kibana/server'; +import uuid from 'uuid'; + +import { + ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION, + ENDPOINT_EVENT_FILTERS_LIST_ID, + ENDPOINT_EVENT_FILTERS_LIST_NAME, +} from '../../../common/constants'; +import { ExceptionListSchema, ExceptionListSoSchema, Version } from '../../../common/schemas'; + +import { getSavedObjectType, transformSavedObjectToExceptionList } from './utils'; + +interface CreateEndpointEventFiltersListOptions { + savedObjectsClient: SavedObjectsClientContract; + user: string; + tieBreaker?: string; + version: Version; +} + +/** + * Creates the Endpoint Trusted Apps agnostic list if it does not yet exist + * + * @param savedObjectsClient + * @param user + * @param tieBreaker + * @param version + */ +export const createEndpointEventFiltersList = async ({ + savedObjectsClient, + user, + tieBreaker, + version, +}: CreateEndpointEventFiltersListOptions): Promise => { + const savedObjectType = getSavedObjectType({ namespaceType: 'agnostic' }); + const dateNow = new Date().toISOString(); + try { + const savedObject = await savedObjectsClient.create( + savedObjectType, + { + comments: undefined, + created_at: dateNow, + created_by: user, + description: ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION, + entries: undefined, + immutable: false, + item_id: undefined, + list_id: ENDPOINT_EVENT_FILTERS_LIST_ID, + list_type: 'list', + meta: undefined, + name: ENDPOINT_EVENT_FILTERS_LIST_NAME, + os_types: [], + tags: [], + tie_breaker_id: tieBreaker ?? uuid.v4(), + type: 'endpoint', + updated_by: user, + version, + }, + { + // We intentionally hard coding the id so that there can only be one Event Filters list within the space + id: ENDPOINT_EVENT_FILTERS_LIST_ID, + } + ); + + return transformSavedObjectToExceptionList({ savedObject }); + } catch (err) { + if (savedObjectsClient.errors.isConflictError(err)) { + return null; + } else { + throw err; + } + } +}; diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts new file mode 100644 index 000000000000..c0888a6c2a4b --- /dev/null +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import seedrandom from 'seedrandom'; +import uuid from 'uuid'; + +const OS_FAMILY = ['windows', 'macos', 'linux']; + +/** + * A generic base class to assist in creating domain specific data generators. It includes + * several general purpose random data generators for use within the class and exposes one + * public method named `generate()` which should be implemented by sub-classes. + */ +export class BaseDataGenerator { + protected random: seedrandom.prng; + + constructor(seed: string | seedrandom.prng = Math.random().toString()) { + if (typeof seed === 'string') { + this.random = seedrandom(seed); + } else { + this.random = seed; + } + } + + /** + * Generate a new record + */ + public generate(): GeneratedDoc { + throw new Error('method not implemented!'); + } + + /** generate random OS family value */ + protected randomOSFamily(): string { + return this.randomChoice(OS_FAMILY); + } + + /** generate a UUID (v4) */ + protected randomUUID(): string { + return uuid.v4(); + } + + /** Generate a random number up to the max provided */ + protected randomN(max: number): number { + return Math.floor(this.random() * max); + } + + protected *randomNGenerator(max: number, count: number) { + let iCount = count; + while (iCount > 0) { + yield this.randomN(max); + iCount = iCount - 1; + } + } + + /** + * Create an array of a given size and fill it with data provided by a generator + * + * @param lengthLimit + * @param generator + * @protected + */ + protected randomArray(lengthLimit: number, generator: () => T): T[] { + const rand = this.randomN(lengthLimit) + 1; + return [...Array(rand).keys()].map(generator); + } + + protected randomMac(): string { + return [...this.randomNGenerator(255, 6)].map((x) => x.toString(16)).join('-'); + } + + protected randomIP(): string { + return [10, ...this.randomNGenerator(255, 3)].map((x) => x.toString()).join('.'); + } + + protected randomVersion(): string { + return [6, ...this.randomNGenerator(10, 2)].map((x) => x.toString()).join('.'); + } + + protected randomChoice(choices: T[]): T { + return choices[this.randomN(choices.length)]; + } + + protected randomString(length: number): string { + return [...this.randomNGenerator(36, length)].map((x) => x.toString(36)).join(''); + } + + protected randomHostname(): string { + return `Host-${this.randomString(10)}`; + } +} diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/event_filter_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/event_filter_generator.ts new file mode 100644 index 000000000000..6bdbb9cde203 --- /dev/null +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/event_filter_generator.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { BaseDataGenerator } from './base_data_generator'; +import { ENDPOINT_EVENT_FILTERS_LIST_ID } from '../../../../lists/common/constants'; +import { CreateExceptionListItemSchema } from '../../../../lists/common'; +import { getCreateExceptionListItemSchemaMock } from '../../../../lists/common/schemas/request/create_exception_list_item_schema.mock'; + +export class EventFilterGenerator extends BaseDataGenerator { + generate(): CreateExceptionListItemSchema { + const overrides: Partial = { + name: `generator event ${this.randomString(5)}`, + list_id: ENDPOINT_EVENT_FILTERS_LIST_ID, + item_id: `generator_endpoint_event_filter_${this.randomUUID()}`, + os_types: [this.randomOSFamily()] as CreateExceptionListItemSchema['os_types'], + tags: ['policy:all'], + namespace_type: 'agnostic', + meta: undefined, + }; + + return Object.assign>( + getCreateExceptionListItemSchemaMock(), + overrides + ); + } +} diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts index 8aec9768dd50..36d0b0cbf3b2 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -35,6 +35,7 @@ import { EsAssetReference, KibanaAssetReference } from '../../../fleet/common/ty import { agentPolicyStatuses } from '../../../fleet/common/constants'; import { firstNonNullValue } from './models/ecs_safety_helpers'; import { EventOptions } from './types/generator'; +import { BaseDataGenerator } from './data_generators/base_data_generator'; export type Event = AlertEvent | SafeEndpointEvent; /** @@ -386,9 +387,8 @@ const alertsDefaultDataStream = { namespace: 'default', }; -export class EndpointDocGenerator { +export class EndpointDocGenerator extends BaseDataGenerator { commonInfo: HostInfo; - random: seedrandom.prng; sequence: number = 0; /** * The EndpointDocGenerator parameters @@ -396,12 +396,7 @@ export class EndpointDocGenerator { * @param seed either a string to seed the random number generator or a random number generator function */ constructor(seed: string | seedrandom.prng = Math.random().toString()) { - if (typeof seed === 'string') { - this.random = seedrandom(seed); - } else { - this.random = seed; - } - + super(seed); this.commonInfo = this.createHostData(); } @@ -1568,47 +1563,6 @@ export class EndpointDocGenerator { }; } - private randomN(n: number): number { - return Math.floor(this.random() * n); - } - - private *randomNGenerator(max: number, count: number) { - let iCount = count; - while (iCount > 0) { - yield this.randomN(max); - iCount = iCount - 1; - } - } - - private randomArray(lengthLimit: number, generator: () => T): T[] { - const rand = this.randomN(lengthLimit) + 1; - return [...Array(rand).keys()].map(generator); - } - - private randomMac(): string { - return [...this.randomNGenerator(255, 6)].map((x) => x.toString(16)).join('-'); - } - - public randomIP(): string { - return [10, ...this.randomNGenerator(255, 3)].map((x) => x.toString()).join('.'); - } - - private randomVersion(): string { - return [6, ...this.randomNGenerator(10, 2)].map((x) => x.toString()).join('.'); - } - - private randomChoice(choices: T[]): T { - return choices[this.randomN(choices.length)]; - } - - private randomString(length: number): string { - return [...this.randomNGenerator(36, length)].map((x) => x.toString(36)).join(''); - } - - private randomHostname(): string { - return `Host-${this.randomString(10)}`; - } - private seededUUIDv4(): string { return uuid.v4({ random: [...this.randomNGenerator(255, 16)] }); } @@ -1646,6 +1600,10 @@ export class EndpointDocGenerator { private randomProcessName(): string { return this.randomChoice(fakeProcessNames); } + + public randomIP(): string { + return super.randomIP(); + } } const fakeProcessNames = [ diff --git a/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts b/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts new file mode 100644 index 000000000000..93af1f406300 --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/endpoint/event_filters/index.ts @@ -0,0 +1,111 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { run, RunFn, createFailError } from '@kbn/dev-utils'; +import { KbnClient } from '@kbn/test'; +import { AxiosError } from 'axios'; +import bluebird from 'bluebird'; +import { EventFilterGenerator } from '../../../common/endpoint/data_generators/event_filter_generator'; +import { + ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION, + ENDPOINT_EVENT_FILTERS_LIST_ID, + ENDPOINT_EVENT_FILTERS_LIST_NAME, + EXCEPTION_LIST_ITEM_URL, + EXCEPTION_LIST_URL, +} from '../../../../lists/common/constants'; +import { CreateExceptionListSchema } from '../../../../lists/common'; + +export const cli = () => { + run( + async (options) => { + try { + await createEventFilters(options); + options.log.success(`${options.flags.count} endpoint event filters created`); + } catch (e) { + options.log.error(e); + throw createFailError(e.message); + } + }, + { + description: 'Load Endpoint Event Filters', + flags: { + string: ['kibana'], + default: { + count: 10, + kibana: 'http://elastic:changeme@localhost:5601', + }, + help: ` + --count Number of event filters to create. Default: 10 + --kibana The URL to kibana including credentials. Default: http://elastic:changeme@localhost:5601 + `, + }, + } + ); +}; + +class EventFilterDataLoaderError extends Error { + constructor(message: string, public readonly meta: unknown) { + super(message); + } +} + +const handleThrowAxiosHttpError = (err: AxiosError): never => { + let message = err.message; + + if (err.response) { + message = `[${err.response.status}] ${err.response.data.message ?? err.message} [ ${String( + err.response.config.method + ).toUpperCase()} ${err.response.config.url} ]`; + } + throw new EventFilterDataLoaderError(message, err.toJSON()); +}; + +const createEventFilters: RunFn = async ({ flags, log }) => { + const eventGenerator = new EventFilterGenerator(); + const kbn = new KbnClient({ log, url: flags.kibana as string }); + + await ensureCreateEndpointEventFiltersList(kbn); + + await bluebird.map( + Array.from({ length: (flags.count as unknown) as number }), + () => + kbn + .request({ + method: 'POST', + path: EXCEPTION_LIST_ITEM_URL, + body: eventGenerator.generate(), + }) + .catch((e) => handleThrowAxiosHttpError(e)), + { concurrency: 10 } + ); +}; + +const ensureCreateEndpointEventFiltersList = async (kbn: KbnClient) => { + const newListDefinition: CreateExceptionListSchema = { + description: ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION, + list_id: ENDPOINT_EVENT_FILTERS_LIST_ID, + meta: undefined, + name: ENDPOINT_EVENT_FILTERS_LIST_NAME, + os_types: [], + tags: [], + type: 'endpoint', + namespace_type: 'agnostic', + }; + + await kbn + .request({ + method: 'POST', + path: EXCEPTION_LIST_URL, + body: newListDefinition, + }) + .catch((e) => { + // Ignore if list was already created + if (e.response.status !== 409) { + handleThrowAxiosHttpError(e); + } + }); +}; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/load_event_filters.js b/x-pack/plugins/security_solution/scripts/endpoint/load_event_filters.js new file mode 100755 index 000000000000..ca0f4ff9365c --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/endpoint/load_event_filters.js @@ -0,0 +1,11 @@ +#!/usr/bin/env node + +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +require('../../../../../src/setup_node_env'); +require('./event_filters').cli(); From 07f226c032263a17b9dded9c8d9621041e857a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Thu, 8 Apr 2021 16:44:44 +0200 Subject: [PATCH 23/49] [Remote clusters] Cloud deployment form when adding new cluster (#94450) (#96558) * Implemented in-form Cloud deployment url input * Fixed i18n files and added mode switch back for non-Cloud * Added cloud docs link to the documentation service, fixed snapshot tests * Fixed docs build * Added jest test for the new cloud url input * Added unit test for cloud validation * Fixed eslint error * Fixed ts errors * Added ts-ignore * Fixed ts errors * Refactored connection mode component and component tests * Fixed import * Fixed copy * Fixed copy * Reverted docs changes * Reverted docs changes * Replaced the screenshot with a popover and refactored integration tests * Added todo for cloud deployments link * Changed cloud URL help text copy * Added cloud base url and deleted unnecessary base path * Fixed es error * Fixed es error * Changed wording * Reverted docs changes * Updated the help popover * Deleted unneeded fragment component * Deleted unneeded fragment component * Updated tests descriptions to be more detailed Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../add/remote_clusters_add.helpers.js | 43 - .../add/remote_clusters_add.helpers.tsx | 47 + .../add/remote_clusters_add.test.js | 230 -- .../add/remote_clusters_add.test.ts | 260 +++ ...al_characters.js => special_characters.ts} | 0 .../edit/remote_clusters_edit.helpers.js | 34 - .../edit/remote_clusters_edit.helpers.tsx | 58 + .../edit/remote_clusters_edit.test.js | 80 - .../edit/remote_clusters_edit.test.tsx | 141 ++ .../{http_requests.js => http_requests.ts} | 19 +- .../helpers/{index.js => index.ts} | 1 + .../helpers/remote_clusters_actions.ts | 199 ++ ...up_environment.js => setup_environment.ts} | 2 + .../public/application/app_context.tsx | 10 +- .../public/application/index.d.ts | 3 +- .../remote_cluster_form.test.js.snap | 2017 ----------------- .../components/cloud_url_help.tsx | 61 + .../components/connection_mode.tsx | 99 + .../remote_cluster_form/components/index.ts | 8 + .../components/proxy_connection.tsx | 162 ++ .../components/sniff_connection.tsx | 158 ++ .../{index.js => index.ts} | 0 .../remote_cluster_form.js | 962 -------- .../remote_cluster_form.test.js | 53 - .../remote_cluster_form.tsx | 629 +++++ .../remote_cluster_form/request_flyout.tsx | 4 +- .../remote_cluster_form/validators/index.ts | 7 + .../validators/validate_cloud_url.test.ts | 128 ++ .../validators/validate_cloud_url.tsx | 80 + .../validators/validate_cluster.tsx | 39 + .../validators/validate_seed.ts | 43 - .../validators/validate_seed.tsx | 40 + .../public/application/sections/index.d.ts | 11 + .../remote_cluster_add/remote_cluster_add.js | 2 +- .../remote_cluster_edit.js | 7 +- .../public/application/services/api.ts | 2 +- .../application/services/documentation.ts | 10 +- .../public/application/services/index.ts | 8 +- .../public/application/services/routing.ts | 2 +- .../public/application/store/index.d.ts | 11 + .../public/assets/cloud_screenshot.png | Bin 0 -> 197089 bytes .../plugins/remote_clusters/public/plugin.ts | 5 +- x-pack/plugins/remote_clusters/tsconfig.json | 2 + .../translations/translations/ja-JP.json | 5 - .../translations/translations/zh-CN.json | 5 - 45 files changed, 2184 insertions(+), 3503 deletions(-) delete mode 100644 x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.helpers.js create mode 100644 x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.helpers.tsx delete mode 100644 x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.test.js create mode 100644 x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.test.ts rename x-pack/plugins/remote_clusters/__jest__/client_integration/add/{special_characters.js => special_characters.ts} (100%) delete mode 100644 x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.helpers.js create mode 100644 x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.helpers.tsx delete mode 100644 x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.test.js create mode 100644 x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.test.tsx rename x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/{http_requests.js => http_requests.ts} (63%) rename x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/{index.js => index.ts} (80%) create mode 100644 x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_actions.ts rename x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/{setup_environment.js => setup_environment.ts} (95%) delete mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap create mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/cloud_url_help.tsx create mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/connection_mode.tsx create mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/index.ts create mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/proxy_connection.tsx create mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/sniff_connection.tsx rename x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/{index.js => index.ts} (100%) delete mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.js delete mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.test.js create mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.tsx create mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_cloud_url.test.ts create mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_cloud_url.tsx create mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_cluster.tsx delete mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seed.ts create mode 100644 x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seed.tsx create mode 100644 x-pack/plugins/remote_clusters/public/application/sections/index.d.ts create mode 100644 x-pack/plugins/remote_clusters/public/application/store/index.d.ts create mode 100644 x-pack/plugins/remote_clusters/public/assets/cloud_screenshot.png diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.helpers.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.helpers.js deleted file mode 100644 index 38672b4d59a2..000000000000 --- a/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.helpers.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { act } from 'react-dom/test-utils'; - -import { registerTestBed } from '@kbn/test/jest'; - -import { RemoteClusterAdd } from '../../../public/application/sections/remote_cluster_add'; -import { createRemoteClustersStore } from '../../../public/application/store'; -import { registerRouter } from '../../../public/application/services/routing'; - -const testBedConfig = { - store: createRemoteClustersStore, - memoryRouter: { - onRouter: (router) => registerRouter(router), - }, -}; - -const initTestBed = registerTestBed(RemoteClusterAdd, testBedConfig); - -export const setup = (props) => { - const testBed = initTestBed(props); - - // User actions - const clickSaveForm = async () => { - await act(async () => { - testBed.find('remoteClusterFormSaveButton').simulate('click'); - }); - - testBed.component.update(); - }; - - return { - ...testBed, - actions: { - clickSaveForm, - }, - }; -}; diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.helpers.tsx b/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.helpers.tsx new file mode 100644 index 000000000000..a47e6c023a16 --- /dev/null +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.helpers.tsx @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { registerTestBed } from '@kbn/test/jest'; + +import { RemoteClusterAdd } from '../../../public/application/sections'; +import { createRemoteClustersStore } from '../../../public/application/store'; +import { AppRouter, registerRouter } from '../../../public/application/services'; +import { createRemoteClustersActions } from '../helpers'; +import { AppContextProvider } from '../../../public/application/app_context'; + +const ComponentWithContext = ({ isCloudEnabled }: { isCloudEnabled: boolean }) => { + return ( + + + + ); +}; + +const testBedConfig = ({ isCloudEnabled }: { isCloudEnabled: boolean }) => { + return { + store: createRemoteClustersStore, + memoryRouter: { + onRouter: (router: AppRouter) => registerRouter(router), + }, + defaultProps: { isCloudEnabled }, + }; +}; + +const initTestBed = (isCloudEnabled: boolean) => + registerTestBed(ComponentWithContext, testBedConfig({ isCloudEnabled }))(); + +export const setup = async (isCloudEnabled = false) => { + const testBed = await initTestBed(isCloudEnabled); + + return { + ...testBed, + actions: { + ...createRemoteClustersActions(testBed), + }, + }; +}; diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.test.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.test.js deleted file mode 100644 index 40abde35835f..000000000000 --- a/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.test.js +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { act } from 'react-dom/test-utils'; - -import { setupEnvironment } from '../helpers'; -import { NON_ALPHA_NUMERIC_CHARS, ACCENTED_CHARS } from './special_characters'; -import { setup } from './remote_clusters_add.helpers'; - -describe('Create Remote cluster', () => { - describe('on component mount', () => { - let find; - let exists; - let actions; - let form; - let server; - let component; - - beforeAll(() => { - ({ server } = setupEnvironment()); - }); - - afterAll(() => { - server.restore(); - }); - - beforeEach(async () => { - await act(async () => { - ({ form, exists, find, actions, component } = setup()); - }); - component.update(); - }); - - test('should have the title of the page set correctly', () => { - expect(exists('remoteClusterPageTitle')).toBe(true); - expect(find('remoteClusterPageTitle').text()).toEqual('Add remote cluster'); - }); - - test('should have a link to the documentation', () => { - expect(exists('remoteClusterDocsButton')).toBe(true); - }); - - test('should have a toggle to Skip unavailable remote cluster', () => { - expect(exists('remoteClusterFormSkipUnavailableFormToggle')).toBe(true); - - // By default it should be set to "false" - expect(find('remoteClusterFormSkipUnavailableFormToggle').props()['aria-checked']).toBe( - false - ); - - act(() => { - form.toggleEuiSwitch('remoteClusterFormSkipUnavailableFormToggle'); - }); - - component.update(); - - expect(find('remoteClusterFormSkipUnavailableFormToggle').props()['aria-checked']).toBe(true); - }); - - test('should have a toggle to enable "proxy" mode for a remote cluster', () => { - expect(exists('remoteClusterFormConnectionModeToggle')).toBe(true); - - // By default it should be set to "false" - expect(find('remoteClusterFormConnectionModeToggle').props()['aria-checked']).toBe(false); - - act(() => { - form.toggleEuiSwitch('remoteClusterFormConnectionModeToggle'); - }); - - component.update(); - - expect(find('remoteClusterFormConnectionModeToggle').props()['aria-checked']).toBe(true); - }); - - test('should display errors and disable the save button when clicking "save" without filling the form', async () => { - expect(exists('remoteClusterFormGlobalError')).toBe(false); - expect(find('remoteClusterFormSaveButton').props().disabled).toBe(false); - - await actions.clickSaveForm(); - - expect(exists('remoteClusterFormGlobalError')).toBe(true); - expect(form.getErrorsMessages()).toEqual([ - 'Name is required.', - 'At least one seed node is required.', - ]); - expect(find('remoteClusterFormSaveButton').props().disabled).toBe(true); - }); - }); - - describe('form validation', () => { - describe('remote cluster name', () => { - let component; - let actions; - let form; - - beforeEach(async () => { - await act(async () => { - ({ component, form, actions } = setup()); - }); - - component.update(); - }); - - test('should not allow spaces', async () => { - form.setInputValue('remoteClusterFormNameInput', 'with space'); - - await actions.clickSaveForm(); - - expect(form.getErrorsMessages()).toContain('Spaces are not allowed in the name.'); - }); - - test('should only allow alpha-numeric characters, "-" (dash) and "_" (underscore)', async () => { - const expectInvalidChar = (char) => { - if (char === '-' || char === '_') { - return; - } - - try { - form.setInputValue('remoteClusterFormNameInput', `with${char}`); - - expect(form.getErrorsMessages()).toContain( - `Remove the character ${char} from the name.` - ); - } catch { - throw Error(`Char "${char}" expected invalid but was allowed`); - } - }; - - await actions.clickSaveForm(); // display form errors - - [...NON_ALPHA_NUMERIC_CHARS, ...ACCENTED_CHARS].forEach(expectInvalidChar); - }); - }); - - describe('seeds', () => { - let actions; - let form; - let component; - - beforeEach(async () => { - await act(async () => { - ({ form, actions, component } = setup()); - }); - - component.update(); - - form.setInputValue('remoteClusterFormNameInput', 'remote_cluster_test'); - }); - - test('should only allow alpha-numeric characters and "-" (dash) in the node "host" part', async () => { - await actions.clickSaveForm(); // display form errors - - const notInArray = (array) => (value) => array.indexOf(value) < 0; - - const expectInvalidChar = (char) => { - form.setComboBoxValue('remoteClusterFormSeedsInput', `192.16${char}:3000`); - expect(form.getErrorsMessages()).toContain( - `Seed node must use host:port format. Example: 127.0.0.1:9400, localhost:9400. Hosts can only consist of letters, numbers, and dashes.` - ); - }; - - [...NON_ALPHA_NUMERIC_CHARS, ...ACCENTED_CHARS] - .filter(notInArray(['-', '_', ':'])) - .forEach(expectInvalidChar); - }); - - test('should require a numeric "port" to be set', async () => { - await actions.clickSaveForm(); - - form.setComboBoxValue('remoteClusterFormSeedsInput', '192.168.1.1'); - expect(form.getErrorsMessages()).toContain('A port is required.'); - - form.setComboBoxValue('remoteClusterFormSeedsInput', '192.168.1.1:abc'); - expect(form.getErrorsMessages()).toContain('A port is required.'); - }); - }); - - describe('proxy address', () => { - let actions; - let form; - let component; - - beforeEach(async () => { - await act(async () => { - ({ form, actions, component } = setup()); - }); - - component.update(); - - act(() => { - // Enable "proxy" mode - form.toggleEuiSwitch('remoteClusterFormConnectionModeToggle'); - }); - - component.update(); - }); - - test('should only allow alpha-numeric characters and "-" (dash) in the proxy address "host" part', async () => { - await actions.clickSaveForm(); // display form errors - - const notInArray = (array) => (value) => array.indexOf(value) < 0; - - const expectInvalidChar = (char) => { - form.setInputValue('remoteClusterFormProxyAddressInput', `192.16${char}:3000`); - expect(form.getErrorsMessages()).toContain( - 'Address must use host:port format. Example: 127.0.0.1:9400, localhost:9400. Hosts can only consist of letters, numbers, and dashes.' - ); - }; - - [...NON_ALPHA_NUMERIC_CHARS, ...ACCENTED_CHARS] - .filter(notInArray(['-', '_', ':'])) - .forEach(expectInvalidChar); - }); - - test('should require a numeric "port" to be set', async () => { - await actions.clickSaveForm(); - - form.setInputValue('remoteClusterFormProxyAddressInput', '192.168.1.1'); - expect(form.getErrorsMessages()).toContain('A port is required.'); - - form.setInputValue('remoteClusterFormProxyAddressInput', '192.168.1.1:abc'); - expect(form.getErrorsMessages()).toContain('A port is required.'); - }); - }); - }); -}); diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.test.ts b/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.test.ts new file mode 100644 index 000000000000..0727bc0c9ba2 --- /dev/null +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/add/remote_clusters_add.test.ts @@ -0,0 +1,260 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SinonFakeServer } from 'sinon'; +import { TestBed } from '@kbn/test/jest'; +import { act } from 'react-dom/test-utils'; + +import { setupEnvironment, RemoteClustersActions } from '../helpers'; +import { setup } from './remote_clusters_add.helpers'; +import { NON_ALPHA_NUMERIC_CHARS, ACCENTED_CHARS } from './special_characters'; + +const notInArray = (array: string[]) => (value: string) => array.indexOf(value) < 0; + +let component: TestBed['component']; +let actions: RemoteClustersActions; +let server: SinonFakeServer; + +describe('Create Remote cluster', () => { + beforeAll(() => { + ({ server } = setupEnvironment()); + }); + + afterAll(() => { + server.restore(); + }); + + beforeEach(async () => { + await act(async () => { + ({ actions, component } = await setup()); + }); + component.update(); + }); + + describe('on component mount', () => { + test('should have the title of the page set correctly', () => { + expect(actions.pageTitle.exists()).toBe(true); + expect(actions.pageTitle.text()).toEqual('Add remote cluster'); + }); + + test('should have a link to the documentation', () => { + expect(actions.docsButtonExists()).toBe(true); + }); + + test('should have a toggle to Skip unavailable remote cluster', () => { + expect(actions.skipUnavailableSwitch.exists()).toBe(true); + + // By default it should be set to "false" + expect(actions.skipUnavailableSwitch.isChecked()).toBe(false); + + actions.skipUnavailableSwitch.toggle(); + + expect(actions.skipUnavailableSwitch.isChecked()).toBe(true); + }); + + describe('on prem', () => { + test('should have a toggle to enable "proxy" mode for a remote cluster', () => { + expect(actions.connectionModeSwitch.exists()).toBe(true); + + // By default it should be set to "false" + expect(actions.connectionModeSwitch.isChecked()).toBe(false); + + actions.connectionModeSwitch.toggle(); + + expect(actions.connectionModeSwitch.isChecked()).toBe(true); + }); + + test('server name has optional label', () => { + actions.connectionModeSwitch.toggle(); + expect(actions.serverNameInput.getLabel()).toBe('Server name (optional)'); + }); + + test('should display errors and disable the save button when clicking "save" without filling the form', async () => { + expect(actions.globalErrorExists()).toBe(false); + expect(actions.saveButton.isDisabled()).toBe(false); + + await actions.saveButton.click(); + + expect(actions.globalErrorExists()).toBe(true); + expect(actions.getErrorMessages()).toEqual([ + 'Name is required.', + // seeds input is switched on by default on prem and is required + 'At least one seed node is required.', + ]); + expect(actions.saveButton.isDisabled()).toBe(true); + }); + + test('renders no switch for cloud url input and proxy address + server name input modes', () => { + expect(actions.cloudUrlSwitch.exists()).toBe(false); + }); + }); + describe('on cloud', () => { + beforeEach(async () => { + await act(async () => { + ({ actions, component } = await setup(true)); + }); + + component.update(); + }); + + test('renders a switch between cloud url input and proxy address + server name input for proxy connection', () => { + expect(actions.cloudUrlSwitch.exists()).toBe(true); + }); + + test('renders no switch between sniff and proxy modes', () => { + expect(actions.connectionModeSwitch.exists()).toBe(false); + }); + test('defaults to cloud url input for proxy connection', () => { + expect(actions.cloudUrlSwitch.isChecked()).toBe(false); + }); + test('server name has no optional label', () => { + actions.cloudUrlSwitch.toggle(); + expect(actions.serverNameInput.getLabel()).toBe('Server name'); + }); + }); + }); + describe('form validation', () => { + describe('remote cluster name', () => { + test('should not allow spaces', async () => { + actions.nameInput.setValue('with space'); + + await actions.saveButton.click(); + + expect(actions.getErrorMessages()).toContain('Spaces are not allowed in the name.'); + }); + + test('should only allow alpha-numeric characters, "-" (dash) and "_" (underscore)', async () => { + const expectInvalidChar = (char: string) => { + if (char === '-' || char === '_') { + return; + } + + try { + actions.nameInput.setValue(`with${char}`); + + expect(actions.getErrorMessages()).toContain( + `Remove the character ${char} from the name.` + ); + } catch { + throw Error(`Char "${char}" expected invalid but was allowed`); + } + }; + + await actions.saveButton.click(); // display form errors + + [...NON_ALPHA_NUMERIC_CHARS, ...ACCENTED_CHARS].forEach(expectInvalidChar); + }); + }); + + describe('proxy address', () => { + beforeEach(async () => { + await act(async () => { + ({ actions, component } = await setup()); + }); + + component.update(); + + actions.connectionModeSwitch.toggle(); + }); + + test('should only allow alpha-numeric characters and "-" (dash) in the proxy address "host" part', async () => { + await actions.saveButton.click(); // display form errors + + const expectInvalidChar = (char: string) => { + actions.proxyAddressInput.setValue(`192.16${char}:3000`); + expect(actions.getErrorMessages()).toContain( + 'Address must use host:port format. Example: 127.0.0.1:9400, localhost:9400. Hosts can only consist of letters, numbers, and dashes.' + ); + }; + + [...NON_ALPHA_NUMERIC_CHARS, ...ACCENTED_CHARS] + .filter(notInArray(['-', '_', ':'])) + .forEach(expectInvalidChar); + }); + + test('should require a numeric "port" to be set', async () => { + await actions.saveButton.click(); + + actions.proxyAddressInput.setValue('192.168.1.1'); + expect(actions.getErrorMessages()).toContain('A port is required.'); + + actions.proxyAddressInput.setValue('192.168.1.1:abc'); + expect(actions.getErrorMessages()).toContain('A port is required.'); + }); + }); + + describe('on prem', () => { + beforeEach(async () => { + await act(async () => { + ({ actions, component } = await setup()); + }); + + component.update(); + + actions.nameInput.setValue('remote_cluster_test'); + }); + + describe('seeds', () => { + test('should only allow alpha-numeric characters and "-" (dash) in the node "host" part', async () => { + await actions.saveButton.click(); // display form errors + + const expectInvalidChar = (char: string) => { + actions.seedsInput.setValue(`192.16${char}:3000`); + expect(actions.getErrorMessages()).toContain( + `Seed node must use host:port format. Example: 127.0.0.1:9400, localhost:9400. Hosts can only consist of letters, numbers, and dashes.` + ); + }; + + [...NON_ALPHA_NUMERIC_CHARS, ...ACCENTED_CHARS] + .filter(notInArray(['-', '_', ':'])) + .forEach(expectInvalidChar); + }); + + test('should require a numeric "port" to be set', async () => { + await actions.saveButton.click(); + + actions.seedsInput.setValue('192.168.1.1'); + expect(actions.getErrorMessages()).toContain('A port is required.'); + + actions.seedsInput.setValue('192.168.1.1:abc'); + expect(actions.getErrorMessages()).toContain('A port is required.'); + }); + }); + + test('server name is optional (proxy connection)', () => { + actions.connectionModeSwitch.toggle(); + actions.saveButton.click(); + expect(actions.getErrorMessages()).toEqual(['A proxy address is required.']); + }); + }); + + describe('on cloud', () => { + beforeEach(async () => { + await act(async () => { + ({ actions, component } = await setup(true)); + }); + + component.update(); + }); + + test('cloud url is required since cloud url input is enabled by default', () => { + actions.saveButton.click(); + expect(actions.getErrorMessages()).toContain('A url is required.'); + }); + + test('proxy address and server name are required when cloud url input is disabled', () => { + actions.cloudUrlSwitch.toggle(); + actions.saveButton.click(); + expect(actions.getErrorMessages()).toEqual([ + 'Name is required.', + 'A proxy address is required.', + 'A server name is required.', + ]); + }); + }); + }); +}); diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/add/special_characters.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/add/special_characters.ts similarity index 100% rename from x-pack/plugins/remote_clusters/__jest__/client_integration/add/special_characters.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/add/special_characters.ts diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.helpers.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.helpers.js deleted file mode 100644 index 094fb5056e98..000000000000 --- a/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.helpers.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { registerTestBed } from '@kbn/test/jest'; - -import { RemoteClusterEdit } from '../../../public/application/sections/remote_cluster_edit'; -import { createRemoteClustersStore } from '../../../public/application/store'; -import { registerRouter } from '../../../public/application/services/routing'; - -export const REMOTE_CLUSTER_EDIT_NAME = 'new-york'; - -export const REMOTE_CLUSTER_EDIT = { - name: REMOTE_CLUSTER_EDIT_NAME, - seeds: ['localhost:9400'], - skipUnavailable: true, -}; - -const testBedConfig = { - store: createRemoteClustersStore, - memoryRouter: { - onRouter: (router) => registerRouter(router), - // The remote cluster name to edit is read from the router ":id" param - // so we first set it in our initial entries - initialEntries: [`/${REMOTE_CLUSTER_EDIT_NAME}`], - // and then we declarae the :id param on the component route path - componentRoutePath: '/:name', - }, -}; - -export const setup = registerTestBed(RemoteClusterEdit, testBedConfig); diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.helpers.tsx b/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.helpers.tsx new file mode 100644 index 000000000000..2259396bf33f --- /dev/null +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.helpers.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { registerTestBed, TestBedConfig } from '@kbn/test/jest'; + +import React from 'react'; +import { RemoteClusterEdit } from '../../../public/application/sections'; +import { createRemoteClustersStore } from '../../../public/application/store'; +import { AppRouter, registerRouter } from '../../../public/application/services'; +import { createRemoteClustersActions } from '../helpers'; +import { AppContextProvider } from '../../../public/application/app_context'; + +export const REMOTE_CLUSTER_EDIT_NAME = 'new-york'; + +export const REMOTE_CLUSTER_EDIT = { + name: REMOTE_CLUSTER_EDIT_NAME, + seeds: ['localhost:9400'], + skipUnavailable: true, +}; + +const ComponentWithContext = (props: { isCloudEnabled: boolean }) => { + const { isCloudEnabled, ...rest } = props; + return ( + + + + ); +}; + +const testBedConfig: TestBedConfig = { + store: createRemoteClustersStore, + memoryRouter: { + onRouter: (router: AppRouter) => registerRouter(router), + // The remote cluster name to edit is read from the router ":id" param + // so we first set it in our initial entries + initialEntries: [`/${REMOTE_CLUSTER_EDIT_NAME}`], + // and then we declare the :id param on the component route path + componentRoutePath: '/:name', + }, +}; + +const initTestBed = (isCloudEnabled: boolean) => + registerTestBed(ComponentWithContext, testBedConfig)({ isCloudEnabled }); + +export const setup = async (isCloudEnabled = false) => { + const testBed = await initTestBed(isCloudEnabled); + + return { + ...testBed, + actions: { + ...createRemoteClustersActions(testBed), + }, + }; +}; diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.test.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.test.js deleted file mode 100644 index 19dd468cb76c..000000000000 --- a/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.test.js +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { act } from 'react-dom/test-utils'; - -import { RemoteClusterForm } from '../../../public/application/sections/components/remote_cluster_form'; -import { setupEnvironment } from '../helpers'; -import { setup as setupRemoteClustersAdd } from '../add/remote_clusters_add.helpers'; -import { - setup, - REMOTE_CLUSTER_EDIT, - REMOTE_CLUSTER_EDIT_NAME, -} from './remote_clusters_edit.helpers'; - -describe('Edit Remote cluster', () => { - let component; - let find; - let exists; - - const { server, httpRequestsMockHelpers } = setupEnvironment(); - - afterAll(() => { - server.restore(); - }); - - httpRequestsMockHelpers.setLoadRemoteClustersResponse([REMOTE_CLUSTER_EDIT]); - - beforeEach(async () => { - await act(async () => { - ({ component, find, exists } = setup()); - }); - component.update(); - }); - - test('should have the title of the page set correctly', () => { - expect(exists('remoteClusterPageTitle')).toBe(true); - expect(find('remoteClusterPageTitle').text()).toEqual('Edit remote cluster'); - }); - - test('should have a link to the documentation', () => { - expect(exists('remoteClusterDocsButton')).toBe(true); - }); - - /** - * As the "edit" remote cluster component uses the same form underneath that - * the "create" remote cluster, we won't test it again but simply make sure that - * the form component is indeed shared between the 2 app sections. - */ - test('should use the same Form component as the "" component', async () => { - let addRemoteClusterTestBed; - - await act(async () => { - addRemoteClusterTestBed = setupRemoteClustersAdd(); - }); - - addRemoteClusterTestBed.component.update(); - - const formEdit = component.find(RemoteClusterForm); - const formAdd = addRemoteClusterTestBed.component.find(RemoteClusterForm); - - expect(formEdit.length).toBe(1); - expect(formAdd.length).toBe(1); - }); - - test('should populate the form fields with the values from the remote cluster loaded', () => { - expect(find('remoteClusterFormNameInput').props().value).toBe(REMOTE_CLUSTER_EDIT_NAME); - expect(find('remoteClusterFormSeedsInput').text()).toBe(REMOTE_CLUSTER_EDIT.seeds.join('')); - expect(find('remoteClusterFormSkipUnavailableFormToggle').props()['aria-checked']).toBe( - REMOTE_CLUSTER_EDIT.skipUnavailable - ); - }); - - test('should disable the form name input', () => { - expect(find('remoteClusterFormNameInput').props().disabled).toBe(true); - }); -}); diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.test.tsx b/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.test.tsx new file mode 100644 index 000000000000..2913de94bc2d --- /dev/null +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/edit/remote_clusters_edit.test.tsx @@ -0,0 +1,141 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { act } from 'react-dom/test-utils'; +import { TestBed } from '@kbn/test/jest'; + +import { RemoteClusterForm } from '../../../public/application/sections/components/remote_cluster_form'; +import { RemoteClustersActions, setupEnvironment } from '../helpers'; +import { setup as setupRemoteClustersAdd } from '../add/remote_clusters_add.helpers'; +import { + setup, + REMOTE_CLUSTER_EDIT, + REMOTE_CLUSTER_EDIT_NAME, +} from './remote_clusters_edit.helpers'; +import { Cluster } from '../../../common/lib'; + +let component: TestBed['component']; +let actions: RemoteClustersActions; +const { server, httpRequestsMockHelpers } = setupEnvironment(); + +describe('Edit Remote cluster', () => { + afterAll(() => { + server.restore(); + }); + + httpRequestsMockHelpers.setLoadRemoteClustersResponse([REMOTE_CLUSTER_EDIT]); + + beforeEach(async () => { + await act(async () => { + ({ component, actions } = await setup()); + }); + component.update(); + }); + + test('should have the title of the page set correctly', () => { + expect(actions.pageTitle.exists()).toBe(true); + expect(actions.pageTitle.text()).toEqual('Edit remote cluster'); + }); + + test('should have a link to the documentation', () => { + expect(actions.docsButtonExists()).toBe(true); + }); + + /** + * As the "edit" remote cluster component uses the same form underneath that + * the "create" remote cluster, we won't test it again but simply make sure that + * the form component is indeed shared between the 2 app sections. + */ + test('should use the same Form component as the "" component', async () => { + let addRemoteClusterTestBed: TestBed; + + await act(async () => { + addRemoteClusterTestBed = await setupRemoteClustersAdd(); + }); + + addRemoteClusterTestBed!.component.update(); + + const formEdit = component.find(RemoteClusterForm); + const formAdd = addRemoteClusterTestBed!.component.find(RemoteClusterForm); + + expect(formEdit.length).toBe(1); + expect(formAdd.length).toBe(1); + }); + + test('should populate the form fields with the values from the remote cluster loaded', () => { + expect(actions.nameInput.getValue()).toBe(REMOTE_CLUSTER_EDIT_NAME); + // seeds input for sniff connection is not shown on Cloud + expect(actions.seedsInput.getValue()).toBe(REMOTE_CLUSTER_EDIT.seeds.join('')); + expect(actions.skipUnavailableSwitch.isChecked()).toBe(REMOTE_CLUSTER_EDIT.skipUnavailable); + }); + + test('should disable the form name input', () => { + expect(actions.nameInput.isDisabled()).toBe(true); + }); + + describe('on cloud', () => { + const cloudUrl = 'cloud-url'; + const defaultCloudPort = '9400'; + test('existing cluster that defaults to cloud url (default port)', async () => { + const cluster: Cluster = { + name: REMOTE_CLUSTER_EDIT_NAME, + mode: 'proxy', + proxyAddress: `${cloudUrl}:${defaultCloudPort}`, + serverName: cloudUrl, + }; + httpRequestsMockHelpers.setLoadRemoteClustersResponse([cluster]); + + await act(async () => { + ({ component, actions } = await setup(true)); + }); + component.update(); + + expect(actions.cloudUrlInput.exists()).toBe(true); + expect(actions.cloudUrlInput.getValue()).toBe(cloudUrl); + }); + + test('existing cluster that defaults to manual input (non-default port)', async () => { + const cluster: Cluster = { + name: REMOTE_CLUSTER_EDIT_NAME, + mode: 'proxy', + proxyAddress: `${cloudUrl}:9500`, + serverName: cloudUrl, + }; + httpRequestsMockHelpers.setLoadRemoteClustersResponse([cluster]); + + await act(async () => { + ({ component, actions } = await setup(true)); + }); + component.update(); + + expect(actions.cloudUrlInput.exists()).toBe(false); + + expect(actions.proxyAddressInput.exists()).toBe(true); + expect(actions.serverNameInput.exists()).toBe(true); + }); + + test('existing cluster that defaults to manual input (proxy address is different from server name)', async () => { + const cluster: Cluster = { + name: REMOTE_CLUSTER_EDIT_NAME, + mode: 'proxy', + proxyAddress: `${cloudUrl}:${defaultCloudPort}`, + serverName: 'another-value', + }; + httpRequestsMockHelpers.setLoadRemoteClustersResponse([cluster]); + + await act(async () => { + ({ component, actions } = await setup(true)); + }); + component.update(); + + expect(actions.cloudUrlInput.exists()).toBe(false); + + expect(actions.proxyAddressInput.exists()).toBe(true); + expect(actions.serverNameInput.exists()).toBe(true); + }); + }); +}); diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/http_requests.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/http_requests.ts similarity index 63% rename from x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/http_requests.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/http_requests.ts index 304ec51986ab..3ebe3ab5738d 100644 --- a/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/http_requests.js +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/http_requests.ts @@ -5,25 +5,24 @@ * 2.0. */ -import sinon from 'sinon'; +import sinon, { SinonFakeServer } from 'sinon'; +import { Cluster } from '../../../common/lib'; // Register helpers to mock HTTP Requests -const registerHttpRequestMockHelpers = (server) => { - const mockResponse = (response) => [ +const registerHttpRequestMockHelpers = (server: SinonFakeServer) => { + const mockResponse = (response: Cluster[] | { itemsDeleted: string[]; errors: string[] }) => [ 200, { 'Content-Type': 'application/json' }, JSON.stringify(response), ]; - const setLoadRemoteClustersResponse = (response) => { - server.respondWith('GET', '/api/remote_clusters', [ - 200, - { 'Content-Type': 'application/json' }, - JSON.stringify(response), - ]); + const setLoadRemoteClustersResponse = (response: Cluster[] = []) => { + server.respondWith('GET', '/api/remote_clusters', mockResponse(response)); }; - const setDeleteRemoteClusterResponse = (response) => { + const setDeleteRemoteClusterResponse = ( + response: { itemsDeleted: string[]; errors: string[] } = { itemsDeleted: [], errors: [] } + ) => { server.respondWith('DELETE', /api\/remote_clusters/, mockResponse(response)); }; diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/index.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/index.ts similarity index 80% rename from x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/index.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/index.ts index 63084b21e390..cf859ff6913f 100644 --- a/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/index.js +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/index.ts @@ -7,3 +7,4 @@ export { nextTick, getRandomString, findTestSubject } from '@kbn/test/jest'; export { setupEnvironment } from './setup_environment'; +export { createRemoteClustersActions, RemoteClustersActions } from './remote_clusters_actions'; diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_actions.ts b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_actions.ts new file mode 100644 index 000000000000..ba0c42479383 --- /dev/null +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/remote_clusters_actions.ts @@ -0,0 +1,199 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TestBed } from '@kbn/test/jest'; +import { act } from 'react-dom/test-utils'; +export interface RemoteClustersActions { + docsButtonExists: () => boolean; + pageTitle: { + exists: () => boolean; + text: () => string; + }; + nameInput: { + setValue: (name: string) => void; + getValue: () => string; + isDisabled: () => boolean; + }; + skipUnavailableSwitch: { + exists: () => boolean; + toggle: () => void; + isChecked: () => boolean; + }; + connectionModeSwitch: { + exists: () => boolean; + toggle: () => void; + isChecked: () => boolean; + }; + cloudUrlSwitch: { + toggle: () => void; + exists: () => boolean; + isChecked: () => boolean; + }; + cloudUrlInput: { + exists: () => boolean; + getValue: () => string; + }; + seedsInput: { + setValue: (seed: string) => void; + getValue: () => string; + }; + proxyAddressInput: { + setValue: (proxyAddress: string) => void; + exists: () => boolean; + }; + serverNameInput: { + getLabel: () => string; + exists: () => boolean; + }; + saveButton: { + click: () => void; + isDisabled: () => boolean; + }; + getErrorMessages: () => string[]; + globalErrorExists: () => boolean; +} +export const createRemoteClustersActions = (testBed: TestBed): RemoteClustersActions => { + const { form, exists, find, component } = testBed; + + const docsButtonExists = () => exists('remoteClusterDocsButton'); + const createPageTitleActions = () => { + const pageTitleSelector = 'remoteClusterPageTitle'; + return { + pageTitle: { + exists: () => exists(pageTitleSelector), + text: () => find(pageTitleSelector).text(), + }, + }; + }; + const createNameInputActions = () => { + const nameInputSelector = 'remoteClusterFormNameInput'; + return { + nameInput: { + setValue: (name: string) => form.setInputValue(nameInputSelector, name), + getValue: () => find(nameInputSelector).props().value, + isDisabled: () => find(nameInputSelector).props().disabled, + }, + }; + }; + + const createSkipUnavailableActions = () => { + const skipUnavailableToggleSelector = 'remoteClusterFormSkipUnavailableFormToggle'; + return { + skipUnavailableSwitch: { + exists: () => exists(skipUnavailableToggleSelector), + toggle: () => { + act(() => { + form.toggleEuiSwitch(skipUnavailableToggleSelector); + }); + component.update(); + }, + isChecked: () => find(skipUnavailableToggleSelector).props()['aria-checked'], + }, + }; + }; + + const createConnectionModeActions = () => { + const connectionModeToggleSelector = 'remoteClusterFormConnectionModeToggle'; + return { + connectionModeSwitch: { + exists: () => exists(connectionModeToggleSelector), + toggle: () => { + act(() => { + form.toggleEuiSwitch(connectionModeToggleSelector); + }); + component.update(); + }, + isChecked: () => find(connectionModeToggleSelector).props()['aria-checked'], + }, + }; + }; + + const createCloudUrlSwitchActions = () => { + const cloudUrlSelector = 'remoteClusterFormCloudUrlToggle'; + return { + cloudUrlSwitch: { + exists: () => exists(cloudUrlSelector), + toggle: () => { + act(() => { + form.toggleEuiSwitch(cloudUrlSelector); + }); + component.update(); + }, + isChecked: () => find(cloudUrlSelector).props()['aria-checked'], + }, + }; + }; + + const createSeedsInputActions = () => { + const seedsInputSelector = 'remoteClusterFormSeedsInput'; + return { + seedsInput: { + setValue: (seed: string) => form.setComboBoxValue(seedsInputSelector, seed), + getValue: () => find(seedsInputSelector).text(), + }, + }; + }; + + const createProxyAddressActions = () => { + const proxyAddressSelector = 'remoteClusterFormProxyAddressInput'; + return { + proxyAddressInput: { + setValue: (proxyAddress: string) => form.setInputValue(proxyAddressSelector, proxyAddress), + exists: () => exists(proxyAddressSelector), + }, + }; + }; + + const createSaveButtonActions = () => { + const click = () => { + act(() => { + find('remoteClusterFormSaveButton').simulate('click'); + }); + + component.update(); + }; + const isDisabled = () => find('remoteClusterFormSaveButton').props().disabled; + return { saveButton: { click, isDisabled } }; + }; + + const createServerNameActions = () => { + const serverNameSelector = 'remoteClusterFormServerNameFormRow'; + return { + serverNameInput: { + getLabel: () => find('remoteClusterFormServerNameFormRow').find('label').text(), + exists: () => exists(serverNameSelector), + }, + }; + }; + + const globalErrorExists = () => exists('remoteClusterFormGlobalError'); + + const createCloudUrlInputActions = () => { + const cloudUrlInputSelector = 'remoteClusterFormCloudUrlInput'; + return { + cloudUrlInput: { + exists: () => exists(cloudUrlInputSelector), + getValue: () => find(cloudUrlInputSelector).props().value, + }, + }; + }; + return { + docsButtonExists, + ...createPageTitleActions(), + ...createNameInputActions(), + ...createSkipUnavailableActions(), + ...createConnectionModeActions(), + ...createCloudUrlSwitchActions(), + ...createSeedsInputActions(), + ...createCloudUrlInputActions(), + ...createProxyAddressActions(), + ...createServerNameActions(), + ...createSaveButtonActions(), + getErrorMessages: form.getErrorsMessages, + globalErrorExists, + }; +}; diff --git a/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.ts similarity index 95% rename from x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js rename to x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.ts index 97ad344a63cc..084552c5e6ab 100644 --- a/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.js +++ b/x-pack/plugins/remote_clusters/__jest__/client_integration/helpers/setup_environment.ts @@ -36,6 +36,8 @@ export const setupEnvironment = () => { notificationServiceMock.createSetupContract().toasts, fatalErrorsServiceMock.createSetupContract() ); + // This expects HttpSetup but we're giving it AxiosInstance. + // @ts-ignore initHttp(mockHttpClient); const { server, httpRequestsMockHelpers } = initHttpRequests(); diff --git a/x-pack/plugins/remote_clusters/public/application/app_context.tsx b/x-pack/plugins/remote_clusters/public/application/app_context.tsx index 7931001c6fae..528ec322f49e 100644 --- a/x-pack/plugins/remote_clusters/public/application/app_context.tsx +++ b/x-pack/plugins/remote_clusters/public/application/app_context.tsx @@ -5,10 +5,11 @@ * 2.0. */ -import React, { createContext } from 'react'; +import React, { createContext, useContext } from 'react'; export interface Context { isCloudEnabled: boolean; + cloudBaseUrl: string; } export const AppContext = createContext({} as any); @@ -22,3 +23,10 @@ export const AppContextProvider = ({ }) => { return {children}; }; + +export const useAppContext = () => { + const ctx = useContext(AppContext); + if (!ctx) throw new Error('Cannot use outside of app context'); + + return ctx; +}; diff --git a/x-pack/plugins/remote_clusters/public/application/index.d.ts b/x-pack/plugins/remote_clusters/public/application/index.d.ts index 167297cedf55..45f981b5f2bc 100644 --- a/x-pack/plugins/remote_clusters/public/application/index.d.ts +++ b/x-pack/plugins/remote_clusters/public/application/index.d.ts @@ -12,7 +12,8 @@ export declare const renderApp: ( elem: HTMLElement | null, I18nContext: I18nStart['Context'], appDependencies: { - isCloudEnabled?: boolean; + isCloudEnabled: boolean; + cloudBaseUrl: string; }, history: ScopedHistory ) => ReturnType; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap deleted file mode 100644 index 5f09193be90c..000000000000 --- a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/__snapshots__/remote_cluster_form.test.js.snap +++ /dev/null @@ -1,2017 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`RemoteClusterForm proxy mode renders correct connection settings when user enables proxy mode 1`] = ` - - -
- - } - fullWidth={true} - title={ - -

- -

-
- } - > -
- -
- -
- - -

- - Name - -

-
-
- -
- -
- - A unique name for the cluster. - -
-
-
-
-
-
- -
- - } - fullWidth={true} - hasChildLabel={true} - hasEmptyLabelSpace={false} - helpText={ - - } - isInvalid={false} - label={ - - } - labelType="label" - > -
-
- - - -
-
- - -
-
- - - - -
-
-
-
- -
- - Name can only contain letters, numbers, underscores, and dashes. - -
-
-
-
-
-
-
-
-
-
-
- - - - - } - onChange={[Function]} - /> - - - } - fullWidth={true} - title={ - -

- -

-
- } - > -
- -
- -
- - -

- - Connection mode - -

-
-
- -
- -
- - Use seed nodes by default, or switch to proxy mode. - - -
-
- - } - onBlur={[Function]} - onChange={[Function]} - onFocus={[Function]} - > -
- - - - Use proxy mode - - -
-
-
-
-
-
-
-
-
-
-
- -
- - } - fullWidth={true} - hasChildLabel={true} - hasEmptyLabelSpace={false} - helpText={ - - } - isInvalid={false} - label={ - - } - labelType="label" - > -
-
- - - -
-
- - -
-
- - - - -
-
-
-
- -
- - The address to use for remote connections. - -
-
-
-
-
- - - , - } - } - /> - } - isInvalid={false} - label={ - - } - labelType="label" - > -
-
- - - -
-
- - -
-
- - - - -
-
-
-
- -
- - - , - } - } - > - A string sent in the server_name field of the TLS Server Name Indication extension if TLS is enabled. - - - - -
-
-
-
-
- - } - label={ - - } - labelType="label" - > -
-
- - - -
-
- - -
-
- - - - -
-
-
-
- -
- - The number of socket connections to open per remote cluster. - -
-
-
-
-
-
-
-
-
-
-
- -

- - - , - "optionName": - - , - } - } - /> -

- - } - fullWidth={true} - title={ - -

- -

-
- } - > -
- -
- -
- - -

- - Make remote cluster optional - -

-
-
- -
- -
-

- - - , - "optionName": - - , - } - } - > - A request fails if any of the queried remote clusters are unavailable. To send requests to other remote clusters if this cluster is unavailable, enable - - - Skip if unavailable - - - . - - - - -

-
-
-
-
-
-
- -
- -
-
- -
- - - Skip if unavailable - -
-
-
-
-
-
-
-
-
-
-
-
-
- -
- - -
- -
- -
- -
- - - - - -
-
-
-
-
-
- -
- - - -
-
-
-
- -`; - -exports[`RemoteClusterForm renders untouched state 1`] = ` -Array [ -
-
-
-
-

- Name -

-
-
- A unique name for the cluster. -
-
-
-
-
-
- -
-
-
-
- -
-
-
- Name can only contain letters, numbers, underscores, and dashes. -
-
-
-
-
-
-
-
-
-

- Connection mode -

-
-
- Use seed nodes by default, or switch to proxy mode. -
-
-
- - - Use proxy mode - -
-
-
-
-
-
-
-
-
- -
-
- -
-
-
- -
-
-
-
- -
-
-
- The number of gateway nodes to connect to for this cluster. -
-
-
-
-
-
-
-
-
-

- Make remote cluster optional -

-
-
-

- A request fails if any of the queried remote clusters are unavailable. To send requests to other remote clusters if this cluster is unavailable, enable - - Skip if unavailable - - . - -

-
-
-
-
-
-
-
- - - Skip if unavailable - -
-
-
-
-
-
-
, -
, -
-
-
-
- -
-
-
-
- -
-
, -] -`; - -exports[`RemoteClusterForm validation renders invalid state and a global form error when the user tries to submit an invalid form 1`] = ` -Array [ -
-
- -
-
-
-
- -
-
-
- Name is required. -
-
- Name can only contain letters, numbers, underscores, and dashes. -
-
-
, -
-
- -
-
- -
, -
-
-
- - - Skip if unavailable - -
-
-
, -
, -] -`; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/cloud_url_help.tsx b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/cloud_url_help.tsx new file mode 100644 index 000000000000..1d4862ff094c --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/cloud_url_help.tsx @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiLink, EuiPopover, EuiPopoverTitle, EuiText } from '@elastic/eui'; +import { useAppContext } from '../../../../app_context'; + +export const CloudUrlHelp: FunctionComponent = () => { + const [isOpen, setIsOpen] = useState(false); + const { cloudBaseUrl } = useAppContext(); + return ( + + { + setIsOpen(!isOpen); + }} + > + + + + } + isOpen={isOpen} + closePopover={() => setIsOpen(false)} + anchorPosition="upCenter" + > + + + + + + + + ), + elasticsearch: Elasticsearch, + }} + /> + + + ); +}; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/connection_mode.tsx b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/connection_mode.tsx new file mode 100644 index 000000000000..d06b4f111ec9 --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/connection_mode.tsx @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { EuiDescribedFormGroup, EuiTitle, EuiFormRow, EuiSwitch, EuiSpacer } from '@elastic/eui'; + +import { SNIFF_MODE, PROXY_MODE } from '../../../../../../common/constants'; +import { useAppContext } from '../../../../app_context'; + +import { ClusterErrors } from '../validators'; +import { SniffConnection } from './sniff_connection'; +import { ProxyConnection } from './proxy_connection'; +import { FormFields } from '../remote_cluster_form'; + +export interface Props { + fields: FormFields; + onFieldsChange: (fields: Partial) => void; + fieldsErrors: ClusterErrors; + areErrorsVisible: boolean; +} + +export const ConnectionMode: FunctionComponent = (props) => { + const { fields, onFieldsChange } = props; + const { mode, cloudUrlEnabled } = fields; + const { isCloudEnabled } = useAppContext(); + + return ( + +

+ +

+ + } + description={ + <> + {isCloudEnabled ? ( + <> + + + + } + checked={!cloudUrlEnabled} + data-test-subj="remoteClusterFormCloudUrlToggle" + onChange={(e) => onFieldsChange({ cloudUrlEnabled: !e.target.checked })} + /> + + + + ) : ( + <> + + + + } + checked={mode === PROXY_MODE} + data-test-subj="remoteClusterFormConnectionModeToggle" + onChange={(e) => + onFieldsChange({ mode: e.target.checked ? PROXY_MODE : SNIFF_MODE }) + } + /> + + + )} + + } + fullWidth + > + {mode === SNIFF_MODE ? : } +
+ ); +}; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/index.ts b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/index.ts new file mode 100644 index 000000000000..864385ad0b1a --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { ConnectionMode } from './connection_mode'; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/proxy_connection.tsx b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/proxy_connection.tsx new file mode 100644 index 000000000000..04e8533a0d2a --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/proxy_connection.tsx @@ -0,0 +1,162 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { EuiFieldNumber, EuiFieldText, EuiFormRow, EuiLink } from '@elastic/eui'; +import { useAppContext } from '../../../../app_context'; +import { proxySettingsUrl } from '../../../../services/documentation'; +import { Props } from './connection_mode'; +import { CloudUrlHelp } from './cloud_url_help'; + +export const ProxyConnection: FunctionComponent = (props) => { + const { fields, fieldsErrors, areErrorsVisible, onFieldsChange } = props; + const { isCloudEnabled } = useAppContext(); + const { proxyAddress, serverName, proxySocketConnections, cloudUrl, cloudUrlEnabled } = fields; + const { + proxyAddress: proxyAddressError, + serverName: serverNameError, + cloudUrl: cloudUrlError, + } = fieldsErrors; + + return ( + <> + {cloudUrlEnabled ? ( + <> + + } + labelAppend={} + isInvalid={Boolean(areErrorsVisible && cloudUrlError)} + error={cloudUrlError} + fullWidth + helpText={ + + } + > + onFieldsChange({ cloudUrl: e.target.value })} + isInvalid={Boolean(areErrorsVisible && cloudUrlError)} + data-test-subj="remoteClusterFormCloudUrlInput" + fullWidth + /> + + + ) : ( + <> + + } + helpText={ + + } + isInvalid={Boolean(areErrorsVisible && proxyAddressError)} + error={proxyAddressError} + fullWidth + > + onFieldsChange({ proxyAddress: e.target.value })} + isInvalid={Boolean(areErrorsVisible && proxyAddressError)} + data-test-subj="remoteClusterFormProxyAddressInput" + fullWidth + /> + + + + ) : ( + + ) + } + helpText={ + + + + ), + }} + /> + } + fullWidth + > + onFieldsChange({ serverName: e.target.value })} + isInvalid={Boolean(areErrorsVisible && serverNameError)} + fullWidth + /> + + + )} + + } + helpText={ + + } + fullWidth + > + onFieldsChange({ proxySocketConnections: Number(e.target.value) })} + fullWidth + /> + + + ); +}; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/sniff_connection.tsx b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/sniff_connection.tsx new file mode 100644 index 000000000000..063aeb3490ae --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/components/sniff_connection.tsx @@ -0,0 +1,158 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { + EuiComboBox, + EuiComboBoxOptionOption, + EuiFieldNumber, + EuiFormRow, + EuiLink, +} from '@elastic/eui'; + +import { transportPortUrl } from '../../../../services/documentation'; +import { validateSeed } from '../validators'; +import { Props } from './connection_mode'; + +export const SniffConnection: FunctionComponent = ({ + fields, + fieldsErrors, + areErrorsVisible, + onFieldsChange, +}) => { + const [localSeedErrors, setLocalSeedErrors] = useState([]); + const { seeds = [], nodeConnections } = fields; + const { seeds: seedsError } = fieldsErrors; + // Show errors if there is a general form error or local errors. + const areFormErrorsVisible = Boolean(areErrorsVisible && seedsError); + const showErrors = areFormErrorsVisible || localSeedErrors.length !== 0; + const errors = + areFormErrorsVisible && seedsError ? localSeedErrors.concat(seedsError) : localSeedErrors; + const formattedSeeds: EuiComboBoxOptionOption[] = seeds.map((seed: string) => ({ label: seed })); + + const onCreateSeed = (newSeed?: string) => { + // If the user just hit enter without typing anything, treat it as a no-op. + if (!newSeed) { + return; + } + + const validationErrors = validateSeed(newSeed); + + if (validationErrors.length !== 0) { + setLocalSeedErrors(validationErrors); + // Return false to explicitly reject the user's input. + return false; + } + + const newSeeds = seeds.slice(0); + newSeeds.push(newSeed.toLowerCase()); + onFieldsChange({ seeds: newSeeds }); + }; + + const onSeedsInputChange = (seedInput?: string) => { + if (!seedInput) { + // If empty seedInput ("") don't do anything. This happens + // right after a seed is created. + return; + } + + // Allow typing to clear the errors, but not to add new ones. + const validationErrors = + !seedInput || validateSeed(seedInput).length === 0 ? [] : localSeedErrors; + + // EuiComboBox internally checks for duplicates and prevents calling onCreateOption if the + // input is a duplicate. So we need to surface this error here instead. + const isDuplicate = seeds.includes(seedInput); + + if (isDuplicate) { + validationErrors.push( + + ); + } + + setLocalSeedErrors(validationErrors); + }; + return ( + <> + + } + helpText={ + + + + ), + }} + /> + } + isInvalid={showErrors} + error={errors} + fullWidth + > + + onFieldsChange({ seeds: options.map(({ label }) => label) }) + } + onSearchChange={onSeedsInputChange} + isInvalid={showErrors} + fullWidth + data-test-subj="remoteClusterFormSeedsInput" + /> + + + + } + helpText={ + + } + fullWidth + > + onFieldsChange({ nodeConnections: Number(e.target.value) })} + fullWidth + /> + + + ); +}; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/index.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/index.ts similarity index 100% rename from x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/index.js rename to x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/index.ts diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.js deleted file mode 100644 index 325215d08af5..000000000000 --- a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.js +++ /dev/null @@ -1,962 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { Component, Fragment } from 'react'; -import PropTypes from 'prop-types'; -import { merge } from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiButton, - EuiButtonEmpty, - EuiCallOut, - EuiComboBox, - EuiDescribedFormGroup, - EuiFieldNumber, - EuiFieldText, - EuiFlexGroup, - EuiFlexItem, - EuiForm, - EuiFormRow, - EuiLink, - EuiLoadingKibana, - EuiLoadingSpinner, - EuiOverlayMask, - EuiSpacer, - EuiSwitch, - EuiText, - EuiTitle, - EuiDelayRender, - EuiScreenReaderOnly, - htmlIdGenerator, -} from '@elastic/eui'; - -import { - skippingDisconnectedClustersUrl, - transportPortUrl, - proxySettingsUrl, -} from '../../../services/documentation'; - -import { RequestFlyout } from './request_flyout'; - -import { - validateName, - validateSeeds, - validateProxy, - validateSeed, - validateServerName, -} from './validators'; - -import { SNIFF_MODE, PROXY_MODE } from '../../../../../common/constants'; - -import { AppContext } from '../../../app_context'; - -const defaultFields = { - name: '', - seeds: [], - skipUnavailable: false, - nodeConnections: 3, - proxyAddress: '', - proxySocketConnections: 18, - serverName: '', -}; - -const ERROR_TITLE_ID = 'removeClustersErrorTitle'; -const ERROR_LIST_ID = 'removeClustersErrorList'; - -export class RemoteClusterForm extends Component { - static propTypes = { - save: PropTypes.func.isRequired, - cancel: PropTypes.func, - isSaving: PropTypes.bool, - saveError: PropTypes.object, - fields: PropTypes.object, - disabledFields: PropTypes.object, - }; - - static defaultProps = { - fields: merge({}, defaultFields), - disabledFields: {}, - }; - - static contextType = AppContext; - - constructor(props, context) { - super(props, context); - - const { fields, disabledFields } = props; - const { isCloudEnabled } = context; - - // Connection mode should default to "proxy" in cloud - const defaultMode = isCloudEnabled ? PROXY_MODE : SNIFF_MODE; - const fieldsState = merge({}, { ...defaultFields, mode: defaultMode }, fields); - - this.generateId = htmlIdGenerator(); - this.state = { - localSeedErrors: [], - seedInput: '', - fields: fieldsState, - disabledFields, - fieldsErrors: this.getFieldsErrors(fieldsState), - areErrorsVisible: false, - isRequestVisible: false, - }; - } - - toggleRequest = () => { - this.setState(({ isRequestVisible }) => ({ - isRequestVisible: !isRequestVisible, - })); - }; - - getFieldsErrors(fields, seedInput = '') { - const { name, seeds, mode, proxyAddress, serverName } = fields; - const { isCloudEnabled } = this.context; - - return { - name: validateName(name), - seeds: mode === SNIFF_MODE ? validateSeeds(seeds, seedInput) : null, - proxyAddress: mode === PROXY_MODE ? validateProxy(proxyAddress) : null, - // server name is only required in cloud when proxy mode is enabled - serverName: isCloudEnabled && mode === PROXY_MODE ? validateServerName(serverName) : null, - }; - } - - onFieldsChange = (changedFields) => { - this.setState(({ fields: prevFields, seedInput }) => { - const newFields = { - ...prevFields, - ...changedFields, - }; - return { - fields: newFields, - fieldsErrors: this.getFieldsErrors(newFields, seedInput), - }; - }); - }; - - getAllFields() { - const { - fields: { - name, - mode, - seeds, - nodeConnections, - proxyAddress, - proxySocketConnections, - serverName, - skipUnavailable, - }, - } = this.state; - const { fields } = this.props; - - let modeSettings; - - if (mode === PROXY_MODE) { - modeSettings = { - proxyAddress, - proxySocketConnections, - serverName, - }; - } else { - modeSettings = { - seeds, - nodeConnections, - }; - } - - return { - name, - skipUnavailable, - mode, - hasDeprecatedProxySetting: fields.hasDeprecatedProxySetting, - ...modeSettings, - }; - } - - save = () => { - const { save } = this.props; - - if (this.hasErrors()) { - this.setState({ - areErrorsVisible: true, - }); - return; - } - - const cluster = this.getAllFields(); - save(cluster); - }; - - onCreateSeed = (newSeed) => { - // If the user just hit enter without typing anything, treat it as a no-op. - if (!newSeed) { - return; - } - - const localSeedErrors = validateSeed(newSeed); - - if (localSeedErrors.length !== 0) { - this.setState({ - localSeedErrors, - }); - - // Return false to explicitly reject the user's input. - return false; - } - - const { - fields: { seeds }, - } = this.state; - - const newSeeds = seeds.slice(0); - newSeeds.push(newSeed.toLowerCase()); - this.onFieldsChange({ seeds: newSeeds }); - }; - - onSeedsInputChange = (seedInput) => { - if (!seedInput) { - // If empty seedInput ("") don't do anything. This happens - // right after a seed is created. - return; - } - - this.setState(({ fields, localSeedErrors }) => { - const { seeds } = fields; - - // Allow typing to clear the errors, but not to add new ones. - const errors = !seedInput || validateSeed(seedInput).length === 0 ? [] : localSeedErrors; - - // EuiComboBox internally checks for duplicates and prevents calling onCreateOption if the - // input is a duplicate. So we need to surface this error here instead. - const isDuplicate = seeds.includes(seedInput); - - if (isDuplicate) { - errors.push( - i18n.translate('xpack.remoteClusters.remoteClusterForm.localSeedError.duplicateMessage', { - defaultMessage: `Duplicate seed nodes aren't allowed.`, - }) - ); - } - - return { - localSeedErrors: errors, - fieldsErrors: this.getFieldsErrors(fields, seedInput), - seedInput, - }; - }); - }; - - onSeedsChange = (seeds) => { - this.onFieldsChange({ seeds: seeds.map(({ label }) => label) }); - }; - - onSkipUnavailableChange = (e) => { - const skipUnavailable = e.target.checked; - this.onFieldsChange({ skipUnavailable }); - }; - - resetToDefault = (fieldName) => { - this.onFieldsChange({ - [fieldName]: defaultFields[fieldName], - }); - }; - - hasErrors = () => { - const { fieldsErrors, localSeedErrors } = this.state; - const errorValues = Object.values(fieldsErrors); - const hasErrors = errorValues.some((error) => error != null) || localSeedErrors.length; - return hasErrors; - }; - - renderSniffModeSettings() { - const { - areErrorsVisible, - fields: { seeds, nodeConnections }, - fieldsErrors: { seeds: errorsSeeds }, - localSeedErrors, - } = this.state; - - // Show errors if there is a general form error or local errors. - const areFormErrorsVisible = Boolean(areErrorsVisible && errorsSeeds); - const showErrors = areFormErrorsVisible || localSeedErrors.length !== 0; - const errors = areFormErrorsVisible ? localSeedErrors.concat(errorsSeeds) : localSeedErrors; - - const formattedSeeds = seeds.map((seed) => ({ label: seed })); - - return ( - <> - - } - helpText={ - - - - ), - }} - /> - } - isInvalid={showErrors} - error={errors} - fullWidth - > - - - - - } - helpText={ - - } - fullWidth - > - - this.onFieldsChange({ nodeConnections: Number(e.target.value) || null }) - } - fullWidth - /> - - - ); - } - - renderProxyModeSettings() { - const { - areErrorsVisible, - fields: { proxyAddress, proxySocketConnections, serverName }, - fieldsErrors: { proxyAddress: errorProxyAddress, serverName: errorServerName }, - } = this.state; - - const { isCloudEnabled } = this.context; - - return ( - <> - - } - helpText={ - - } - isInvalid={Boolean(areErrorsVisible && errorProxyAddress)} - error={errorProxyAddress} - fullWidth - > - this.onFieldsChange({ proxyAddress: e.target.value })} - isInvalid={Boolean(areErrorsVisible && errorProxyAddress)} - data-test-subj="remoteClusterFormProxyAddressInput" - fullWidth - /> - - - - ) : ( - - ) - } - helpText={ - - - - ), - }} - /> - } - fullWidth - > - this.onFieldsChange({ serverName: e.target.value })} - isInvalid={Boolean(areErrorsVisible && errorServerName)} - fullWidth - /> - - - - } - helpText={ - - } - fullWidth - > - - this.onFieldsChange({ proxySocketConnections: Number(e.target.value) || null }) - } - fullWidth - /> - - - ); - } - - renderMode() { - const { - fields: { mode }, - } = this.state; - - const { isCloudEnabled } = this.context; - - return ( - -

- -

- - } - description={ - <> - - - - } - checked={mode === PROXY_MODE} - data-test-subj="remoteClusterFormConnectionModeToggle" - onChange={(e) => - this.onFieldsChange({ mode: e.target.checked ? PROXY_MODE : SNIFF_MODE }) - } - /> - - {isCloudEnabled && mode === PROXY_MODE ? ( - <> - - - } - > - - - - ), - searchString: ( - - - - ), - }} - /> - - - ) : null} - - } - fullWidth - > - {mode === PROXY_MODE ? this.renderProxyModeSettings() : this.renderSniffModeSettings()} -
- ); - } - - renderSkipUnavailable() { - const { - fields: { skipUnavailable }, - } = this.state; - - return ( - -

- -

- - } - description={ - -

- - - - ), - learnMoreLink: ( - - - - ), - }} - /> -

-
- } - fullWidth - > - { - this.resetToDefault('skipUnavailable'); - }} - > - - - ) : null - } - > - - -
- ); - } - - renderActions() { - const { isSaving, cancel } = this.props; - const { areErrorsVisible, isRequestVisible } = this.state; - - if (isSaving) { - return ( - - - - - - - - - - - - ); - } - - let cancelButton; - - if (cancel) { - cancelButton = ( - - - - - - ); - } - - const isSaveDisabled = areErrorsVisible && this.hasErrors(); - - return ( - - - - - - - - - - {cancelButton} - - - - - - {isRequestVisible ? ( - - ) : ( - - )} - - - - ); - } - - renderSavingFeedback() { - if (this.props.isSaving) { - return ( - - - - ); - } - - return null; - } - - renderSaveErrorFeedback() { - const { saveError } = this.props; - - if (saveError) { - const { message, cause } = saveError; - - let errorBody; - - if (cause && Array.isArray(cause)) { - if (cause.length === 1) { - errorBody =

{cause[0]}

; - } else { - errorBody = ( -
    - {cause.map((causeValue) => ( -
  • {causeValue}
  • - ))} -
- ); - } - } - - return ( - - - {errorBody} - - - - - ); - } - - return null; - } - - renderErrors = () => { - const { - areErrorsVisible, - fieldsErrors: { name: errorClusterName, seeds: errorsSeeds, proxyAddress: errorProxyAddress }, - localSeedErrors, - } = this.state; - - const hasErrors = this.hasErrors(); - - if (!areErrorsVisible || !hasErrors) { - return null; - } - - const errorExplanations = []; - - if (errorClusterName) { - errorExplanations.push({ - key: 'nameExplanation', - field: i18n.translate('xpack.remoteClusters.remoteClusterForm.inputNameErrorMessage', { - defaultMessage: 'The "Name" field is invalid.', - }), - error: errorClusterName, - }); - } - - if (errorsSeeds) { - errorExplanations.push({ - key: 'seedsExplanation', - field: i18n.translate('xpack.remoteClusters.remoteClusterForm.inputSeedsErrorMessage', { - defaultMessage: 'The "Seed nodes" field is invalid.', - }), - error: errorsSeeds, - }); - } - - if (localSeedErrors && localSeedErrors.length) { - errorExplanations.push({ - key: 'localSeedExplanation', - field: i18n.translate('xpack.remoteClusters.remoteClusterForm.inputLocalSeedErrorMessage', { - defaultMessage: 'The "Seed nodes" field is invalid.', - }), - error: localSeedErrors.join(' '), - }); - } - - if (errorProxyAddress) { - errorExplanations.push({ - key: 'seedsExplanation', - field: i18n.translate('xpack.remoteClusters.remoteClusterForm.inputProxyErrorMessage', { - defaultMessage: 'The "Proxy address" field is invalid.', - }), - error: errorProxyAddress, - }); - } - - const messagesToBeRendered = errorExplanations.length && ( - -
- {errorExplanations.map(({ key, field, error }) => ( -
-
{field}
-
{error}
-
- ))} -
-
- ); - - return ( - - - - - - } - color="danger" - iconType="cross" - /> - {messagesToBeRendered} - - ); - }; - - render() { - const { - disabledFields: { name: disabledName }, - } = this.props; - - const { - isRequestVisible, - areErrorsVisible, - fields: { name }, - fieldsErrors: { name: errorClusterName }, - } = this.state; - - return ( - - {this.renderSaveErrorFeedback()} - - - -

- -

- - } - description={ - - } - fullWidth - > - - } - helpText={ - - } - error={errorClusterName} - isInvalid={Boolean(areErrorsVisible && errorClusterName)} - fullWidth - > - this.onFieldsChange({ name: e.target.value })} - fullWidth - disabled={disabledName} - data-test-subj="remoteClusterFormNameInput" - /> - -
- - {this.renderMode()} - - {this.renderSkipUnavailable()} -
- - {this.renderErrors()} - - - - {this.renderActions()} - - {this.renderSavingFeedback()} - - {isRequestVisible ? ( - this.setState({ isRequestVisible: false })} - /> - ) : null} -
- ); - } -} diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.test.js b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.test.js deleted file mode 100644 index 2ae16b8ca7cb..000000000000 --- a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.test.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { mountWithIntl, renderWithIntl } from '@kbn/test/jest'; -import { findTestSubject, takeMountedSnapshot } from '@elastic/eui/lib/test'; -import { RemoteClusterForm } from './remote_cluster_form'; - -// Make sure we have deterministic aria IDs. -jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ - htmlIdGenerator: (prefix = 'staticGenerator') => (suffix = 'staticId') => `${prefix}_${suffix}`, -})); - -describe('RemoteClusterForm', () => { - test(`renders untouched state`, () => { - const component = renderWithIntl( {}} />); - expect(component).toMatchSnapshot(); - }); - - describe('proxy mode', () => { - test('renders correct connection settings when user enables proxy mode', () => { - const component = mountWithIntl( {}} />); - - findTestSubject(component, 'remoteClusterFormConnectionModeToggle').simulate('click'); - - expect(component).toMatchSnapshot(); - }); - }); - - describe('validation', () => { - test('renders invalid state and a global form error when the user tries to submit an invalid form', () => { - const component = mountWithIntl( {}} />); - - findTestSubject(component, 'remoteClusterFormSaveButton').simulate('click'); - - const fieldsSnapshot = [ - 'remoteClusterFormNameFormRow', - 'remoteClusterFormSeedNodesFormRow', - 'remoteClusterFormSkipUnavailableFormRow', - 'remoteClusterFormGlobalError', - ].map((testSubject) => { - const mountedField = findTestSubject(component, testSubject); - return takeMountedSnapshot(mountedField); - }); - - expect(fieldsSnapshot).toMatchSnapshot(); - }); - }); -}); diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.tsx b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.tsx new file mode 100644 index 000000000000..9f6eee757c75 --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.tsx @@ -0,0 +1,629 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { Component, Fragment } from 'react'; +import { merge } from 'lodash'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiButton, + EuiButtonEmpty, + EuiCallOut, + EuiDescribedFormGroup, + EuiFieldText, + EuiFlexGroup, + EuiFlexItem, + EuiForm, + EuiFormRow, + EuiLink, + EuiLoadingKibana, + EuiLoadingSpinner, + EuiOverlayMask, + EuiSpacer, + EuiSwitch, + EuiText, + EuiTitle, + EuiDelayRender, + EuiScreenReaderOnly, + htmlIdGenerator, + EuiSwitchEvent, +} from '@elastic/eui'; + +import { Cluster } from '../../../../../common/lib'; +import { SNIFF_MODE, PROXY_MODE } from '../../../../../common/constants'; + +import { AppContext, Context } from '../../../app_context'; + +import { skippingDisconnectedClustersUrl } from '../../../services/documentation'; + +import { RequestFlyout } from './request_flyout'; +import { ConnectionMode } from './components'; +import { + ClusterErrors, + convertCloudUrlToProxyConnection, + convertProxyConnectionToCloudUrl, + validateCluster, +} from './validators'; +import { isCloudUrlEnabled } from './validators/validate_cloud_url'; + +const defaultClusterValues: Cluster = { + name: '', + seeds: [], + skipUnavailable: false, + nodeConnections: 3, + proxyAddress: '', + proxySocketConnections: 18, + serverName: '', +}; + +const ERROR_TITLE_ID = 'removeClustersErrorTitle'; +const ERROR_LIST_ID = 'removeClustersErrorList'; + +interface Props { + save: (cluster: Cluster) => void; + cancel?: () => void; + isSaving?: boolean; + saveError?: any; + cluster?: Cluster; +} + +export type FormFields = Cluster & { cloudUrl: string; cloudUrlEnabled: boolean }; + +interface State { + fields: FormFields; + fieldsErrors: ClusterErrors; + areErrorsVisible: boolean; + isRequestVisible: boolean; +} + +export class RemoteClusterForm extends Component { + static defaultProps = { + fields: merge({}, defaultClusterValues), + }; + + static contextType = AppContext; + private readonly generateId: (idSuffix?: string) => string; + + constructor(props: Props, context: Context) { + super(props, context); + + const { cluster } = props; + const { isCloudEnabled } = context; + + // Connection mode should default to "proxy" in cloud + const defaultMode = isCloudEnabled ? PROXY_MODE : SNIFF_MODE; + const fieldsState: FormFields = merge( + {}, + { + ...defaultClusterValues, + mode: defaultMode, + cloudUrl: convertProxyConnectionToCloudUrl(cluster), + cloudUrlEnabled: isCloudEnabled && isCloudUrlEnabled(cluster), + }, + cluster + ); + + this.generateId = htmlIdGenerator(); + this.state = { + fields: fieldsState, + fieldsErrors: validateCluster(fieldsState, isCloudEnabled), + areErrorsVisible: false, + isRequestVisible: false, + }; + } + + toggleRequest = () => { + this.setState(({ isRequestVisible }) => ({ + isRequestVisible: !isRequestVisible, + })); + }; + + onFieldsChange = (changedFields: Partial) => { + const { isCloudEnabled } = this.context; + + // when cloudUrl changes, fill proxy address and server name + const { cloudUrl } = changedFields; + if (cloudUrl) { + const { proxyAddress, serverName } = convertCloudUrlToProxyConnection(cloudUrl); + changedFields = { + ...changedFields, + proxyAddress, + serverName, + }; + } + + this.setState(({ fields: prevFields }) => { + const newFields = { + ...prevFields, + ...changedFields, + }; + return { + fields: newFields, + fieldsErrors: validateCluster(newFields, isCloudEnabled), + }; + }); + }; + + getCluster(): Cluster { + const { + fields: { + name, + mode, + seeds, + nodeConnections, + proxyAddress, + proxySocketConnections, + serverName, + skipUnavailable, + }, + } = this.state; + const { cluster } = this.props; + + let modeSettings; + + if (mode === PROXY_MODE) { + modeSettings = { + proxyAddress, + proxySocketConnections, + serverName, + }; + } else { + modeSettings = { + seeds, + nodeConnections, + }; + } + + return { + name, + skipUnavailable, + mode, + hasDeprecatedProxySetting: cluster?.hasDeprecatedProxySetting, + ...modeSettings, + }; + } + + save = () => { + const { save } = this.props; + + if (this.hasErrors()) { + this.setState({ + areErrorsVisible: true, + }); + return; + } + + const cluster = this.getCluster(); + save(cluster); + }; + + onSkipUnavailableChange = (e: EuiSwitchEvent) => { + const skipUnavailable = e.target.checked; + this.onFieldsChange({ skipUnavailable }); + }; + + resetToDefault = (fieldName: keyof Cluster) => { + this.onFieldsChange({ + [fieldName]: defaultClusterValues[fieldName], + }); + }; + + hasErrors = () => { + const { fieldsErrors } = this.state; + const errorValues = Object.values(fieldsErrors); + return errorValues.some((error) => error != null); + }; + + renderSkipUnavailable() { + const { + fields: { skipUnavailable }, + } = this.state; + + return ( + +

+ +

+ + } + description={ + +

+ + + + ), + learnMoreLink: ( + + + + ), + }} + /> +

+
+ } + fullWidth + > + { + this.resetToDefault('skipUnavailable'); + }} + > + + + ) : null + } + > + + +
+ ); + } + + renderActions() { + const { isSaving, cancel } = this.props; + const { areErrorsVisible, isRequestVisible } = this.state; + + if (isSaving) { + return ( + + + + + + + + + + + + ); + } + + let cancelButton; + + if (cancel) { + cancelButton = ( + + + + + + ); + } + + const isSaveDisabled = areErrorsVisible && this.hasErrors(); + + return ( + + + + + + + + + + {cancelButton} + + + + + + {isRequestVisible ? ( + + ) : ( + + )} + + + + ); + } + + renderSavingFeedback() { + if (this.props.isSaving) { + return ( + + + + ); + } + + return null; + } + + renderSaveErrorFeedback() { + const { saveError } = this.props; + + if (saveError) { + const { message, cause } = saveError; + + let errorBody; + + if (cause && Array.isArray(cause)) { + if (cause.length === 1) { + errorBody =

{cause[0]}

; + } else { + errorBody = ( +
    + {cause.map((causeValue) => ( +
  • {causeValue}
  • + ))} +
+ ); + } + } + + return ( + + + {errorBody} + + + + + ); + } + + return null; + } + + renderErrors = () => { + const { + areErrorsVisible, + fieldsErrors: { + name: errorClusterName, + seeds: errorsSeeds, + proxyAddress: errorProxyAddress, + serverName: errorServerName, + cloudUrl: errorCloudUrl, + }, + } = this.state; + + const hasErrors = this.hasErrors(); + + if (!areErrorsVisible || !hasErrors) { + return null; + } + + const errorExplanations = []; + + if (errorClusterName) { + errorExplanations.push({ + key: 'nameExplanation', + field: i18n.translate('xpack.remoteClusters.remoteClusterForm.inputNameErrorMessage', { + defaultMessage: 'The "Name" field is invalid.', + }), + error: errorClusterName, + }); + } + + if (errorsSeeds) { + errorExplanations.push({ + key: 'seedsExplanation', + field: i18n.translate('xpack.remoteClusters.remoteClusterForm.inputSeedsErrorMessage', { + defaultMessage: 'The "Seed nodes" field is invalid.', + }), + error: errorsSeeds, + }); + } + + if (errorProxyAddress) { + errorExplanations.push({ + key: 'proxyAddressExplanation', + field: i18n.translate('xpack.remoteClusters.remoteClusterForm.inputProxyErrorMessage', { + defaultMessage: 'The "Proxy address" field is invalid.', + }), + error: errorProxyAddress, + }); + } + + if (errorServerName) { + errorExplanations.push({ + key: 'serverNameExplanation', + field: i18n.translate( + 'xpack.remoteClusters.remoteClusterForm.inputServerNameErrorMessage', + { + defaultMessage: 'The "Server name" field is invalid.', + } + ), + error: errorServerName, + }); + } + + if (errorCloudUrl) { + errorExplanations.push({ + key: 'cloudUrlExplanation', + field: i18n.translate('xpack.remoteClusters.remoteClusterForm.inputcloudUrlErrorMessage', { + defaultMessage: 'The "Elasticsearch endpoint URL" field is invalid.', + }), + error: errorCloudUrl, + }); + } + + const messagesToBeRendered = errorExplanations.length && ( + +
+ {errorExplanations.map(({ key, field, error }) => ( +
+
{field}
+
{error}
+
+ ))} +
+
+ ); + + return ( + + + + + + } + color="danger" + iconType="cross" + /> + {messagesToBeRendered} + + ); + }; + + render() { + const { isRequestVisible, areErrorsVisible, fields, fieldsErrors } = this.state; + const { name: errorClusterName } = fieldsErrors; + const { cluster } = this.props; + const isNew = !cluster; + return ( + + {this.renderSaveErrorFeedback()} + + + +

+ +

+ + } + description={ + + } + fullWidth + > + + } + helpText={ + + } + error={errorClusterName} + isInvalid={Boolean(areErrorsVisible && errorClusterName)} + fullWidth + > + this.onFieldsChange({ name: e.target.value })} + fullWidth + disabled={!isNew} + data-test-subj="remoteClusterFormNameInput" + /> + +
+ + + + {this.renderSkipUnavailable()} +
+ + {this.renderErrors()} + + + + {this.renderActions()} + + {this.renderSavingFeedback()} + + {isRequestVisible ? ( + this.setState({ isRequestVisible: false })} + /> + ) : null} +
+ ); + } +} diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/request_flyout.tsx b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/request_flyout.tsx index 4e402b8b55a5..2bcedc2bce45 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/request_flyout.tsx +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/request_flyout.tsx @@ -24,13 +24,13 @@ import { Cluster, serializeCluster } from '../../../../../common/lib'; interface Props { close: () => void; - name: string; cluster: Cluster; } export class RequestFlyout extends PureComponent { render() { - const { name, close, cluster } = this.props; + const { close, cluster } = this.props; + const { name } = cluster; const endpoint = 'PUT _cluster/settings'; const payload = JSON.stringify(serializeCluster(cluster), null, 2); const request = `${endpoint}\n${payload}`; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/index.ts b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/index.ts index 67a5d8f727f3..6f3956a19f6a 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/index.ts +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/index.ts @@ -10,3 +10,10 @@ export { validateProxy } from './validate_proxy'; export { validateSeeds } from './validate_seeds'; export { validateSeed } from './validate_seed'; export { validateServerName } from './validate_server_name'; +export { validateCluster, ClusterErrors } from './validate_cluster'; +export { + isCloudUrlEnabled, + validateCloudUrl, + convertProxyConnectionToCloudUrl, + convertCloudUrlToProxyConnection, +} from './validate_cloud_url'; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_cloud_url.test.ts b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_cloud_url.test.ts new file mode 100644 index 000000000000..599706ba85b0 --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_cloud_url.test.ts @@ -0,0 +1,128 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + isCloudUrlEnabled, + validateCloudUrl, + convertCloudUrlToProxyConnection, + convertProxyConnectionToCloudUrl, + i18nTexts, +} from './validate_cloud_url'; + +describe('Cloud url', () => { + describe('validation', () => { + it('errors when the url is empty', () => { + const actual = validateCloudUrl(''); + expect(actual).toBe(i18nTexts.urlEmpty); + }); + + it('errors when the url is invalid', () => { + const actual = validateCloudUrl('invalid%url'); + expect(actual).toBe(i18nTexts.urlInvalid); + }); + }); + + describe('is cloud url', () => { + it('true for a new cluster', () => { + const actual = isCloudUrlEnabled(); + expect(actual).toBe(true); + }); + + it('true when proxy connection is empty', () => { + const actual = isCloudUrlEnabled({ name: 'test', proxyAddress: '', serverName: '' }); + expect(actual).toBe(true); + }); + + it('true when proxy address is the same as server name and default port', () => { + const actual = isCloudUrlEnabled({ + name: 'test', + proxyAddress: 'some-proxy:9400', + serverName: 'some-proxy', + }); + expect(actual).toBe(true); + }); + it('false when proxy address is the same as server name but not default port', () => { + const actual = isCloudUrlEnabled({ + name: 'test', + proxyAddress: 'some-proxy:1234', + serverName: 'some-proxy', + }); + expect(actual).toBe(false); + }); + it('true when proxy address is not the same as server name', () => { + const actual = isCloudUrlEnabled({ + name: 'test', + proxyAddress: 'some-proxy:9400', + serverName: 'some-server-name', + }); + expect(actual).toBe(false); + }); + }); + describe('conversion from cloud url', () => { + it('empty url to empty proxy connection values', () => { + const actual = convertCloudUrlToProxyConnection(''); + expect(actual).toEqual({ proxyAddress: '', serverName: '' }); + }); + + it('url with protocol and port to proxy connection values', () => { + const actual = convertCloudUrlToProxyConnection('http://test.com:1234'); + expect(actual).toEqual({ proxyAddress: 'test.com:9400', serverName: 'test.com' }); + }); + + it('url with protocol and no port to proxy connection values', () => { + const actual = convertCloudUrlToProxyConnection('http://test.com'); + expect(actual).toEqual({ proxyAddress: 'test.com:9400', serverName: 'test.com' }); + }); + + it('url with no protocol to proxy connection values', () => { + const actual = convertCloudUrlToProxyConnection('test.com'); + expect(actual).toEqual({ proxyAddress: 'test.com:9400', serverName: 'test.com' }); + }); + it('invalid url to empty proxy connection values', () => { + const actual = convertCloudUrlToProxyConnection('invalid%url'); + expect(actual).toEqual({ proxyAddress: '', serverName: '' }); + }); + }); + + describe('conversion to cloud url', () => { + it('empty proxy address to empty cloud url', () => { + const actual = convertProxyConnectionToCloudUrl({ + name: 'test', + proxyAddress: '', + serverName: 'test', + }); + expect(actual).toEqual(''); + }); + + it('empty server name to empty cloud url', () => { + const actual = convertProxyConnectionToCloudUrl({ + name: 'test', + proxyAddress: 'test', + serverName: '', + }); + expect(actual).toEqual(''); + }); + + it('different proxy address and server name to empty cloud url', () => { + const actual = convertProxyConnectionToCloudUrl({ + name: 'test', + proxyAddress: 'test', + serverName: 'another-test', + }); + expect(actual).toEqual(''); + }); + + it('valid proxy connection to cloud url', () => { + const actual = convertProxyConnectionToCloudUrl({ + name: 'test', + proxyAddress: 'test-proxy:9400', + serverName: 'test-proxy', + }); + expect(actual).toEqual('test-proxy'); + }); + }); +}); diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_cloud_url.tsx b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_cloud_url.tsx new file mode 100644 index 000000000000..1f4862f0113e --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_cloud_url.tsx @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { Cluster } from '../../../../../../common/lib'; +import { isAddressValid } from './validate_address'; + +export const i18nTexts = { + urlEmpty: ( + + ), + urlInvalid: ( + + ), +}; + +const CLOUD_DEFAULT_PROXY_PORT = '9400'; +const EMPTY_PROXY_VALUES = { proxyAddress: '', serverName: '' }; +const PROTOCOL_REGEX = new RegExp(/^https?:\/\//); + +export const isCloudUrlEnabled = (cluster?: Cluster): boolean => { + // enable cloud url for new clusters + if (!cluster) { + return true; + } + const { proxyAddress, serverName } = cluster; + if (!proxyAddress && !serverName) { + return true; + } + const portParts = (proxyAddress ?? '').split(':'); + const proxyAddressWithoutPort = portParts[0]; + const port = portParts[1]; + return port === CLOUD_DEFAULT_PROXY_PORT && proxyAddressWithoutPort === serverName; +}; + +const formatUrl = (url: string) => { + url = (url ?? '').trim().toLowerCase(); + // delete http(s):// protocol string if any + url = url.replace(PROTOCOL_REGEX, ''); + return url; +}; + +export const convertProxyConnectionToCloudUrl = (cluster?: Cluster): string => { + if (!isCloudUrlEnabled(cluster)) { + return ''; + } + return cluster?.serverName ?? ''; +}; +export const convertCloudUrlToProxyConnection = ( + cloudUrl: string = '' +): { proxyAddress: string; serverName: string } => { + cloudUrl = formatUrl(cloudUrl); + if (!cloudUrl || !isAddressValid(cloudUrl)) { + return EMPTY_PROXY_VALUES; + } + const address = cloudUrl.split(':')[0]; + return { proxyAddress: `${address}:${CLOUD_DEFAULT_PROXY_PORT}`, serverName: address }; +}; + +export const validateCloudUrl = (cloudUrl: string): JSX.Element | null => { + if (!cloudUrl) { + return i18nTexts.urlEmpty; + } + cloudUrl = formatUrl(cloudUrl); + if (!isAddressValid(cloudUrl)) { + return i18nTexts.urlInvalid; + } + return null; +}; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_cluster.tsx b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_cluster.tsx new file mode 100644 index 000000000000..e0fa434f21d5 --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_cluster.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { validateName } from './validate_name'; +import { PROXY_MODE, SNIFF_MODE } from '../../../../../../common/constants'; +import { validateSeeds } from './validate_seeds'; +import { validateProxy } from './validate_proxy'; +import { validateServerName } from './validate_server_name'; +import { validateCloudUrl } from './validate_cloud_url'; +import { FormFields } from '../remote_cluster_form'; + +type ClusterError = JSX.Element | null; + +export interface ClusterErrors { + name?: ClusterError; + seeds?: ClusterError; + proxyAddress?: ClusterError; + serverName?: ClusterError; + cloudUrl?: ClusterError; +} +export const validateCluster = (fields: FormFields, isCloudEnabled: boolean): ClusterErrors => { + const { name, seeds = [], mode, proxyAddress, serverName, cloudUrlEnabled, cloudUrl } = fields; + + return { + name: validateName(name), + seeds: mode === SNIFF_MODE ? validateSeeds(seeds) : null, + proxyAddress: !cloudUrlEnabled && mode === PROXY_MODE ? validateProxy(proxyAddress) : null, + // server name is only required in cloud when proxy mode is enabled + serverName: + !cloudUrlEnabled && isCloudEnabled && mode === PROXY_MODE + ? validateServerName(serverName) + : null, + cloudUrl: cloudUrlEnabled ? validateCloudUrl(cloudUrl) : null, + }; +}; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seed.ts b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seed.ts deleted file mode 100644 index a5b3656b36de..000000000000 --- a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seed.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -import { isAddressValid, isPortValid } from './validate_address'; - -export function validateSeed(seed?: string): string[] { - const errors: string[] = []; - - if (!seed) { - return errors; - } - - const isValid = isAddressValid(seed); - - if (!isValid) { - errors.push( - i18n.translate( - 'xpack.remoteClusters.remoteClusterForm.localSeedError.invalidCharactersMessage', - { - defaultMessage: - 'Seed node must use host:port format. Example: 127.0.0.1:9400, localhost:9400. ' + - 'Hosts can only consist of letters, numbers, and dashes.', - } - ) - ); - } - - if (!isPortValid(seed)) { - errors.push( - i18n.translate('xpack.remoteClusters.remoteClusterForm.localSeedError.invalidPortMessage', { - defaultMessage: 'A port is required.', - }) - ); - } - - return errors; -} diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seed.tsx b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seed.tsx new file mode 100644 index 000000000000..4863dff5ec33 --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/validators/validate_seed.tsx @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { isAddressValid, isPortValid } from './validate_address'; + +export function validateSeed(seed?: string): JSX.Element[] { + const errors: JSX.Element[] = []; + + if (!seed) { + return errors; + } + + const isValid = isAddressValid(seed); + + if (!isValid) { + errors.push( + + ); + } + + if (!isPortValid(seed)) { + errors.push( + + ); + } + + return errors; +} diff --git a/x-pack/plugins/remote_clusters/public/application/sections/index.d.ts b/x-pack/plugins/remote_clusters/public/application/sections/index.d.ts new file mode 100644 index 000000000000..ab0f579c1a41 --- /dev/null +++ b/x-pack/plugins/remote_clusters/public/application/sections/index.d.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { ComponentType } from 'react'; + +export declare const RemoteClusterEdit: ComponentType; +export declare const RemoteClusterAdd: ComponentType; +export declare const RemoteClusterList: ComponentType; diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js index 6ee6bd6d87d5..124d2d42afb7 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_add/remote_cluster_add.js @@ -73,7 +73,7 @@ export class RemoteClusterAdd extends PureComponent { description={ } /> diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js index c68dd7ab10aa..18ee2e2b3875 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_edit/remote_cluster_edit.js @@ -27,10 +27,6 @@ import { getRouter, redirect } from '../../services'; import { setBreadcrumbs } from '../../services/breadcrumb'; import { RemoteClusterPageTitle, RemoteClusterForm, ConfiguredByNodeWarning } from '../components'; -const disabledFields = { - name: true, -}; - export class RemoteClusterEdit extends Component { static propTypes = { isLoading: PropTypes.bool, @@ -202,8 +198,7 @@ export class RemoteClusterEdit extends Component { ) : null} Store; diff --git a/x-pack/plugins/remote_clusters/public/assets/cloud_screenshot.png b/x-pack/plugins/remote_clusters/public/assets/cloud_screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c9302ef76eac6184fad0eb6931558c94980e54 GIT binary patch literal 197089 zcmeEtbyQrIsEtQZYU^Ni?%W{?-gWZsNcIfTiH5TqM*DBO-#nr)R-lbJo4SedGwSZhS2AE z!E;H)C+wfUxZx+pJSJ4cW-ggY>?9z6#zLbj=cf6#llw)@Ya%x6Fc98v>YRumbTYdw z)a*Ar0e25j2|WSps(64}GiKCOu+f z%A&G4!&F{vi@MxKxFlKkd{w*tH0hDbt#1f^Pe}MCRzP>rH|m!2F06SEg!RFpq{VaT z?Va>fUz#G(4~FTIuU_%4J}hxD$ zFUi}__#Ka3sL7ZkM$L|L(6LFsOJnttJcQUXHxDBhzpaN6sz z6U&KxT9xy3M-uN9Dvt@yejv{$%%u*h$ANF~pPES#rl4I*K6Z^6*beG3L1%j0V}dsG zXrPm$8j~C)xRYxXMKutxLiiKI>9fcR!Oml`75Z0?k2>ExmJ$qkG)67<`&I4deQN6v z^c!iZ_m5xT&`XuR$Dj*L7&WtbsfnE^xjE`of+dWV`FTW2CkJ;2brStT#yJP_28*G~ zZ3e&bYw<6(6rA9$nqvn+w2^OTtB<@WK4R$n3SRNKCilZ>NAvu}x%&ErWbAwFgr@_P zJ<=}kV@oVFg%!W+hp|W}=COR>D`C)N-6Q((obNOIYj2*d4Z|GeK_sqhU+&G$$8+^_ zeK#REN(&_r75HrN8|B-8uJ>;+UWr5ye-BsawlLW;$KonX0j3BK$qrE{<86r%g_)05F&(e zHS%QS+Qg6B=!ci`4P(I9($3N&3Wi~$~tFx9cmRyy{=<~8OR=lequV~Q6Y^b!kuwAcbZwRVKpF^MX zt%ulqPQ2&kAr0;=uE;wmG%UCnt#M-&PR>%`ETSrEn!t3gcmL?V=1#Puxsx%yYmxIR z37dm9y(Y^g!X^2{J8qTkl5VwtFW!z}G2>jyv$hgk`M&90llE2Ap|x0%QH)X2k{k#F z#0a+m8r-GA&n`Uoj3=p5l(YB6QYD&gPHXz{a7@q)f^33hF?_M-u)kwRV#{C`exJvN zkm0`KinxvBj^roHsrDwKqdTQn)O_E(oC z+Ggx3PUufCTD|2-(rcNusw1kC0+^reZiNq*4O8jkv*{AigjWz%5K*yJusvtfG2qv| z)Z5i}sW`3pQ9)^-QGQnrs9>#do;PvS<=5jEad4XX)#%hnGmkY7^Qg{j&75%xHtc&b z^a8>h$DF8fI2(U3d+B{Sb!mu;9sDFX5f=xyswhoOC9B274mRl=&WGnJb zsKU+8)o0xSHso3Psr^9O<*A3>*7(lp+|-EHPRqnaJK3;f%e-9^QB&0+6Jeo zAX+o}fbvS$P5XsCJFJ$mm!|`ey3GtxGdeWFsxmhU@S69v_NF>NOt<1w5p+DNccRju z%7Qp$s~Q(M|2T?n&-7>T7X>SVt?#YwA3Xr?K@Mad3TXEsK)bTIwPfVH9|%{ zhV{7h_$zw6VXU+UOKr6<14Yw;#aZn-;-PkK`2f|+j0phW_URU-T2BE(0j2WYuka16 z)9>RyZRaO2ZpiPo@09|iV*YzPS9&Psgz2 z0~2do)12=`<sX1El-0jr)Kp%{T6#xmois-YrVI6>-=YqWQ{;( z;>6|BCnY6|PSwESOFWUsB2I_r%X)Q#pL9+tArfH$ZD0`#Phg>?2d+pb%4B|6*xAOJ>eI-f4LpT7_-7UewPJFM6P9Ewa)Ed;FhloN|_7IFq-Vg*3qKm;pH zN8(}iL4Mw3%>-gUYd@9V;C!)k7_bemv}Cf|*+pbrby0je2PNKErV|zISkEz6bX7BL3phu z${!RRCW68jLP`=TIE+Frm9*)K!h47MiX`0Z4t0Mm&**{ByCwWgmyMg-&`kV?rZWy| z2OsLOR*^c+(fiW&L)kDOiX`B0=A#6S+;5Rywt^8`Mk=3%z<`07p@(G3htke>=#?wk za5X>=6)#&`wl-4VO|sNguu@S$VL_&!prE4?qM#vDsK_r0Dk%#3-_j^3il}7&nN~+- z`bV8dC@8_UD3AY9M<03r^NB%TNa}yw(c-?NU?QIgk=NIpNB>d#iGL2-f27gMk!2`S z8ZrtB$h(HQtEHtAz{c6l%d%yV zdukbHS4(O>4qlEoG~!s))YPJ`7FNRQZ{_|$j(ifMv2kFLSg$;097YR$;|=HkMCN8|^?xDzQ}TDRzm4nf-HHBbOjrwG z=_=#w=xFKWCjMVDF8a5g{#)UHz31Nv-`jdwI_SQ&MN$HgV-n})65#y@*}oS3kEDA4 zMJmMm=ASA5spOw1|BOLc&D9q9qNaZ)QJhPZ^DlY-T3_7~;OyZ3r@EGtt(!RaKS=&1 z`yW)IoPXBkpVsN`Oz^i{Bo~NdiE{oYM~P!~p88~3>>>|34xB!ju0`PDmgx{=eUi zH7^8#aDh~T2Od3;RYf_M|GBq%0yfFGQcu`sVcf~Y&kty0+b@vQL0$Ol<7w3gb-0wP z-`_X5;8R}5>49s^K0NWVt)Voh+x(m_Y7}Z_oS*J*m(>gPRfImRHc4~`qfjLm_8r~{(HJ&KHmMfC+ubHm~#a6HLV`xk%&A>U;)0#kK}^)R#boM z+J(8=9i~11^Zq8->m8XQjb?_#L$cav@Znn1vcG_T9K)Uj0d6SA|GfP>@I#Vw@We<+ zy-vNBi-kCmElP$FQy~lud>+_E}lBoTOti{NQ`MZdD$Nb3evM_@Tf>V?V_6$7aGLwBhhTB^hQgqBM&__CtVw3EufBkO`M9HXQ4~#%X_7o|pQTqj`g{4$*u@BzS1`H8yr5 zAFo%iGM^B+z@O?+0;!zDeIqFT&1zc^z2dn9o{a3Tijh}j3)-f6YUQyr)>CEL$puNL z@wW4g^-A{r;UCv0Z>E%7OX}4A2cG%oKGZ*dwmKbkAai0)yXf-Of7KL`?m~k+F*_eW zxqVX9CH!y5@t-ig@#|*NL07jK4Yp#+{lh`b3ZF}j)W>HxbpPEv(F9J}PY<-+WPfXD z$`Gm@{ET|{YmQ+$68dU=8YKp~=lfdh;WEgnkCXk}5p7{=UHos?(PV$-#FVO|3wW5U z_;N59WLS-ZOD@O+*#7qXvuh|x^?18snaN@;?w?7Ilni@zixf8X`||;kmq*LaZ}&2j z9Q5iGD;JvSbVf2#q2J9S5{uf20SF%R}Ispa$Cmz`u0qA%CkGj zOh!WzG8`C$X|ddXSL=KvesdQsL1)ld9w(y1!K_&l^U+Q5JFvfwj< zJs^w+vOs&;0ry`xZKwhvbi0}2WwDp8CmNX0~@W1!J%2nxKP6kP{f)mHL%TGBQw5QDxYfX=5NE^0Baf5mJ)%v1mF*3+YU#Z- z3#DF^Ogf>IHMp~%UuvJbl{p%#Z^$2;b&jnuXR$Y8BU*+BE!@bf>(HMbm1}1ObZ)g?oJrfr&bL+*xPII{%mN+_Jb?H zY~MyBA|)F=m&rK8iGYbKC&|nj`obPIjKfa$ggU5r1QcE|k^T>Nc&Tq(;*_&bLLFwR zx!x(o3OCp*3?>a1u2wX?YjL}zu3n=b{Ov6FDabRG50LgT04RI(BP2Qg?ACq9t#yBH z7je($KJd5?+WSMR%yNsd4tpY%AMYp#lFgZ|S>cnv;Op$ktX~jv^`knOuO#Qw7|db* zuG;4tL0j^$HkFgCI@q%tu?=qqY!@7=;P|~_C0+jU>H_{QTUd;QKs+dy;c@T@^T?wdhZeW~v7;f?L!HYQRg zeAO{B9f&xOq*MD1L*MZIJ;J$8?T*%~T9U9hl26cdCS0cAZRnb6nHZ90ob1OWzKYnU zA+O+O__s4qnOUvh-XwE#WxeytSC55(pReI_WnJdA(Yo%Z1IId+*C9H<7BayVh260` zr#jW>!lUPE{TV`Meshm~^Pmw%B2Qm}ww7MqC9xT{u;mstUXVWibY*B*IKODGdwJuTMDmtR%-X<(GtDDH!E+shFK)cGYZ z8Ou~IplioPr?$iLeO=qdWlBi2v2%)tKot1xiCL$|`VV&>v~x6CrtOOl&W~|aKM6D4 zZ2~urlMCe{?ZnHTvmVn@ju_XSp`W@|K-tJk2 zC~(_Vf9<@!_@?HOL>vr6yCeZc^FErd>jLPX-+7Gk1aRusASI($@C<^Vn`G5%%Nz^aC&zGyrP@fFjzrH?fve}t#+BuIh1;;6 zWFyr#Kc{?s?e!oE*};@={HdB*3nZ-+<>o5{|9t5F?Oa?lmaGGcid^?pWBi!- zvBS$5s+Z+`i4MR@{&YD8nx_~C&1bGUNE;w|i~8{KJ+UV(mW!k?sOP|QiNa$v*rRHB z0F-Ypkjm#9<>(9#zBB?+#dSh(a71=wL=5V-FiUm7xqf#S0*&n;RyV~k+=F>#UDq7r;$^`>GAg@!qP(GIJFa!zmmVx zJLROOk1XR!lqZt%!Q@_?=WYSEN0Kpc(g%1T;*6x{F$?s~%OVT6&6V3n--v_z^P?}G zAzvEO+)l}7v$Bf{5j4Ui?eMUM9-3kTZI(&><|`0Du4lb~LD*R}SEf?BMmcvMu11=KqBejT=Z&xN+j=d zqvX2R##sCKc5I)lN>Ao_%l} z(muM+=jqN#O7TVP8#6WQW1}_fe?@0Zo{uV1fk`w#U*kbC^9((1EG^Nv2L|)K8Si_J zW1ZDDg5q}us%V9u&`E>$AVJN^xS2DNlYCmx@nV5ue{*Ylr#&DUfkh^4pQ@LAK- zm3*|#W@4lGr}5SUr!UK7ivy#yW{#{l#XArPi zLz(6nWRDLv3@C@n@di{$*xlm1M~r4)kO{~;UiI%ohR&K#`m*Viw(Q03GDUC7tR)7M zs!k`1H@;!(6cf8&yRGWf0-#wx#V0#FyVkvC)|Y_B8C#jqC+#p+tvGH=MFpf*VL9J; zP-{D}m9xw}wGzEI^&=ERYG?TAL;XCF%;rGi5Hs!R<}hn;GJv%cXBW%vtbhoW<%RwodorBuWEw+!B8k|gs4kTm#sV>DMLN{ZW2zX?kS-RnuK z!X$$aTB$L(_)+`r?hWh5l9-KwL=B|=#=Kl*bYMH*sIr20%`V}X=y4!|E*AX_>t#aN z%K@dpM>q8HQRG{kJZXGe+Y}XkPpDDVo4;qH7rz@wKi zKBJ$XUXPvSSwbrfYk>&dbu=59jB-+%76I$` z(@(HZv*8NGv13q|9QAUWowFBqE2;i=X^*Lxv#d4`lt*{RS`hu%hEH`?V1C>o;(|ZeMe;DKxv7Crb zr;uRfy_S(+G!p`TO&`g=Kb^U`tc-$&wJ=t}G1c^-6T z*H~?kEMIQmrOwAyu<(cMJ|xRi7LZ9m!4LkC5f3Z0eSm@qs1}p)h~M%;oprRs!cT?U z0PB;b_Xyk3oc75|Ee+lk%^;}^#hN_XLWkM$?>YoypChs(AZt{S&@%r<3>FBkzY!^) z1OAwAih)t~!z&FO@$=*SMhNNPTM58G0<+_Nd%lM8?$NJKafF))AE*k7#=V+&3L{23ut-ugiWtjS-VQl9@pzUoi+lDu9Zx$6lC2A9imntT~4#WEKQZ&8Zo5C z#HGaY&YpJB`k^bn;VA9sb-KZPV>=JAI&hJu%&&`c-!Iierk%Dq*2TY_!q~myNmDn?z&y*}VUr z#9gSE5*>Sg)X~}1>kcqY+xsD)onT+tJU1~_RjlUQTLyKFv`Z9&sqaZ=>T7M*L5Rsl z0tSMgTm9C!qYRl9yVXr^<~TNo9D-_X#&pDSeV)5b!f1!mwNyI^eXkDV#qlJFj=%5O zSAk!%r!8BhYfCxT;s)H%+uAJHj1q$b#!S94_qq|HVT!@L&>WX;(Q8jzwOrS60y*Ix z2Xiw{c{^0Q(2C`i)a}Ip@T&NOTc>oNN}7QEo-S2%B9-59%{oqQrRNfd<6M25tL5O# z_X<=_hsw@_Cr0IZPi)wJwo$FWY(y* z;!}7gk~!mpatUn}Y@u!OLH2bk<3j;4G(0*k4d3WD4!E;a zmKpCM&!4y?-54+125liUbJF*U0}v_EC^BA=s2OoY5n;n-6Xy{Vv?+`SPl2{J$3(O$1hQ z;k+WbI`l>5DcXVM8$T3VcC&J#3sZ1aMHgS;!d4b8n=8Rx*U3;L3MYT3LIptS1Is$q z+koFOxt!?Od!y8It{MZc&RWHt=P$?PDdV!P7M~xJPB3TkD#dD8aRQC0crFdSb3BpJ zM-Q1TyB9ZyzUz*tzeywb_6u`eH5P?Y>yi)nzqn@kx#rl!_j6$lRlGKtY7`uW)z^MuGu!rGVg#&i~hB( zEvlM8s-QG9N@ zpYptt(Xl)JJ!+c2k<}_P=uRK*GZ);F6No}<-o7_Sz{MzpIQ=hqtU*8MfUyuO;Z^byE3YSGC_Nx8ZP>pWL>YCkxRJ9)TYSrad}I zA!)uR?XL0P1u*T?Sf&lFhFHd~r+xCOn!0*{+c@cs?`Fs8*H32-#;{$4hQfo!v9Xp4 z9p|TOkL$eimKEKx;G>N`>jC54c$=wGYQD~UdeaVAi$}Y=-j&bX?Vxdm;oz9wNHSpz zpbZ&N#>V-vlOO0@33=pXY0nOHNCk;Gdo(7>$*#-cWd5+c+;5J$h}Bf(`=W6h?myp% z)YI>$To4Nn1|6izXNzH$rwc1mQBqVs)U$QgcwP|?q^X4P3%m>|q*c3=$Q&=u4Q?Rc zX&DD@49Cl3h%OrY>(+6b!0bdV(+p0ltd0k}=i4h06 zwYHY|JuJHJPS$|dSN*P6`{WV;`^9mt3wjBO!j8Y!fe4YyJOOFzkrXqFPb9>=J2C>5 zADiQpGr2n*V2i0sZ>Ld0bYBQ$N(|4uL0aa1xUEXbs$2HTXuDqw%}L2mSJ18o;SI}5 z6Gf3gcy*S|79PkuTa%s=sqS7jA7*yS)NQjFH|pv)I8eS3`HC^JYkgGklqzj@{1(z+ zm1{Hkvsvv^EXK}ADxV=-^jvb(e*gObbddPjb~-dQ01UrH+9w1!d)UQ4cQ1A&*t6UD z!A7<3oJs=#$k8^8I=E3qP%(1i`M#!(#1OI{#YO*%xq=@eXEMHF>$=h*rAAE36w6~B zm7`I{>oh4TJ)GyVHKgYqaQk>YJkGFCrB%eDqhmXA_bVouG5G;orm$yxv_zJf-_!Fp z>xWJvx9qe?x{SO&eye@NszaQEqvvhyJmXG2AUKKpeAa&)mL*aEJ8;~L#XO3A4LMI# ze?T|3G3iB6sm6jM%j;GXz}QF7Wk2ZibC;f%$x6YE!;h#e?2$wpJwoE-=gqJgh$QiS^ZB^aaC#nGMWcA_PO1>elIzB3n9|I%wN{DH zNaw!2;dc*t%eBTeW`zL_+ul~@Mgsk#YMQG3^jpz>Da%?+0ZMht$7y!a3QptSvX)go`P4I8=A$T%4 zDCUd4+AlqHG&Vi>0(Z!ut+07Su^BCq0xQO;yEul=p+(wmrc3?U?QdC?e?npdPX_{ zsrXP8`RR6ld<1a`nnpN9|aHF|Zw3tMb`kh~!<6&Z#WWI56tsVwWHy>Q=ie0;yFLU$o8UinRc*B-p zcgcM38e|ZSr<*j(Lz>zmz^Zg%$L|*j@_#{KB&i)xLDBrSwMWE}6_QUg_35o~5n_CI z^Y2S$#l=(k)a;;+OwLi1=Bg405*?270ZBT>RP20qi!^5vhCAT76Ymnl<&tjn2cGn9 z-2 z8L=sj2<`v8RuDhP2_70M%I}(O0m^^Tcta1ZHYB^wJO+W2B8$~o!r9&TE?;(-%c44^C38AQE#w& z`2ni?QXos>$Tr3;tS+~AQexGAsnnR1wqbThz&KvN!EQ#7Pbn7Tkj^Uf>IzrDzf$6A zKPN|zK4YX9LvvTHn)`Y-FpkT7=PXGdD29k|j)~I(JI+I<%|_(~+Qlo-#!;dS$QI1R za9}lFHF;K6FN-7Hu%xm6`&s|z=*KVpta`Hc0zWs9kQ8O@g~eDd(0*(s=+ zoEHE__z(Md9|iTFuCY3&Nl>X|ydI3~Kr`IdK z(A)ov6a0FvujN8wjvp#6k;OZ)pj`|b&2yhiz5v{ID?mJy+Ko)7A@|O6@x~s9NvU%D5+eR&hG2+FfuZ{_U~*@w+f_7d=tKz^SkvdJpi zJE|jgM+3eSBZ`yL0WIQ>4MFNqSr1ORCaw7?qixUMN>zg*>*D-%lY)Bt3k`h$%0{R8 zT*H|GP7%&Vy~bO!m3YrCjox~>>6=@-UDqS6tWD%jj8)LECQEf#;(=@*LzlR!%0LKQ zuQ@^X1ZKlu8X%to42Y{J`%nJk^>42svTkR_XuQ1Pk~w)KQeiKc$!*+6eLxCj8Zp<& zi>+7JIya)=QYXi;9JB{+R*VUda^@BpuoN-65=xF6n|zOmZrZjx-y*A$b6WyMZzitN zQh+xfT262-Z47yNf~*WavBWc|xc|Uy=J><=QV{MhrWxGhI|2|Y;Ku7Rz3%9%#d(?Y zt;T>cvWe%6DkoK{r`u7NF{4aHyg#@3x^(G7=7`Xc4qx}4oiTur=&NWh*aQdEXoS$Pfr_Sn?q4Od~S zB^SD=a6h?UT5W_}Fe0w_ihG`IP?Y!uiY5wN*L19z|-^N0b|*(PV|E@auU{s{=)qQ34NZyZdsxp?#kNU1u+!^SyPi z3M^cpBd9^8(p|^MrO+BG;y=5o=b>NnzOr5vJ__1WJIVW&ktR5OSM8Kv+`bq2lHRkD zJZn3UXuJrdZU-$ltK@gSe=q?{RYHd}f{fx$s8ka9>;=M>K0&h+%lu^L(s}d4rmOVpM)m>M_U0RdJf1707`fCKa9Zn@@riYQe@ zvp|1g>yd2F{XHpiCO{s1@9DpMB@9N|+(}4vJ4E%v*>yaGEOqw^?ofnkIPHCH7YgY3 zj)AV{xaAN32DzMmjsvfm%eYxD*K!o!Yo35@@|o|^h=J3ZWnjEHZ>v~wB;lXF+_kq% zDeOKJsf=&WH-5YHw6mWt@Nu(Tk%wusZ@^)!at<#X!cah~q$;KAn{xA8A|8(=Zgh;i z3+rvh78*0HLIgcWga}8bXL8NfdsWuzkF>vMlPO&}dCH$xm>!u=k;Mu}Mg@%R;vyBs zx&ZgL5O=J!xBCWb)I6~97|;jbsGKxjuo}AV=Esg4I-JSPtPqb2v*GUdI)V&u zAC1YwU)kQ!APR@)sqK^4K^%mWk}xddFShm2QJki>h{YRe8$xaJ_DYJc|FD zjrTW`PqO3@5|H7t(O`XVw({9O%LA<~Nh}ff8I@Ydty0=^28P>j2E&4D36b5VOyXL! z5!j3;A9;guNb{5BYn!HS#@j}E!V(nXLWs%sgyy+@jz*8&| zB&k6XhR1~$lh=eB4@3NOBO=cl#i7|>&`$^WaA%eMkyt-Zc*s=jA*^5LtMy4-A%8H3p>QaMME8#kNU|F5 zS#W?J(jhY2hTpOv{zO;_x*@OR(^55(>5%Ko~^ZfCiqgi1lV$OYbzJXkty=sr{rlPY^kDb9kKWe zk{KYRSl#uQ^yen1i#;2bhR!$#)jnAp(I|MyPO68&2O}K4axTt;N>;CJLATlEddqYZ zkf4yT2VgWsG5pKF;0?&fue3R-;%+R-U&AmIbv4S6P@*A=7F+fx!v%L2GN%%LIo7=~G%DL8;vR`~6CN;^C zdU>@B)xyB@Ql|7iru06!xgRg-RLOD_e>k;Ye|8y=2H`UYH;z%U0zxU1wXTlQ#OU$~ zKCc<`zLN^S6mgxQ1{hbhz3KSvq|sY0;eT78oZ@#fSWb%1y^-3^y;B;z*=giSHh4F* zKG`dr6q)YN-4x#UV7v9KYzO%DQ@DO4jLXo1CYo`U02^FL$UtjE%7nMLJluA9{!woeX31J1n=Ma~&o>ntwHeK0?Kj=m^;`$T{{@TY z8GotEfmEy$erB{zGfS{8K?K{bHP9E!#%POqh=A!jf-dW1s znMOzZvG7GlS?7Bs;LfvW3Q4zqpqDIu6uN=KHeYOXA@d<#|ru@hI9Arbt4_wC$X4aa@KTXS?osqT@RsifQDruTACnZ34$e z z)6xu)kFX`3u3CPjPSx34pfOqRZ2chZoU`jFJ!eWIFs{sS z-|p4HHBmJ$+9In!Yraq|#f@Xy8BR#9j{=&FiiJs-+Aemvi!Lk4&AKn;U1VFrsb7?sO@AAPrh) za#nBpaiGb`NyB7eS!889T#HLJi5HV8+7?aLLQ6z#b+LlzopiiLpe6sMnn8!6&X;0` zdvv>?Lj~Bf_!NtC)<>)K3Asm)aYkwsdrpauCY)z}_WaCVz+fo)~$adQ+ z5GR|1M%#73NIQWLRh@!aOStH$3KsFuQU6jd4&OUjNOlsBHDti~0lgsQrP0G+3Rlqf ztaCAEo4Dvpm+BZ6G>J*W?Wilxo^ax`DlCNeQkyq<6EgJZ8G%w1YouZ%3!sHS$o`U? zmO}N~Hb9$f7CWPzZ+XB}F;&t$tQh_U{n=Zw4DdZ%DWf*WZEy1RUVEmn&2)Weg%9*_ zF>m=TZqr+&$%zPWvNx)7d{D13L+>{oLJ-5^m^BzmwFa}8ZMGO=(Y1Tb{8XWNOQO)6 zTwUTjIq<#Nma+fBJ|cGqEH0DL zS?;GB{V4}QQGbarqjrD7b_XZRMx(eK2gt4TWu8u_(>iuiO`kKV8oOQYZh#rn{m((o zut|p8miGuI?eY+kh1KP3jOsQ%p8}HdyuK~NMp6ycZU8bUB_}md+F2L2Ok0sR`^0S^ ztf|kR4(|%6y~VCe7jWC`1f(qPX4k8F1fHv>&TUi{=)RA zofSraSC$vMO^0l0+{l$X2<-_jmC#m$mPNS0R3*_TnPFk|vfjw?qcNlL9@dU7-yk<5 z|NB(7wt4!iQ!1mY+RP%5f{ovDMT?ie^UUh(hC`eV#OcZoRgi5jQ}gVF8tBzzgO)(;YypRr!V<)1zP1ntgiE=6-pUD)){k3#?X%Xd6Xxsgl z8n<2U`P^mo2P*@^a+ba2kH}6k4>yq!Ieav?9PJ
;gLBW7KrTwnn@iuets>=U!`- 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

M|4!~-3cgu7U#8Pr4HL9(7d^4r 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 Kq*(UloBsm`DHQVn literal 0 HcmV?d00001 diff --git a/x-pack/plugins/remote_clusters/public/plugin.ts b/x-pack/plugins/remote_clusters/public/plugin.ts index 107d4e127d1b..540a8b40a620 100644 --- a/x-pack/plugins/remote_clusters/public/plugin.ts +++ b/x-pack/plugins/remote_clusters/public/plugin.ts @@ -60,13 +60,14 @@ export class RemoteClustersUIPlugin initNotification(toasts, fatalErrors); initHttp(http); - const isCloudEnabled = Boolean(cloud?.isCloudEnabled); + const isCloudEnabled: boolean = Boolean(cloud?.isCloudEnabled); + const cloudBaseUrl: string = cloud?.baseUrl ?? ''; const { renderApp } = await import('./application'); const unmountAppCallback = await renderApp( element, i18nContext, - { isCloudEnabled }, + { isCloudEnabled, cloudBaseUrl }, history ); diff --git a/x-pack/plugins/remote_clusters/tsconfig.json b/x-pack/plugins/remote_clusters/tsconfig.json index 0bee6300cf0b..9dc7926bd62e 100644 --- a/x-pack/plugins/remote_clusters/tsconfig.json +++ b/x-pack/plugins/remote_clusters/tsconfig.json @@ -8,10 +8,12 @@ "declarationMap": true }, "include": [ + "__jest__/**/*", "common/**/*", "fixtures/**/*", "public/**/*", "server/**/*", + "../../../typings/**/*", ], "references": [ { "path": "../../../src/core/tsconfig.json" }, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a1bb98669cd7..e42b87f38847 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -16756,10 +16756,6 @@ "xpack.remoteClusters.addTitle": "リモートクラスターを追加", "xpack.remoteClusters.appName": "リモートクラスター", "xpack.remoteClusters.appTitle": "リモートクラスター", - "xpack.remoteClusters.cloudClusterInformationDescription": "クラスターのプロキシアドレスとサーバー名を見つけるには、デプロイメニューの{security}ページに移動し、{searchString}を検索します。", - "xpack.remoteClusters.cloudClusterInformationTitle": "Elasticsearch Cloudデプロイのプロキシモードを使用", - "xpack.remoteClusters.cloudClusterSearchDescription": "リモートクラスターパラメーター", - "xpack.remoteClusters.cloudClusterSecurityDescription": "セキュリティ", "xpack.remoteClusters.configuredByNodeWarningTitle": "このリモートクラスターはノードの elasticsearch.yml 構成ファイルで定義されているため、編集または削除できません。", "xpack.remoteClusters.connectedStatus.connectedAriaLabel": "接続済み", "xpack.remoteClusters.connectedStatus.notConnectedAriaLabel": "未接続", @@ -16833,7 +16829,6 @@ "xpack.remoteClusters.remoteClusterForm.fieldServerNameRequiredLabel": "サーバー名", "xpack.remoteClusters.remoteClusterForm.fieldSocketConnectionsHelpText": "リモートクラスターごとに開くソケット接続の数。", "xpack.remoteClusters.remoteClusterForm.hideRequestButtonLabel": "リクエストを非表示", - "xpack.remoteClusters.remoteClusterForm.inputLocalSeedErrorMessage": "「シードノード」フィールドが無効です。", "xpack.remoteClusters.remoteClusterForm.inputNameErrorMessage": "「名前」フィールドが無効です。", "xpack.remoteClusters.remoteClusterForm.inputProxyErrorMessage": "「プロキシアドレス」フィールドが無効です。", "xpack.remoteClusters.remoteClusterForm.inputSeedsErrorMessage": "「シードノード」フィールドが無効です。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 1fa26ba98307..623e127bd84b 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -16981,10 +16981,6 @@ "xpack.remoteClusters.addTitle": "添加远程集群", "xpack.remoteClusters.appName": "远程集群", "xpack.remoteClusters.appTitle": "远程集群", - "xpack.remoteClusters.cloudClusterInformationDescription": "要查找您的集群的代理地址和服务器名称,请前往部署菜单的{security}页面并搜索“{searchString}”。", - "xpack.remoteClusters.cloudClusterInformationTitle": "将代理模式用于 Elastic Cloud 部署", - "xpack.remoteClusters.cloudClusterSearchDescription": "远程集群参数", - "xpack.remoteClusters.cloudClusterSecurityDescription": "安全", "xpack.remoteClusters.configuredByNodeWarningTitle": "您无法编辑或删除此远程集群,因为它是在节点的 elasticsearch.yml 配置文件中定义的。", "xpack.remoteClusters.connectedStatus.connectedAriaLabel": "已连接", "xpack.remoteClusters.connectedStatus.notConnectedAriaLabel": "未连接", @@ -17059,7 +17055,6 @@ "xpack.remoteClusters.remoteClusterForm.fieldServerNameRequiredLabel": "服务器名", "xpack.remoteClusters.remoteClusterForm.fieldSocketConnectionsHelpText": "每个远程集群要打开的套接字数目。", "xpack.remoteClusters.remoteClusterForm.hideRequestButtonLabel": "隐藏请求", - "xpack.remoteClusters.remoteClusterForm.inputLocalSeedErrorMessage": "“种子节点”字段无效。", "xpack.remoteClusters.remoteClusterForm.inputNameErrorMessage": "“名称”字段无效。", "xpack.remoteClusters.remoteClusterForm.inputProxyErrorMessage": "“代理地址”字段无效。", "xpack.remoteClusters.remoteClusterForm.inputSeedsErrorMessage": "“种子节点”字段无效。", From 2510fb18c7792ece57156ee55f8c9ef3f4353a3e Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 8 Apr 2021 11:00:30 -0400 Subject: [PATCH 24/49] [Lens] Fix Chart Switcher Icon Color Contrast (#96146) (#96344) * add new lns prefixed classes to target icon colors * correct groupPosition prop on visual options * account for icon accent color contrast * switch to ternary operator Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Michael Marcialis --- x-pack/plugins/lens/public/app_plugin/app.scss | 8 +++++--- .../visual_options_popover/visual_options_popover.tsx | 2 +- .../lens/public/xy_visualization/xy_config_panel.tsx | 5 ++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/lens/public/app_plugin/app.scss b/x-pack/plugins/lens/public/app_plugin/app.scss index 8416577a6042..b2b63015deef 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.scss +++ b/x-pack/plugins/lens/public/app_plugin/app.scss @@ -30,13 +30,15 @@ .lensChartIcon__subdued { fill: $euiTextSubduedColor; - // Not great, but the easiest way to fix the gray fill when stuck in a button with a fill - // Like when selected in a button group - .euiButton--fill & { + .lnsLayerChartSwitch__item-isSelected & { fill: currentColor; } } .lensChartIcon__accent { fill: $euiColorVis0; + + .lnsLayerChartSwitch__item-isSelected & { + fill: makeGraphicContrastColor($euiColorVis0, $euiColorDarkShade); + } } diff --git a/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/visual_options_popover.tsx b/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/visual_options_popover.tsx index fcdef86cc5d0..b8b89f146bdc 100644 --- a/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/visual_options_popover.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/visual_options_popover.tsx @@ -83,7 +83,7 @@ export const VisualOptionsPopover: React.FC = ({ defaultMessage: 'Visual options', })} type="visualOptions" - groupPosition="right" + groupPosition="left" buttonDataTestSubj="lnsVisualOptionsButton" isDisabled={isDisabled} > diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx index d7868a17bf9d..6f3017b80be1 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel.tsx @@ -98,10 +98,13 @@ export function LayerContextMenu(props: VisualizationLayerWidgetProps) { defaultMessage: 'Chart type', })} name="chartType" - className="eui-displayInlineBlock" + className="eui-displayInlineBlock lnsLayerChartSwitch" options={visualizationTypes .filter((t) => isHorizontalSeries(t.id as SeriesType) === horizontalOnly) .map((t) => ({ + className: `lnsLayerChartSwitch__item ${ + layer.seriesType === t.id ? 'lnsLayerChartSwitch__item-isSelected' : '' + }`, id: t.id, label: t.label, iconType: t.icon || 'empty', From 12ffed606217192d6eb59b543d6d59d97e9ef9c9 Mon Sep 17 00:00:00 2001 From: spalger Date: Thu, 8 Apr 2021 08:13:51 -0700 Subject: [PATCH 25/49] skip entire fleet_api_integration suite to unblock es promotion (#96515) (cherry picked from commit afc1fd022e9ead8685a7e63a1b738688f5c82a44) --- x-pack/scripts/functional_tests.js | 3 ++- x-pack/test/fleet_api_integration/apis/agents_setup.ts | 3 +-- x-pack/test/fleet_api_integration/apis/epm/list.ts | 3 +-- x-pack/test/fleet_api_integration/apis/fleet_setup.ts | 3 +-- .../security_solution_endpoint_api_int/apis/artifacts/index.ts | 3 +-- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js index ccecea04591e..98b74a1566ce 100644 --- a/x-pack/scripts/functional_tests.js +++ b/x-pack/scripts/functional_tests.js @@ -70,7 +70,8 @@ require('@kbn/test').runTestsCli([ require.resolve('../test/reporting_api_integration/reporting_and_security.config.ts'), require.resolve('../test/reporting_api_integration/reporting_without_security.config.ts'), require.resolve('../test/security_solution_endpoint_api_int/config.ts'), - require.resolve('../test/fleet_api_integration/config.ts'), + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/96515 + // require.resolve('../test/fleet_api_integration/config.ts'), require.resolve('../test/functional_enterprise_search/without_host_configured.config.ts'), require.resolve('../test/functional_vis_wizard/config.ts'), require.resolve('../test/search_sessions_integration/config.ts'), diff --git a/x-pack/test/fleet_api_integration/apis/agents_setup.ts b/x-pack/test/fleet_api_integration/apis/agents_setup.ts index d49bc91251b0..91d6ca0119d1 100644 --- a/x-pack/test/fleet_api_integration/apis/agents_setup.ts +++ b/x-pack/test/fleet_api_integration/apis/agents_setup.ts @@ -15,8 +15,7 @@ export default function (providerContext: FtrProviderContext) { const es = getService('es'); const esArchiver = getService('esArchiver'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/96515 - describe.skip('fleet_agents_setup', () => { + describe('fleet_agents_setup', () => { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('empty_kibana'); diff --git a/x-pack/test/fleet_api_integration/apis/epm/list.ts b/x-pack/test/fleet_api_integration/apis/epm/list.ts index 0a7002764a54..5a991e52bdba 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/list.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/list.ts @@ -19,8 +19,7 @@ export default function (providerContext: FtrProviderContext) { // because `this` has to point to the Mocha context // see https://mochajs.org/#arrow-functions - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/96515 - describe.skip('EPM - list', async function () { + describe('EPM - list', async function () { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('fleet/empty_fleet_server'); diff --git a/x-pack/test/fleet_api_integration/apis/fleet_setup.ts b/x-pack/test/fleet_api_integration/apis/fleet_setup.ts index a82ed3f8cf22..c9709475d182 100644 --- a/x-pack/test/fleet_api_integration/apis/fleet_setup.ts +++ b/x-pack/test/fleet_api_integration/apis/fleet_setup.ts @@ -15,8 +15,7 @@ export default function (providerContext: FtrProviderContext) { const es = getService('es'); const esArchiver = getService('esArchiver'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/96515 - describe.skip('fleet_setup', () => { + describe('fleet_setup', () => { skipIfNoDockerRegistry(providerContext); before(async () => { await esArchiver.load('empty_kibana'); diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts b/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts index 8ee028ae3f56..e1edeb780869 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts @@ -19,8 +19,7 @@ export default function (providerContext: FtrProviderContext) { const supertestWithoutAuth = getSupertestWithoutAuth(providerContext); let agentAccessAPIKey: string; - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/96515 - describe.skip('artifact download', () => { + describe('artifact download', () => { const esArchiverSnapshots = [ 'endpoint/artifacts/fleet_artifacts', 'endpoint/artifacts/api_feature', From 3ee7b36bd1207e75a7daac610d3e279c42cc8b57 Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Thu, 8 Apr 2021 16:28:28 +0100 Subject: [PATCH 26/49] [ML] Excludes metadata fields from jobs caps fields service response (#96548) (#96573) --- .../ml/server/models/job_service/new_job_caps/field_service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts index 0287c2af11a7..c6cf608fe1e0 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts @@ -80,7 +80,7 @@ class FieldsService { if (firstKey !== undefined) { const field = fc[firstKey]; // add to the list of fields if the field type can be used by ML - if (supportedTypes.includes(field.type) === true) { + if (supportedTypes.includes(field.type) === true && field.metadata_field !== true) { fields.push({ id: k, name: k, From 7fcddeca12f80fee3a9ef2a53c70388bcd10f8cb Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 8 Apr 2021 11:33:54 -0400 Subject: [PATCH 27/49] Document SO migrations enableV2 and batchSize config options (#96290) (#96587) * document SO batchsize and migrationsv2 enablement options * use refs by name * Update docs/setup/settings.asciidoc Co-authored-by: Luke Elmers * apply Lukes suggestion * add a note that migrations.enableV2 will be removed soon * document migrations.retryAttempts * Apply suggestions from code review Co-authored-by: Kaarina Tungseth Co-authored-by: Luke Elmers Co-authored-by: Kaarina Tungseth Co-authored-by: Mikhail Shustov Co-authored-by: Luke Elmers Co-authored-by: Kaarina Tungseth --- docs/setup/settings.asciidoc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index 643718b96165..90e813afad6f 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -429,6 +429,15 @@ to display map tiles in tilemap visualizations. By default, override this parameter to use their own Tile Map Service. For example: `"https://tiles.elastic.co/v2/default/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana"` +| `migrations.batchSize:` + | Defines the number of documents migrated at a time. The higher the value, the faster the Saved Objects migration process performs at the cost of higher memory consumption. If the migration fails due to a `circuit_breaking_exception`, set a smaller `batchSize` value. *Default: `1000`* + +| `migrations.enableV2:` + | experimental[]. Enables the new Saved Objects migration algorithm. For information about the migration algorithm, refer to <>. When `migrations v2` is stable, the setting will be removed in an upcoming release without any further notice. Setting the value to `false` causes {kib} to use the legacy migration algorithm, which shipped in 7.11 and earlier versions. *Default: `true`* + +| `migrations.retryAttempts:` + | The number of times migrations retry temporary failures, such as a network timeout, 503 status code, or `snapshot_in_progress_exception`. When upgrade migrations frequently fail after exhausting all retry attempts with a message such as `Unable to complete the [...] step after 15 attempts, terminating.`, increase the setting value. *Default: `15`* + | `newsfeed.enabled:` | Controls whether to enable the newsfeed system for the {kib} UI notification center. Set to `false` to disable the From 5cf095032e815f17e3472dc64a5dd6d0f69cac24 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 8 Apr 2021 11:05:13 -0500 Subject: [PATCH 28/49] skip flaky test. #77933 --- x-pack/test/accessibility/apps/spaces.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/accessibility/apps/spaces.ts b/x-pack/test/accessibility/apps/spaces.ts index 032186b2e90e..41926628c237 100644 --- a/x-pack/test/accessibility/apps/spaces.ts +++ b/x-pack/test/accessibility/apps/spaces.ts @@ -24,7 +24,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.common.navigateToApp('home'); }); - it('a11y test for manage spaces menu from top nav on Kibana home', async () => { + // flaky https://github.com/elastic/kibana/issues/77933 + it.skip('a11y test for manage spaces menu from top nav on Kibana home', async () => { await PageObjects.spaceSelector.openSpacesNav(); await retry.waitFor( 'Manage spaces option visible', From d2bc43c6b343f1c258b86f5112514902f95e26e9 Mon Sep 17 00:00:00 2001 From: Nick Partridge Date: Thu, 8 Apr 2021 11:33:06 -0500 Subject: [PATCH 29/49] [Dashboard] Fix Lens and TSVB chart tooltip positioning relative to global headers (#94247) (#96578) --- src/core/public/rendering/_base.scss | 14 ++++++++++++++ src/core/public/rendering/rendering_service.tsx | 1 + .../visualizations/views/timeseries/index.js | 1 + .../vis_type_xy/public/components/xy_settings.tsx | 4 +++- .../public/pie_visualization/render_function.tsx | 2 ++ .../__snapshots__/expression.test.tsx.snap | 7 +++++++ .../lens/public/xy_visualization/expression.tsx | 2 +- 7 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/core/public/rendering/_base.scss b/src/core/public/rendering/_base.scss index de13785a17f5..ed2d9bc0b391 100644 --- a/src/core/public/rendering/_base.scss +++ b/src/core/public/rendering/_base.scss @@ -11,6 +11,16 @@ min-height: 100%; } +#app-fixed-viewport { + pointer-events: none; + visibility: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + .app-wrapper { display: flex; flex-flow: column nowrap; @@ -35,6 +45,10 @@ @mixin kbnAffordForHeader($headerHeight) { padding-top: $headerHeight; + #app-fixed-viewport { + top: $headerHeight; + } + .euiFlyout, .euiCollapsibleNav { top: $headerHeight; diff --git a/src/core/public/rendering/rendering_service.tsx b/src/core/public/rendering/rendering_service.tsx index 843f2a253f33..787fa475c7d5 100644 --- a/src/core/public/rendering/rendering_service.tsx +++ b/src/core/public/rendering/rendering_service.tsx @@ -52,6 +52,7 @@ export class RenderingService { {chromeHeader}

+
{bannerComponent}
{appComponent}
diff --git a/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/index.js b/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/index.js index c973b7b89893..f9a52a9450dc 100644 --- a/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/index.js +++ b/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/index.js @@ -149,6 +149,7 @@ export const TimeSeries = ({ tooltip={{ snap: true, type: tooltipMode === 'show_focused' ? TooltipType.Follow : TooltipType.VerticalCursor, + boundary: document.getElementById('app-fixed-viewport') ?? undefined, headerFormatter: tooltipFormatter, }} externalPointerEvents={{ tooltip: { visible: false } }} diff --git a/src/plugins/vis_type_xy/public/components/xy_settings.tsx b/src/plugins/vis_type_xy/public/components/xy_settings.tsx index 59bed0060a6a..8922f512522a 100644 --- a/src/plugins/vis_type_xy/public/components/xy_settings.tsx +++ b/src/plugins/vis_type_xy/public/components/xy_settings.tsx @@ -148,13 +148,15 @@ export const XYSettings: FC = ({ : headerValueFormatter && (tooltip.detailedTooltip ? undefined : ({ value }: any) => headerValueFormatter(value)); + const boundary = document.getElementById('app-fixed-viewport') ?? undefined; const tooltipProps: TooltipProps = tooltip.detailedTooltip ? { ...tooltip, + boundary, customTooltip: tooltip.detailedTooltip(headerFormatter), headerFormatter: undefined, } - : { ...tooltip, headerFormatter }; + : { ...tooltip, boundary, headerFormatter }; return (
Date: Thu, 8 Apr 2021 13:24:40 -0400 Subject: [PATCH 32/49] [Security Solution][Rac][Tgrid] Use correct prop name for disabling timeline context menu button (#96453) (#96586) * Use correct prop name for disabling timeline context menu button * Update usages of disabled to isDisabled on EuiIconButton * Update failing snapshot and tests looking for old prop --- .../add_to_case_action.test.tsx | 4 +- .../timeline_actions/add_to_case_action.tsx | 2 +- .../timeline_actions/alert_context_menu.tsx | 167 +++++++++--------- .../tooltip_footer.test.tsx.snap | 4 +- .../map_tool_tip/tooltip_footer.test.tsx | 32 ++-- .../map_tool_tip/tooltip_footer.tsx | 4 +- 6 files changed, 110 insertions(+), 103 deletions(-) diff --git a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.test.tsx b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.test.tsx index c99cabb50e3d..40a202f5257a 100644 --- a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.test.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.test.tsx @@ -341,7 +341,7 @@ describe('AddToCaseAction', () => { ); expect( - wrapper.find(`[data-test-subj="attach-alert-to-case-button"]`).first().prop('disabled') + wrapper.find(`[data-test-subj="attach-alert-to-case-button"]`).first().prop('isDisabled') ).toBeTruthy(); }); @@ -358,7 +358,7 @@ describe('AddToCaseAction', () => { ); expect( - wrapper.find(`[data-test-subj="attach-alert-to-case-button"]`).first().prop('disabled') + wrapper.find(`[data-test-subj="attach-alert-to-case-button"]`).first().prop('isDisabled') ).toBeTruthy(); }); }); diff --git a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.tsx b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.tsx index decd37a7646e..45c1355cecfa 100644 --- a/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.tsx @@ -172,7 +172,7 @@ const AddToCaseActionComponent: React.FC = ({ size="s" iconType="folderClosed" onClick={openPopover} - disabled={isDisabled} + isDisabled={isDisabled} /> ), diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx index b2e5638ff120..26b9662a8f19 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx @@ -215,19 +215,20 @@ const AlertContextMenuComponent: React.FC = ({ setEventsLoading, ]); - // eslint-disable-next-line react-hooks/exhaustive-deps - const openAlertActionComponent = ( - - {i18n.ACTION_OPEN_ALERT} - - ); + const openAlertActionComponent = useMemo(() => { + return ( + + {i18n.ACTION_OPEN_ALERT} + + ); + }, [openAlertActionOnClick, hasIndexUpdateDelete, hasIndexMaintenance]); const closeAlertActionClick = useCallback(() => { updateAlertStatusAction({ @@ -248,19 +249,20 @@ const AlertContextMenuComponent: React.FC = ({ setEventsLoading, ]); - // eslint-disable-next-line react-hooks/exhaustive-deps - const closeAlertActionComponent = ( - - {i18n.ACTION_CLOSE_ALERT} - - ); + const closeAlertActionComponent = useMemo(() => { + return ( + + {i18n.ACTION_CLOSE_ALERT} + + ); + }, [closeAlertActionClick, hasIndexUpdateDelete, hasIndexMaintenance]); const inProgressAlertActionClick = useCallback(() => { updateAlertStatusAction({ @@ -281,72 +283,77 @@ const AlertContextMenuComponent: React.FC = ({ setEventsLoading, ]); - // eslint-disable-next-line react-hooks/exhaustive-deps - const inProgressAlertActionComponent = ( - - {i18n.ACTION_IN_PROGRESS_ALERT} - - ); - - const button = ( - - - - ); + const inProgressAlertActionComponent = useMemo(() => { + return ( + + {i18n.ACTION_IN_PROGRESS_ALERT} + + ); + }, [canUserCRUD, hasIndexUpdateDelete, inProgressAlertActionClick]); + + const button = useMemo(() => { + return ( + + + + ); + }, [disabled, onButtonClick, ariaLabel]); const handleAddEndpointExceptionClick = useCallback((): void => { closePopover(); setOpenAddExceptionModal('endpoint'); }, [closePopover]); - // eslint-disable-next-line react-hooks/exhaustive-deps - const addEndpointExceptionComponent = ( - - {i18n.ACTION_ADD_ENDPOINT_EXCEPTION} - - ); + const addEndpointExceptionComponent = useMemo(() => { + return ( + + {i18n.ACTION_ADD_ENDPOINT_EXCEPTION} + + ); + }, [canUserCRUD, hasIndexWrite, isEndpointAlert, handleAddEndpointExceptionClick]); const handleAddExceptionClick = useCallback((): void => { closePopover(); setOpenAddExceptionModal('detection'); }, [closePopover]); - // eslint-disable-next-line react-hooks/exhaustive-deps - const addExceptionComponent = ( - - - {i18n.ACTION_ADD_EXCEPTION} - - - ); + const addExceptionComponent = useMemo(() => { + return ( + + + {i18n.ACTION_ADD_EXCEPTION} + + + ); + }, [handleAddExceptionClick, canUserCRUD, hasIndexWrite]); const statusFilters = useMemo(() => { if (!alertStatus) { diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/__snapshots__/tooltip_footer.test.tsx.snap b/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/__snapshots__/tooltip_footer.test.tsx.snap index 8db9006da615..1b91d396bee3 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/__snapshots__/tooltip_footer.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/__snapshots__/tooltip_footer.test.tsx.snap @@ -27,16 +27,16 @@ exports[`ToolTipFilter renders correctly against snapshot 1`] = ` aria-label="Next" color="text" data-test-subj="previous-feature-button" - disabled={true} iconType="arrowLeft" + isDisabled={true} onClick={[MockFunction]} /> diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/tooltip_footer.test.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/tooltip_footer.test.tsx index a74022a22252..cc7662cf1e96 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/tooltip_footer.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/tooltip_footer.test.tsx @@ -42,7 +42,7 @@ describe('ToolTipFilter', () => { ); expect( - wrapper.find('[data-test-subj="previous-feature-button"]').first().prop('disabled') + wrapper.find('[data-test-subj="previous-feature-button"]').first().prop('isDisabled') ).toBe(true); }); @@ -70,9 +70,9 @@ describe('ToolTipFilter', () => { /> ); - expect(wrapper.find('[data-test-subj="next-feature-button"]').first().prop('disabled')).toBe( - false - ); + expect( + wrapper.find('[data-test-subj="next-feature-button"]').first().prop('isDisabled') + ).toBe(false); }); test('nextFeature is called when featureIndex is < totalFeatures', () => { @@ -102,7 +102,7 @@ describe('ToolTipFilter', () => { ); expect( - wrapper.find('[data-test-subj="previous-feature-button"]').first().prop('disabled') + wrapper.find('[data-test-subj="previous-feature-button"]').first().prop('isDisabled') ).toBe(false); }); @@ -130,9 +130,9 @@ describe('ToolTipFilter', () => { /> ); - expect(wrapper.find('[data-test-subj="next-feature-button"]').first().prop('disabled')).toBe( - true - ); + expect( + wrapper.find('[data-test-subj="next-feature-button"]').first().prop('isDisabled') + ).toBe(true); }); test('nextFunction is not called when featureIndex >== totalFeatures', () => { @@ -161,7 +161,7 @@ describe('ToolTipFilter', () => { ); expect( - wrapper.find('[data-test-subj="previous-feature-button"]').first().prop('disabled') + wrapper.find('[data-test-subj="previous-feature-button"]').first().prop('isDisabled') ).toBe(true); }); @@ -189,9 +189,9 @@ describe('ToolTipFilter', () => { /> ); - expect(wrapper.find('[data-test-subj="next-feature-button"]').first().prop('disabled')).toBe( - true - ); + expect( + wrapper.find('[data-test-subj="next-feature-button"]').first().prop('isDisabled') + ).toBe(true); }); test('nextFunction is not called when only a single feature is provided', () => { @@ -221,7 +221,7 @@ describe('ToolTipFilter', () => { ); expect( - wrapper.find('[data-test-subj="previous-feature-button"]').first().prop('disabled') + wrapper.find('[data-test-subj="previous-feature-button"]').first().prop('isDisabled') ).toBe(false); }); @@ -249,9 +249,9 @@ describe('ToolTipFilter', () => { /> ); - expect(wrapper.find('[data-test-subj="next-feature-button"]').first().prop('disabled')).toBe( - false - ); + expect( + wrapper.find('[data-test-subj="next-feature-button"]').first().prop('isDisabled') + ).toBe(false); }); test('nextFunction is called when featureIndex > 0 && featureIndex < totalFeatures', () => { diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/tooltip_footer.tsx b/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/tooltip_footer.tsx index 252260b2c5a2..dbb280228e50 100644 --- a/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/tooltip_footer.tsx +++ b/x-pack/plugins/security_solution/public/network/components/embeddables/map_tool_tip/tooltip_footer.tsx @@ -54,7 +54,7 @@ export const ToolTipFooterComponent = ({ onClick={previousFeature} iconType="arrowLeft" aria-label="Next" - disabled={featureIndex <= 0} + isDisabled={featureIndex <= 0} /> = totalFeatures - 1} + isDisabled={featureIndex >= totalFeatures - 1} /> From 9daedb2671a49facb4c1996577808eba39a01c2b Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Thu, 8 Apr 2021 12:40:37 -0500 Subject: [PATCH 33/49] [DOCS] Adds the release notes and breaking changes from previous releases (#96608) --- docs/CHANGELOG.asciidoc | 6562 +++++++++++++++++++++++++++++++++++++++ docs/index.asciidoc | 2 + 2 files changed, 6564 insertions(+) diff --git a/docs/CHANGELOG.asciidoc b/docs/CHANGELOG.asciidoc index 74062ac52413..71c05052c018 100644 --- a/docs/CHANGELOG.asciidoc +++ b/docs/CHANGELOG.asciidoc @@ -11,6 +11,43 @@ Review important information about the {kib} 7.12.x releases. * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> +// * <> -- @@ -458,3 +495,6528 @@ Reporting:: * Deserialize query string options for serverside ES Query {kibana-pull}90050[#90050] Security:: * Do not generate an ephemeral encryption key in production {kibana-pull}81511[#81511] + +//// +[[release-notes-7.11.2]] +== {kib} 7.11.2 + +The 7.11.2 release includes the following security update, known issue, and bug fixes. For information on the breaking changes, refer to <>. + +[float] +[[security-update-v7.11.2]] +=== Security update + +When you use the following background API calls, {kib} extends your session and fails to log you out: + +* POST /api/ui_metric/report + +* POST /api/index_management/indices/reload + +* POST /api/index_lifecycle_management/policies?withIndices=true + +* GET /api/remote_clusters + +* GET /api/saved_objects_tagging/tags + +To avoid extending the session, use the `kbn-system-request` header, which indicates that the API call is not a user request. + +[float] +[[known-issues-v7.11.2]] +=== Known issue + +When upgrading from 7.11.0 or 7.11.1 to 7.11.2, certain connectors, including those that connect to Jira, +ServiceNow, and IBM Resilient, are not properly migrated during the upgrade process, causing them to be +deleted. + +Impacts include: + +* Kibana *Alerts and Actions* that have been configured to use the affected connectors will no +longer create these actions. +* Security detection rules that have been configured to use the affected connectors as part of their +rule actions will no longer create these actions. +* Security Case workflow users will need to recreate external connectors before cases can be pushed +or updated via the affected connectors. +* Open cases that were previously connected to third-party systems via the affected connectors will +need to be re-connected after the connector(s) are recreated. + +If you use these affected connectors, it is recommended to consider delaying the upgrade to 7.11.2, +and instead upgrade to 7.12.0 once it is released. + +[float] +[[bug-v7.11.2]] +=== Bug fixes +Alerting:: +* For simplistic email servers, set `rejectUnauthorized` to `false` {kibana-pull}91760[#91760] +APM:: +* Fixes an issue preventing metric-document only services from displaying in the Services overview list {kibana-pull}92378[#92378] +Canvas:: +* Removes custom plot plugins when *Canvas* is unmounted {kibana-pull}90722[#90722] +Elastic Security:: +For the Elastic Security 7.11.2 bug fixes, refer to {security-guide}/release-notes.html[_Elastic Security Solution Release Notes_]. +Lens and visualizations:: +* Fixes *TSVB* chart scroll when legend has many items {kibana-pull}91394[#91394] +* Use timestamp on brush event instead of iso dates {kibana-pull}91483[#91483] +Machine Learning:: +* Fixes geo_shape content causing *Data Visualizer* to not load correctly {kibana-pull}92052[#92052] +* Fixes applying missing_bucket configuration to transform request payload {kibana-pull}91635[#91635] +Management:: +* Fixes use of undefined value in JS import {kibana-pull}92791[#92791] +* Fixes an issue where users were unable to configure replicas in the cold phase when searchable snapshots are enabled {kibana-pull}92782[#92782] +Metrics:: +* Fixes `ignoreLookback` behavior for Snapshot API {kibana-pull}91169[#91169] +Security:: +* Fixes an issue where `elasticsearch.sniffInterval`, `elasticsearch.sniffOnConnectionFault`, or `elasticsearch.sniffOnStart` causes an authentication issue when performing requests against the sniffed nodes {kibana-pull}91276[#91276] +* Fixes session idle timeout {kibana-pull}91070[#91070] + +[[release-notes-7.11.1]] +== {kib} 7.11.1 + +The 7.11.1 release includes the following enhancements and bug fixes. For information on the breaking changes, refer to <>. + +[float] +[[enhancement-v7.11.1]] +=== Enhancements +Machine Learning:: +* Improves the lazy ML node UI {kibana-pull}90455[#90455] +Security:: +* Prevent autocompleting the username field {kibana-pull}88682[#88682] + +[float] +[[bug-v7.11.1]] +=== Bug fixes +Dashboard:: +* Fixes a 7.11.0 regression where pending dashboard searches aren't canceled when navigating to another app {kibana-pull}90306[#90306] +* Sync tooltip legend values {kibana-pull}90036[#90036] +Discover:: +* Fixes 'auto' collapsing of documents {kibana-pull}89712[#89712] +Elastic Security Solution:: +For the Elastic Security Solution 7.11.1 bug fixes, refer to {security-guide}/release-notes.html[_Elastic Security Solution Release Notes_]. +Lens and visualizations:: +* *Lens* visualizations now load faster on dashboards {kibana-pull}88953[#88953] +* Advanced input now works for aggregation-based visualizations {kibana-pull}88154[#88154] +Maps:: +* Always check license at plugin startup {kibana-pull}87873[#87873] +Monitoring:: +* Fully control the in memory table pagination and sorting properties {kibana-pull}85862[#85862] +* Tweak timeout for failing cloud test {kibana-pull}86671[#86671] +* Stop using constructor.name for logstash pipelines {kibana-pull}87386[#87386] +* Make sure we use the right duration for messaging on this alert {kibana-pull}87579[#87579] +* Avoid spamming toast messages {kibana-pull}89930[#89930] + + +[[release-notes-7.11.0]] +== {kib} 7.11.0 + +For detailed information about the 7.11.0 release, review the <>, <>, and <>. +For the 7.11.0 breaking changes, refer to <>. + +[float] +[[deprecation-v7.11.0]] +=== Deprecations +Lens and visualizations:: +* Deprecates `visualization:colorMapping` advanced setting {kibana-pull}83372[#83372] +Management:: +* Deprecates `kibana.index` setting {kibana-pull}83988[#83988] +* Deprecates `reporting.index` setting {kibana-pull}84005[#84005] +* Deprecates `xpack.task_manager.index` setting {kibana-pull}84155[#84155] +Security:: +* Deprecates disabling the spaces plugin {kibana-pull}83984[#83984] +* Deprecates disabling the security plugin {kibana-pull}85159[#85159] + +[float] +[[enhancement-v7.11.0]] +=== Enhancements +Alerting:: +* Updates alert type selection layout to rows instead of grid {kibana-pull}73665[#73665] +* Back Button on Add Connector Flyout {kibana-pull}80160[#80160] +* Disables "Save" button for Alerts with broken Connectors {kibana-pull}80579[#80579] +* Adds UI notifier to indicate secret fields and to remember / reenter values {kibana-pull}80657[#80657] +* Adds `defaultActionMessage` to index threshold alert UI type definition {kibana-pull}80936[#80936] +* Don't wait for health check before showing Create Alert flyout {kibana-pull}80996[#80996] +* Adds `hasAuth` to Webhook Configuration to avoid confusing UX {kibana-pull}81390[#81390] +* Grouped list of alert types using producers in Types filter of Alerts tab {kibana-pull}81876[#81876] +* Adds Alerts & Actions to the app directory {kibana-pull}81902[#81902] +* Adds a link to documentation in the alerts and actions management UI {kibana-pull}81909[#81909] +* Adds an Run When field in the alert flyout to assign the action to an Action Group {kibana-pull}82472[#82472] +* Displays Action Group in Alert Details {kibana-pull}82645[#82645] +* Removes placeholders and updates validation messages on connector forms {kibana-pull}82734[#82734] +* Notify only on action group change {kibana-pull}82969[#82969] +* Adds ability to assign alert actions to resolved action group in UI {kibana-pull}83139[#83139] +* Microsoft Teams connector {kibana-pull}83169[#83169] +* Adds action group and date to mustache template variables for actions {kibana-pull}83195[#83195] +* Updates widths on columns in Alert Detail view {kibana-pull}83823[#83823] +* Escaping is now off for most action parameters, except those that need per-action escaping, including the Slack, Email, and Webhook action parameters {kibana-pull}83919[#83919] +* Adds ECS audit events for alerts and actions plugins {kibana-pull}84113[#84113] +* Adds footer to all emails sent by Kibana email connector with a link to open Kibana or to the alert details page {kibana-pull}84371[#84371] +* Adds default dedupKey value as an {{alertInstanceId}} to provide grouping functionality for PagerDuty incidents {kibana-pull}84598[#84598] +APM:: +* Transition to Elastic charts for all relevant APM charts {kibana-pull}80298[#80298] +* APM Experiments settings {kibana-pull}81554[#81554] +* APM index settings import/export in saved-object management {kibana-pull}82784[#82784] +* Service overview: Dependencies table {kibana-pull}83416[#83416] +* Service overview: Transactions table {kibana-pull}83429[#83429] +* Latency chart for overview {kibana-pull}84634[#84634] +* Add APM agent config options {kibana-pull}84678[#84678] +* Updates header icons {kibana-pull}84760[#84760] +* Adds log_level/sanitize_field_names config options to Python Agent {kibana-pull}84810[#84810] +* Adds `ignore_unavailable` to avoid querying closed indices {kibana-pull}84813[#84813] +* Adds sanitize_field_names and transaction_ignore_urls config options to Ruby agent {kibana-pull}85646[#85646] +* Adds transaction_ignore_urls as central config {kibana-pull}85734[#85734] +* Service overview: Instances table {kibana-pull}85770[#85770] +* APM Alerts Preview charts {kibana-pull}85868[#85868] +Canvas:: +* Layout option for generating full-page Canvas reports {kibana-pull}84959[#84959] +Dashboard:: +* Library Notification Popover {kibana-pull}79581[#79581] +* Url Drilldown basic template helpers {kibana-pull}80500[#80500] +* Edit Panel Title On Click {kibana-pull}81076[#81076] +* Dashboards connected via drilldowns are now exported or copied to a different space together {kibana-pull}82602[#82602] +* Panel toolbar {kibana-pull}83342[#83342] +* Export CSV action for Lens embeddables in dashboard {kibana-pull}83654[#83654] +* ExternalUrl service was integrated with URL Drilldown {kibana-pull}85779[#85779] +Discover:: +* Adds new responsive layout {kibana-pull}83633[#83633] +Elastic Security Solution:: +For the Elastic Security Solution 7.11.0 release information, refer to {security-guide}/release-notes.html[_Elastic Security Solution Release Notes_]. +Fleet:: +* Agent logs UI {kibana-pull}83356[#83356] +Lens and visualizations:: +* Adds categorical color palettes in Lens {kibana-pull}75309[#75309] +* Adds color for dimension trigger in Lens {kibana-pull}76871[#76871] +* Adds median operation in Lens {kibana-pull}79453[#79453] +* Improves the range formatter {kibana-pull}80132[#80132] +* Adds drag support within dimension group to reorder in Lens {kibana-pull}80547[#80547] +* Renames X/Y axis to horizontal/vertical in Lens {kibana-pull}80991[#80991] +* Adds value labels in Lens bar charts {kibana-pull}81776[#81776] +* Enables "Other" bucket for top values operation in Lens {kibana-pull}82704[#82704] +* Adds CSV Export for Lens {kibana-pull}83430[#83430] +* Adds "Last value" operation to Lens {kibana-pull}83437[#83437] +* Adds sorting to Lens data tables {kibana-pull}84435[#84435] +* Adds in-product help to Lens fields list {kibana-pull}85544[#85544] +* Adds toggle to height data table export button {kibana-pull}70801[#70801] +* Adds support for HDR percentiles in TSVB visualizations {kibana-pull}78306[#78306] +* Displays epoch on a more human readable format for TSVB {kibana-pull}79110[#79110] +* Adds *Ignore global filters* to series options in TSVB {kibana-pull}79337[#79337] +* Updates *New visualization* window {kibana-pull}79627[#79627] +* Adds `textTruncate` option for tooltips {kibana-pull}80524[#80524] +* Renames 'positive rate' to 'counter rate' {kibana-pull}80939[#80939] +* Use "histogram:maxBars" and "histogram:barTarget" advanced settings in TSVB {kibana-pull}83628[#83628] +* Fixes Graph saved object references {kibana-pull}85295[#85295] +* Allow sorting by median {kibana-pull}79839[#79839] +Logs:: +* Syncs logs timerange with wider Kibana {kibana-pull}79444[#79444] +* Displays progress for asynchronous loading of the log entry fly-out content and cancels pending requests when closing the fly-out {kibana-pull}83906[#83906] +Machine Learning:: +* Data frame analytics: Scatterplot matrix for outlier detection {kibana-pull}73419[#73419] +* Adds space aware jobs {kibana-pull}77916[#77916] +* Adds probability values in decision path visualization for classification data frame analytics {kibana-pull}80229[#80229] +* DFAnalytics Creation: update form to handle `num_top_classes` setting for all classes {kibana-pull}80751[#80751] +* DF Analytics wizard: ensure user can set mml manually or select to use given estimate {kibana-pull}81078[#81078] +* Adds annotation markers to time series brush area to indicate annotations exist outside of selected range {kibana-pull}81490[#81490] +* Configure sorting for partition values on Single Metric Viewer {kibana-pull}81510[#81510] +* Adds option for anomaly charts for metric detector should plot min, mean or max as appropriate {kibana-pull}81662[#81662] +* Data frame analytics: Adds map view {kibana-pull}81666[#81666] +* Improves support for script and aggregation fields in anomaly detection jobs {kibana-pull}81923[#81923] +* Adds space aware jobs (#77916) {kibana-pull}82446[#82446] +* Job saved objects initialization {kibana-pull}82639[#82639] +* Adds non-space aware checks for existing jobs {kibana-pull}82814[#82814] +* Additional job spaces initialization {kibana-pull}83127[#83127] +* Persisted URL state for the "Anomaly detection jobs" page {kibana-pull}83149[#83149] +* Performance improvements to annotations editing in Single Metric Viewer & buttons placement {kibana-pull}83216[#83216] +* Space management UI {kibana-pull}83320[#83320] +* Persisted URL state for the Data frame analytics jobs and models pages {kibana-pull}83439[#83439] +* Improves browser history navigation {kibana-pull}83792[#83792] +* Persisted URL state for Anomalies table {kibana-pull}84314[#84314] +* Persisted URL state for Data Frame Analytics Exploration page {kibana-pull}84499[#84499] +* Improves messaging and support for datafeed using aggregated and scripted fields {kibana-pull}84594[#84594] +* Adds security_linux and security_windows Modules {kibana-pull}85065[#85065] +* Data Frame Analytics: check space permissions before deleting jobs {kibana-pull}85495[#85495] +* Redesign index-based Data Visualizer {kibana-pull}85726[#85726] +* Adds runtime_mappings to job wizards {kibana-pull}85817[#85817] +Management:: +* Allows custom name for fields via index pattern field management {kibana-pull}70039[#70039] +* In index pattern management - Refresh button removed as index pattern field lists are refreshed when index patterns are loaded, such as on page load or when moving between kibana apps {kibana-pull}82223[#82223] +* Painless Lab in DevTools now supports autocompletion for keywords, and class and class members for the Painless language based on a given context {kibana-pull}80577[#80577] +* Transforms: Remove index field limitation for custom query {kibana-pull}81467[#81467] +* In the Index Management app, you can now click a data stream index lifecycle policy and view it in the Index Lifecycle Policies app {kibana-pull}82165[#82165] +* Use monacco editor in the inspector request panel {kibana-pull}82272[#82272] +* In the Index Management app, you can now click a data stream index template and view it on the Index Templates tab {kibana-pull}82592[#82592] +* In the Index Management app, data streams managed by Fleet can now be identified by a 'Managed' label {kibana-pull}83049[#83049] +* In the Index Management app, buttons to delete a data stream are now controlled by user privileges {kibana-pull}83573[#83573] +* Index Patterns service now has public HTTP API, which third parties can use to manage index patterns, index pattern field metadata, and scripted fields {kibana-pull}83576[#83576] +* The ILM policy UI now supports configuring searchable snapshot in the cold and hot phases {kibana-pull}83783[#83783] +* Adds shrink field to hot phase {kibana-pull}84087[#84087] +* Index and component templates can now be configured with runtime fields in their mappings {kibana-pull}84184[#84184] +* The Ingest Node Pipelines UI now supports autocompletion for the Painless language when defining a condition for a processor, ane when defining a source for a script processor {kibana-pull}84554[#84554] +* In the Index Management app, hidden data streams are now displayed and indicated by a label {kibana-pull}85028[#85028] +* Aligns form fields in ILM with ESUI standards {kibana-pull}85143[#85143] +* Moves error and loading notices for data allocation {kibana-pull}85154[#85154] +* Index Lifecycle Management app now includes readonly action {kibana-pull}85419[#85419] +* Adds support for latest function {kibana-pull}85784[#85784] +* Updates logstash pipeline management to use system index APIs {kibana-pull}80405[#80405] +* Reintroduce "Add support for runtime field types to mappings editor" {kibana-pull}79940[#79940] +* Form UI {kibana-pull}81766[#81766] +Maps:: +* Geo line source {kibana-pull}76572[#76572] +* Supports envelope {kibana-pull}80614[#80614] +* Adds query bar inputs to geo threshold alerts tracked points & boundaries {kibana-pull}80871[#80871] +* Support by value saved objects {kibana-pull}82486[#82486] +* Show icon when layer is filtered by time and allow layers to ignore global time range {kibana-pull}83006[#83006] +* Saved object tagging {kibana-pull}83197[#83197] +* Updates style when metrics change {kibana-pull}83586[#83586] +* Support URL drilldowns {kibana-pull}83732[#83732] +* Background color map setting {kibana-pull}83822[#83822] +* Adds geo containment tracking alert type {kibana-pull}84151[#84151] +* Style by percentiles {kibana-pull}84291[#84291] +* Use index-pattern field display name in UX {kibana-pull}84945[#84945] +* Adds percentile {kibana-pull}85367[#85367] +* Adds on-prem EMS config {kibana-pull}82525[#82525] +Metrics:: +* Adds endpoint for Metrics API {kibana-pull}81693[#81693] +* Adds full custom metric UI to inventory alerts {kibana-pull}81929[#81929] +* Adds basic interaction and shell for node details overlay {kibana-pull}82013[#82013] +* Adds metrics to node details {kibana-pull}83357[#83357] +* Don't show loading screen during auto-reload {kibana-pull}83376[#83376] +* Adds logs to node details {kibana-pull}83433[#83433] +* Adds Process tab to Enhanced Node Details {kibana-pull}83477[#83477] +* Implements Resolved action group in Metrics alerts {kibana-pull}83687[#83687] +* Adds metadata tab to node details flyout {kibana-pull}84454[#84454] +* Fixes double loading of inventory page when there's a default view {kibana-pull}84843[#84843] +* Synch time for metrics ui Kibana time {kibana-pull}85502[#85502] +Monitoring:: +* Thread pool rejections alert {kibana-pull}79433[#79433] +* Improves Collector `fetch` API {kibana-pull}79595[#79595] +* Usage collection add saved objects client to collector fetch context {kibana-pull}80554[#80554] +* Some progress on making alerts better in the UI {kibana-pull}81569[#81569] +* CCR read exceptions alert {kibana-pull}85908[#85908] +Operations:: +* Starting in 8.0, deb and rpm packages will restart on upgrade by default {kibana-pull}82049[#82049] +* Adds a new CLI for generating encryption keys used by Kibana {kibana-pull}82838[#82838] +* Adds deb and rpm packages for ARM64 {kibana-pull}84364[#84364] +* Upgrades the major Node.js version used by and shipped with Kibana from v12 to v14 {kibana-pull}83425[#83425] +* Adds experimental support for configuring CORS policy {kibana-pull}84316[#84316] +Platform:: +* Apply back pressure in Task Manager whenever Elasticsearch responds with a 429 {kibana-pull}75666[#75666] +* Adds basic observability into Task Manager's runtime operations {kibana-pull}77868[#77868] +* Custom labels for ranges {kibana-pull}79628[#79628] +* Adds cumulative sum expression function {kibana-pull}80129[#80129] +* Adds a row click trigger to Lens embeddable for datatable expression renderer {kibana-pull}83167[#83167] +* Adds search request batching using bfetch {kibana-pull}83418[#83418] and {kibana-pull}84043[#84043] +* Normalize values by time unit {kibana-pull}83904[#83904] +* Navigation search now includes deep links into various applications, allowing you to quickly navigate directly to the screens you need most {kibana-pull}83380[#83380] +* Adds tags UI to search results {kibana-pull}85084[#85084] +Querying & Filtering:: +* Use new Search API for rollup search {kibana-pull}83275[#83275] +Security:: +* Adds audit logging events and event filtering{kibana-pull}74640[#74640] +* Allow the default space to be accessed via `/s/default` {kibana-pull}77109[#77109] +* Omit runtime fields from FLS suggestions {kibana-pull}78330[#78330] +* Adds the ability to log in to Kibana anonymously without using any 3rd-party reverse proxy workarounds {kibana-pull}79985[#79985] +* Adds the ability to specify session timeout settings for every provider separately {kibana-pull}82583[#82583] +* Adds cloud links to user menu {kibana-pull}82803[#82803] +* Users are now redirected back to the original URL after they log in again {kibana-pull}84229[#84229] +Uptime:: +* Upgrades the major Node.js version used by and shipped with Kibana from v10 to v12 {kibana-pull}61587[#61587] +* Persist date range between uptime and other apps {kibana-pull}79418[#79418] +* Prompt for confirmation when saving alert with no action {kibana-pull}79892[#79892] +* Applies the active timefilter onto the autocomplete requests to fix performance issues {kibana-pull}81515[#81515] +* Adds description and documentation link in alert flyout {kibana-pull}81526[#81526] +* Put APM links into header action menu {kibana-pull}82292[#82292] +* Displays response headers for a ping {kibana-pull}82332[#82332] +* APM header changes {kibana-pull}82870[#82870] +* Uptime overview overhaul {kibana-pull}83406[#83406] +* Waterfall view {kibana-pull}84821[#84821] +* Display tags in monitor list and details page {kibana-pull}85168[#85168] + +[float] +[[bug-v7.11.0]] +=== Bug fixes +Alerting:: +* Don't change previousStartedAt when alert execution fails {kibana-pull}81388[#81388] +* Enables the EventLog Client to query across ILM versions of the `.event-log` index {kibana-pull}81920[#81920] +* Used SO for saving the API key IDs that should be deleted {kibana-pull}82211[#82211] +* Fixes pagination in connectors list {kibana-pull}83638[#83638] +* Prevents errors in Action and Alert Type UIs from cascading through Alerts Management {kibana-pull}83925[#83925] +* Fixes buggy default message behaviour {kibana-pull}84202[#84202] +* Revert the Revert of "[Alerting] renames Resolved action group to Recovered (#84123)" {kibana-pull}84662[#84662] +* Fixes bug where severity is auto selected but not applied to the action in PagerDuty {kibana-pull}84891[#84891] +* Fixes bug when switching between threshold comparators {kibana-pull}85844[#85844] +* Set refresh: false when partially updating the alert's execution status {kibana-pull}86316[#86316] +* Sort action type filters in alerts list and hide case action type {kibana-pull}86360[#86360] +* Fixes webhook errror messages to be more specific {kibana-pull}87044[#87044] +* Shift polling interval by random amount when Task Manager experiences consistent claim version conflicts {kibana-pull}88020[#88020] +APM:: +* Fixes link to upgrade assistant {kibana-pull}82138[#82138] +* Filtering by "Type" on error overview sometimes causes an error {kibana-pull}82750[#82750] +* Fixes broken link to ML when time range is not set {kibana-pull}85976[#85976] +* Set default for agent icons {kibana-pull}86023[#86023] +* Adds range query to service map trace walk {kibana-pull}86631[#86631] +* Filter out service nodes if there are no metrics {kibana-pull}86639[#86639] +* Truncate long service names in Trace overview {kibana-pull}86759[#86759] +* "View job" link from latency charts leads to a malfunctioning page {kibana-pull}86788[#86788] +* `transactionType` should be required on service-specific endpoints {kibana-pull}86893[#86893] +* Custom links can still be created with a read only user. {kibana-pull}87089[#87089] +* Toggle action and service icon menus {kibana-pull}87220[#87220] +* Blank page when selecting a future time range {kibana-pull}87298[#87298] +* Fixes alert creation items being available for readonly users {kibana-pull}87343[#87343] +* Fixes missing datepicker when service maps has no data {kibana-pull}87393[#87393] +* Explicitly set environment for cross-service links {kibana-pull}87481[#87481] +* Optimize anomaly data loading strategy {kibana-pull}87522[#87522] +* Fixes a bug that would sometimes cause the Kibana process to crash with Error: Failed to run task "apm-telemetry-task" as it is currently running {kibana-pull}87645[#87645] +* Fixes stale custom links list after creating new link {kibana-pull}87932[#87932] +* Fixes alerting expression popovers positions on scroll {kibana-pull}88085[#88085] +* Hide “Create configuration” for users without write access {kibana-pull}88149[#88149] +* Hide `recording` setting from from RUM agents {kibana-pull}88152[#88152] +* Reset time range if either value changes {kibana-pull}88186[#88186] +Dashboard:: +* Fixes cloning panels reactive issue {kibana-pull}74253[#74253] +* Fixes dashboard "snapshot share" is not sharing panel state in view mode {kibana-pull}79837[#79837] +* Deangularize Dashboard {kibana-pull}82909[#82909] +* Fixes Unlink Action via Rollback of ReplacePanel {kibana-pull}83873[#83873] +* Transition Embeddable State Transfer to Session Storage {kibana-pull}85688[#85688] +* Fixes Add From Library Flyout Staying Open {kibana-pull}86698[#86698] +Discover:: +* Fixes double fetching of saved search embeddable {kibana-pull}84060[#84060] +* Fixes navigating back when changing index pattern {kibana-pull}84061[#84061] +Elastic Security Solution:: +For the Elastic Security Solution 7.11.0 release information, refer to {security-guide}/release-notes.html[_Elastic Security Solution Release Notes_]. +Fleet:: +* Fixes duplicate ingest pipeline refs {kibana-pull}82078[#82078] +Lens and visualizations:: +* Do not reset formatting when switching between custom ranges and auto histogram {kibana-pull}82694[#82694] +* Makes incomplete switches possible {kibana-pull}83519[#83519] +* Fixes bug causing bar charts to render bars at the wrong width {kibana-pull}83545[#83545] +* Fixes label input debouncing {kibana-pull}84121[#84121] +* Fixes Treemap outer labels with transparent background {kibana-pull}84245[#84245] +* Line Visualization improper scaling can result in gaps {kibana-pull}80135[#80135] +* Handle correctly {{key}} placeholder on series name {kibana-pull}81748[#81748] +* Fixes "other bucket" for fields containing dashes {kibana-pull}81981[#81981] +* Disable using top_hits in pipeline aggregations {kibana-pull}82278[#82278] +* Fixes Moving Avg help link in Vis Editor {kibana-pull}82423[#82423] +* TSVB doesn't communicate it's index-patterns to dashboard {kibana-pull}82964[#82964] +* Offset option doesn't work properly for some values {kibana-pull}83051[#83051] +* Remove extra column in split mode {kibana-pull}83193[#83193] +* Table tab not working with rollup indexes {kibana-pull}83635[#83635] +* Filter bar in Vega is not usable with non default index pattern. {kibana-pull}84090[#84090] +* TSVB field list performance issue on using annotations {kibana-pull}84407[#84407] +* Gauge visualization can no longer be clicked to filter on values since Kibana 7.10.0 {kibana-pull}84768[#84768] +* Wrong x-axis formatting if "dateFormat" configuration property is not specified {kibana-pull}84899[#84899] +* Date histogram timestamps on daily are getting displayed as epoch times {kibana-pull}85565[#85565] +* Fixes request with disabled aggregation {kibana-pull}85696[#85696] +* Visualize charts flicker on each change {kibana-pull}86888[#86888] +Logs:: +* Fixes selection of suggested field names in the logs stream query bar {kibana-pull}85973[#85973] +* Fixes initial selection of log threshold alert condition field if missing from mapping {kibana-pull}86488[#86488] +Machine Learning:: +* Fixes exclude frequent in advanced wizard (#81121) {kibana-pull}81154[#81154] +* Updating analysis config schema (#82703) {kibana-pull}82714[#82714] +* Data Frame Analytics Classification results view: fix 'Actual' label {kibana-pull}86060[#86060] +* Anomaly Detection: Fix validation error when no data in index. {kibana-pull}86114[#86114] +* DFA results view: ensure results not stuck in loading state when no docs returned from text search {kibana-pull}86178[#86178] +* Fix sort order of data recognizer module cards {kibana-pull}86250[#86250] +* Fixes displaying of setup errors in recognizer wizard {kibana-pull}86430[#86430] +* Fixes alignment of values in data frame analytics results view badges {kibana-pull}86621[#86621] +* Fixes cloning of partition field in per-partition categorization jobs {kibana-pull}86635[#86635] +* Fix Single Metric Viewer y domain extending beyond the visible focus area {kibana-pull}86655[#86655] +* Ensure job group badge fonts are same color {kibana-pull}86674[#86674] +* Anomaly Detection jobs list: fix edit groups popup {kibana-pull}86836[#86836] +Management:: +* Fixes issues in Index Management and ILM when resources have special characters in names {kibana-pull}80835[#80835] +* Fixes ilm navigation {kibana-pull}81664[#81664] +* Fixes a bug in the Watcher UI where the search input cleared after 1 minute of inactivity, causing a user to lose the filtered results {kibana-pull}82651[#82651] +* Fixes a bug in the Index Templates UI where editing an index template with a deprecated type defined and no mapped fields could remove the type on save {kibana-pull}82987[#82987] +* Grokdebugger correctly passes Elasticsearch errors to the Kibana UI {kibana-pull}83036[#83036] +* Fixes an issue in the Snapshot and Restore UI, where editing a Snapshot Lifecycle Management policy may fail if it contains a previous snapshot failure with a large payload content {kibana-pull}83928[#83928] +* Reset to default for empty strings {kibana-pull}85137[#85137] +* Fixes esaggs missing default time field scenario in Lens {kibana-pull}85754[#85754] +* Transforms: Support for missing_bucket in transform advanced pivot editor {kibana-pull}85758[#85758] +* Documentation links in the Index Lifecycle Management UI have been updated {kibana-pull}87216[#87216] +* Fixes a bug causing the index pattern override selection to be cleared when switching page while performing a legacy format saved object import {kibana-pull}81621[#81621] +* Fixes a UI error when attempting to copy a saved object when a user only has Read access to the Default space {kibana-pull}81828[#81828] +* Fixes index pattern recreation when removing experimental packages {kibana-pull}81940[#81940] +* Fixes logstash central pipeline management test {kibana-pull}83281[#83281] +Maps:: +* Fixes feature tooltip remains open when zoom level change hides layer {kibana-pull}81373[#81373] +* Fixes geojson upload diacritic handling {kibana-pull}83122[#83122] +* Always initialize routes on server-startup {kibana-pull}84806[#84806] +* Fixes multi-select query from Controls visualization not always getting applied to map in dashboard {kibana-pull}87310[#87310] +* Fixes zooming while drawing shape filter logs errors in console {kibana-pull}88413[#88413] +Metrics:: +* Refactor Observability Overview for Performance {kibana-pull}84955[#84955] +* Hide drawer on inventory {kibana-pull}85503[#85503] +Monitoring:: +* Iterate over saved object & index patterns pages to collect telemetry results {kibana-pull}73077[#73077] +* Fixes bug in logs UI link {kibana-pull}80943[#80943] +* Uses asCurrentUser in getClusterUuid {kibana-pull}82908[#82908] +* Uses fetchClustersRange {kibana-pull}87882[#87882] +* Change cloud messaging on no data page {kibana-pull}88375[#88375] +Operations:: +* Fixes the logging destination for systemd installations and and updates the sysv filename to be consistent with other stack products {kibana-pull}74896[#74896] +* Create keystore after installation {kibana-pull}76465[#76465] +* Wrap blocked paths in quotes {kibana-pull}83560[#83560] +Platform:: +* Adds loading indicator during debounce time {kibana-pull}80158[#80158] +* Mark task as failed if maxAttempts has been met. {kibana-pull}80681[#80681] +* Reactively disable Task Manager lifecycle when core services become unavailable {kibana-pull}81779[#81779] +* Schedule retry based on schedule on recurring tasks {kibana-pull}83682[#83682] +Querying & Filtering:: +* KQL autocomplete suggestions for field values will now have backslashes properly escaped {kibana-pull}85457[#85457] +Security:: +* Prevent Kerberos and PKI providers from initiating a new session for unauthenticated XHR/API requests {kibana-pull}82817[#82817] +* Fixes incomplete client cert chain when using PKI authentication with the login selector {kibana-pull}88229[#88229] +Uptime:: +* Monitor status alert use url as instance {kibana-pull}81736[#81736] +* Removes Connector flyouts after usage {kibana-pull}82126[#82126] +* User experience display low values {kibana-pull}86026[#86026] +* Simple monitor status alert fix for page duty and other connectors {kibana-pull}87460[#87460] +* Fixes kuery bar dark theme {kibana-pull}87827[#87827] +* Clear ping state when PingList component in unmounted {kibana-pull}88321[#88321] +* UX use replace history instead of push on first load {kibana-pull}88586[#88586] +* Fixes impacted page load errors {kibana-pull}88597[#88597] + +[[release-notes-7.10.2]] +== {kib} 7.10.2 + +For detailed information about the 7.10.2 release, review the following bug fixes. For the breaking changes, refer to the <>. + +[float] +[[security-update-v7.10.2]] +=== Security update +*Vega* visualizations are susceptible to stored and reflected XSS via a vulnerable version of the Vega library. When you create *Vega* visualizations or create a vulnerable URL that describes the visualization, an arbitrary JavaScript can execute in your browser. + +[float] +[[affected-versions-v7.10.2]] +==== Affected versions +Affected versions include 7.10.1 and earlier. + +[float] +[[solution-v7.10.2]] +==== Solution +Verify if you use *Vega* visualizations, then complete the following: + +* If you use *Vega* visualizations, upgrade to 7.10.2. +* If you do not use *Vega* visualizations, open your kibana.yml file, then change `vega.enabled: true` to `vega.enabled: false`. + +[float] +[[bug-v7.10.2]] +=== Bug fixes +Alerting:: +* Don't reset server log level if level is defined {kibana-pull}83651[#83651] +Dashboard:: +* Fixes Duplicated Create New Modal {kibana-pull}86489[#86489] +Logs:: +* Fixes value completion in the logs stream query bar {kibana-pull}85772[#85772] +Machine Learning:: +* Fixes watcher URL to the Anomaly Explorer page {kibana-pull}85123[#85123] +* Fixes Anomaly Explorer data refresh with relative time bounds {kibana-pull}86142[#86142] +* Fixes zoom missing in Anomaly detection URLs {kibana-pull}86182[#86182] and {kibana-pull}86400[#86400] +* Fixes charts grid on the Anomaly Explorer page {kibana-pull}86904[#86904] +Management:: +* When number of replicas is set to zero, it is now correctly displayed in Index Lifecycle Management policies {kibana-pull}85251[#85251] +* The list of data streams in Index Management now sorts numerically by the raw bytes value, which renders them in the correct order {kibana-pull}86204[#86204] +* Fixes a bug where the enterprise level subscription displayed as platinum {kibana-pull}85849[#85849] +* From table actions in the Cross-Cluster Replication app, you can now pause/resume index replication, unfollow leader index, or delete an auto-follow pattern {kibana-pull}84433[#84433] +* Accessibility fix in Rollup Jobs app: when selecting a row in the jobs table, a screen reader pronounces the job's name {kibana-pull}84567[#84567] +Monitoring:: +* Makes alert status fetching more resilient {kibana-pull}84676[#84676] +* Adds unmapped_type to additional queries {kibana-pull}85837[#85837] +Security:: +* Fixes 500 error when using PKI authentication with an incomplete certificate chain {kibana-pull}86700[#86700] + +[[release-notes-7.10.1]] +== {kib} 7.10.1 + +For detailed information about the 7.10.1 release, review the following enhancements and bug fixes. + +For the breaking changes, refer to the <>. + +[float] +[[enhancement-v7.10.1]] +=== Enhancements +Machine Learning:: +* Adds unsigned_long support to data frame analytics and anomaly detection {kibana-pull}82636[#82636] +Platform:: +* Fixes a bug causing searching for saved objects using special characters such as * or - to not return any results {kibana-pull}82693[#82693] + +[float] +[[bug-v7.10.1]] +=== Bug fixes +APM:: +* Fixes missing `service.node.name` {kibana-pull}84269[#84269] +* Page load chart breakdown tooltip formatting {kibana-pull}83627[#83627] +Canvas:: +* Fixes elements not being updated properly when filter is changed on workpad {kibana-pull}81863[#81863] +Dashboard:: +* Fixes an issue when exporting a Saved Search visualization, inside of a dashboard,ß to CSV was returning blank rows {kibana-pull}81524[#81524] +Discover:: +* Fixes double fetching of saved search embeddable {kibana-pull}84060[#84060] +Ingest Management:: +* Fixes error with creating agent policy during add integration {kibana-pull}83993[#83993] +* Disallows dashes in namespace strings {kibana-pull}83996[#83996] +* Adds config options to accepted docker env vars {kibana-pull}84338[#84338] +Lens and visualizations:: +* Reloads on change via history object {kibana-pull}81753[#81753] +* Fixes underlying data drilldown for Lens {kibana-pull}82737[#82737] +* Fixes bug in terms formatting {kibana-pull}82776[#82776] +* Do not reset filter state on incoming app navigation {kibana-pull}83786[#83786] +* Vis listing page breaks on unknown vis type {kibana-pull}82018[#82018] +* Fixes area rendering with negative values {kibana-pull}83313[#83313] +* Vertical cursor is not displayed across visualizations of a dashboard {kibana-pull}83435[#83435] +* Y-axis has number formatting not considering all series formatters in the group {kibana-pull}83438[#83438] +* Fixes tagcloud explicitly pass params {kibana-pull}84107[#84107] +* Fixes timelion not working with single quotes {kibana-pull}84196[#84196] +Machine Learning:: +* Fixes setting of anomaly chart time range depending on bucket spans {kibana-pull}81291[#81291] +* Fixes formatting of fields in index data visualizer {kibana-pull}82593[#82593] +* Fixes anomaly detection validation when using advanced properties in the analysis config {kibana-pull}82703[#82703] +* Fixes Anomaly Explorer population charts when multiple causes in anomaly {kibana-pull}84254[#84254] +* Fixes swim lane for top influencers {kibana-pull}84258[#84258] +* Fixes unnecessary trigger of wildcard field type search for {ml} plugin routes {kibana-pull}84605[#84605] +Management:: +* Fixes a bug causing Kibana to crash when importing a file with an invalid format from the saved object management section {kibana-pull}82406[#82406] +Maps:: +* Fixes threshold alert issue resolving nested fields {kibana-pull}83577[#83577] +Metrics:: +* Adds timerange and sorting to node detail metadata request {kibana-pull}81033[#81033] +* Converts legend key to optional {kibana-pull}83495[#83495] +* Optimizations for Snapshot and Inventory Metadata {kibana-pull}83596[#83596] +Monitoring:: +* Adds catch clause to handle exceptions on loading page {kibana-pull}82179[#82179] +* Fixes the plugins passed into legacy routes {kibana-pull}82192[#82192] +* Fixes small issue with detecting missing monitoring data from APM {kibana-pull}83646[#83646] +* Only looks at ES for the missing data alert for now {kibana-pull}83839[#83839] +* Fixes rison error {kibana-pull}83987[#83987] +* Fixes issues with show_license_expiration {kibana-pull}84361[#84361] +Security:: +* Adjusts encoding for security management pages {kibana-pull}83629[#83629] +* Fixes "Severity override" dropdowns in "Create new rule" -> "About rule" {kibana-pull}82271[#82271] +Sharing:: +* Embeddable Error Handling Without ReplacePanel {kibana-pull}82201[#82201] +Uptime:: +* Page load chart breakdown tooltip formatting {kibana-pull}83627[#83627] + + +[[release-notes-7.10.0]] +== {kib} 7.10.0 + +For detailed information about the 7.10.0 release, review the following sections. + +<> | <> | <> | <> + +[float] +[[enhancement-v7.10.0]] +=== Enhancements +Alerting:: +* Batches the update operations in Task Manager {kibana-pull}71470[#71470] +* Actions add proxy support {kibana-pull}74289[#74289] +* Exempt Alerts pre 7.10 from RBAC on their Action execution until updated {kibana-pull}75563[#75563] +* Improves performance of the authorization filter in AlertsClient.find by skipping KQL parsing {kibana-pull}77040[#77040] +* Adds a Test Connector tab in the Connectors list {kibana-pull}77365[#77365] +* Adds a "Test Connector" button on the Connectors List to make discovery of the Test tab easier {kibana-pull}78746[#78746] +* The high-level search API SearchSource is now available on the server {kibana-pull}78383[#78383] +* Adds Role Based Access-Control to the Alerting & Action plugins based on Kibana Feature Controls {kibana-pull}67157[#67157] +APM:: +* Metrics-powered UI {kibana-pull}73953[#73953] +* Uses platform history {kibana-pull}74328[#74328] +* Immediately returns terms for unbound queries {kibana-pull}74543[#74543] +* Implements nest level expand/collapse toggle for each span row {kibana-pull}75259[#75259] +* Removes additional "No data" message and re-ordering charts {kibana-pull}75399[#75399] +* Uses the outcome field to calculate the transaction error rate chart {kibana-pull}75528[#75528] +* Improves breakdown data gaps {kibana-pull}75534[#75534] +* UI filters: Change transaction type selector from dropdown to radio buttons {kibana-pull}75625[#75625] +* Language-specific stacktrace formatting {kibana-pull}75924[#75924] +* Service maps layout enhancements {kibana-pull}76481[#76481] +* Service inventory redesign {kibana-pull}76744[#76744] +* Shows accurate metrics for containerized applications {kibana-pull}76768[#76768] +* Anomaly detection Settings page: Link directly to ML jobs management to filter for the select environment {kibana-pull}77875[#77875] +* Removes `max` validation for transaction_max_spans {kibana-pull}77987[#77987] +* Service maps grouped external resource nodes {kibana-pull}78136[#78136] +* Alerting: Add global option to create all alert types {kibana-pull}78151[#78151] +* Empty prompt and loading spinner for service map {kibana-pull}78382[#78382] +* Adds default message to alerts. {kibana-pull}78930[#78930] +* Persists time range between APM and other apps {kibana-pull}79090[#79090] +* Sets service map cursors {kibana-pull}80920[#80920] +* Persists time range across apps {kibana-pull}79258[#79258] +Dashboard:: +* Lens By Value With AttributeService {kibana-pull}77561[#77561] +Discover:: +* Uiactions to navigate to visualize or maps {kibana-pull}74121[#74121] +* Supports unsigned_long fields {kibana-pull}81115[#81115] +Ingest Manager:: +* Agent bulk actions UI {kibana-pull}77690[#77690] +* Supports multiple kibana urls {kibana-pull}75712[#75712] +* Adds upgrade action {kibana-pull}77412[#77412] +* User experience metrics {kibana-pull}77384[#77384] +* Uses optional `registryProxyUrl` setting when contacting Registry {kibana-pull}78648[#78648] +* Upgrades Agents in Fleet {kibana-pull}78810[#78810] +* Configures Elasticsearch output with YAML in global output settings {kibana-pull}79019[#79019] +Kibana UI:: +* Elastic home page redesign {kibana-pull}70571[#70571] +* Stacked headers and navigational search {kibana-pull}72331[#72331] +* Kibana Overview Page {kibana-pull}75827[#75827] +* Adds meta data and highlighting to nav search {kibana-pull}77662[#77662] +* Creates new "Add Data" tutorials for several newly added Filebeat modules {kibana-pull}77237[#77237] +Lens and visualizations:: +* Lens is GA {kibana-pull}75574[#75574] +* Lens legend improvements {kibana-pull}70619[#70619] +* Lens added stack as percentage {kibana-pull}70703[#70703] +* Lens adds styling options for x and y axes {kibana-pull}71829[#71829] +* Lens adds filters aggregation {kibana-pull}75635[#75635] +* Lens supports drag to replace {kibana-pull}75895[#75895] +* Lens adds histogram/range aggregation for numbers {kibana-pull}76121[#76121] +* Lens settings panel redesign and separate settings per y axis {kibana-pull}76373[#76373] +* Lens field stats for IP fields and scripted fields {kibana-pull}76457[#76457] +* Adds Lens to Recently Accessed {kibana-pull}77249[#77249] +* Navigate from discover to lens {kibana-pull}77873[#77873] +* Lens shows runtime fields in field list and improve performance {kibana-pull}79167[#79167] +* Drilldowns for TSVB / Vega / Timelion {kibana-pull}74848[#74848] +* TSVB filter ratio now supports KQL {kibana-pull}75033[#75033] +* Vega is now GA {kibana-pull}75157[#75157] +* Uses prefix search in visualize editor's field and aggregation select {kibana-pull}75290[#75290] +* TSVB Markdown now handles the case when a field has key_as_string value. Common case is the value is a date string (e.x. 2020-08-21T20:36:58.000Z) or a boolean stringified value ("true"/"false"). +Such a value will be first converted into a moment object and formatted with dateFormat from Kibana UI settings. If the key_as_string value is not recognized by a known format in Moments.js, +a formatted value from elasticsearch will be returned {kibana-pull}75555[#75555] +* Agg-based histograms now have `auto` interval option {kibana-pull}76001[#76001] +* The search.aggs service in the data plugin is now available on the server. Usage is the same as on the client, except that a scoped saved objects +client must be provided on the server in order to retrieve the start contract {kibana-pull}74472[#74472] +Logs:: +* Log alerts chart previews {kibana-pull}75296[#75296] +* Adds dataset-specific categorization warnings {kibana-pull}75351[#75351] +* Log threshold ratio alerts {kibana-pull}76867[#76867] +* Adds timestamp as a context variable to log threshold alerts {kibana-pull}78932[#78932] +Machine Learning:: +* Adds combined job and datafeed JSON editing {kibana-pull}72117[#72117] +* Dat frame analytics creation wizard: default destination index to job id {kibana-pull}72758[#72758] +* Adds decision path charts to exploration results table {kibana-pull}73561[#73561] +* Data frame analytics creation wizard: ensures user can switch back to form from JSON editor {kibana-pull}73752[#73752] +* Adds datafeed query reset button {kibana-pull}73958[#73958] +* Data frame analytics creation wizard: shows link to results {kibana-pull}74025[#74025] +* Adds initial file analysis overrides {kibana-pull}74376[#74376] +* Add ability to pass a group ID filter to job management page {kibana-pull}74533[#74533] +* Adds memory status to data frame analytics job list {kibana-pull}74570[#74570] +* Switching to new {es} client {kibana-pull}74965[#74965] +* Inference models management {kibana-pull}74978[#74978] +* Adds indicator if there are stopped partitions in categorization job wizard {kibana-pull}75709[#75709] +* Adds Metadata and Discovery Analysis Jobs to Security Integration {kibana-pull}76023[#76023] +* Adds option to Advanced Settings to set default time range filter for anomaly detection jobs {kibana-pull}76347[#76347] +* Adds machine learning modules for Metrics UI Integration {kibana-pull}76460[#76460] +* Collapsable sections on data frame analytics job result pages {kibana-pull}76641[#76641] +* Improves client side error handling {kibana-pull}76743[#76743] +* Adds geo point combined field to CSV import {kibana-pull}77117[#77117] +* Adds option to create anomaly detection jobs without starting the datafeed {kibana-pull}77484[#77484] +* Adds feature importance summary charts {kibana-pull}78238[#78238] +* Default filter of data frame analytics results page by `defaultIsTraining` value in url {kibana-pull}78303[#78303] +* Replaces use of rest_total_hits_as_int with track_total_hits {kibana-pull}78423[#78423] +* Adds runtime fields support {kibana-pull}78700[#78700] +* Adds `ml.is_training` filter to regression/classification views {kibana-pull}78702[#78702] +* Data frame analytics creation wizard: replaces select input with job type cards with icons {kibana-pull}78872[#78872] +* Data frame analytics results view: ensures boolean values in charts shown without formatting {kibana-pull}78888[#78888] +* Only adjust the bounds of Single Metric Viewer if annotations are visible {kibana-pull}79210[#79210] +* Data frame analytics creation wizard: ensures job creation possible when model memory lower than estimate {kibana-pull}79229[#79229] +* Expandable sections for classification and regression {kibana-pull}79414[#79414] + +Management:: +* Empty index patterns page re-design {kibana-pull}68819[#68819] +* Adds inspector for VEGA {kibana-pull}70941[#70941] +* Adds links to "wait for snapshot policy" combobox that navigate to the snapshot policy creation wizard, when there no policies created +yet or the value doesn't match any existing policies {kibana-pull}72473[#72473] +* Adds the possibility to preview the final composite of a composable template. The user will be able to see this preview from the creation or +editing wizard flow, or when looking at the details of a composable template {kibana-pull}72598[#72598] +* Refines the debugging user experience when creating or editing an ingest node pipeline in the existing Ingest Node Pipelines UI. Once a sample +document(s) is provided, the pipeline is executed. The UI highlights the status of each processor, and shows the user how their sample documents change shape at each step in the pipeline {kibana-pull}74964[#74964] +* The Data Streams tab in Index Management now allows users to view additional information for data streams {kibana-pull}75107[#75107] +* Data tiers for 7.10 {kibana-pull}76126[#76126] +* The mappings editor in the Index Templates UI now supports configuring the constant_keyword field type {kibana-pull}76564[#76564] +* The mappings editor in the Index Templates UI now supports configuring the wildcard field type {kibana-pull}76574[#76574] +* The mappings editor in the Index Templates UI now supports configuring the histogram field type. Support for the meta parameter was also added +to the boolean, binary, completion, date, flattened, geo_point, numeric, range, search_as_you_type, token_count and text field types {kibana-pull}76671[#76671] +* Time suffix for duration formatter {kibana-pull}76729[#76729] +* The ingest node pipeline editor now has the ability to move processors into an empty tree {kibana-pull}76885[#76885] +* The ILM UI now allows attaching a lifecycle policy to both a composable index template and a legacy index templatee {kibana-pull}77077[#77077] +* Adds forcemerge action to hot phase with a rollover enabled {kibana-pull}77193[#77193] +* Transforms: Extend editing and creation options {kibana-pull}77370[#77370] +* The mappings editor in the Index Templates UI now supports configuring the point field type {kibana-pull}77543[#77543] +* Adds an option to select a higher compression codec for force merge action in ILM {kibana-pull}78175[#78175] +* The mappings editor in the Index Templates UI now supports configuring the version field type {kibana-pull}78206[#78206] +* Updates transform cloning to include description and new fields {kibana-pull}78364[#78364] +* Optimises keyboard navigation of the ingest processors component {kibana-pull}79122[#79122] +Maps:: +* Auto-fits to data bounds {kibana-pull}72129[#72129] +* Implements save and return from dashboard {kibana-pull}74303[#74303] +* Adds initial location option that fits to data bounds {kibana-pull}74583[#74583] +* Adds drilldown support map embeddable {kibana-pull}75598[#75598] +* Originating App Breadcrumb {kibana-pull}75692[#75692] +* Adds mvt support for ES doc sources {kibana-pull}75698[#75698] +* Adds message to empty add tooltip card {kibana-pull}75809[#75809] +* Introduces geo-threshold alerts {kibana-pull}76285[#76285] +* Removes alias icon for Lens and Maps {kibana-pull}76418[#76418] +* Adds deprecated message to tile_map and region_map visualizations. {kibana-pull}77683[#77683] +* Adds super-fine option to grid/cluster layer {kibana-pull}78201[#78201] +* Enables auto fit to bounds by default {kibana-pull}79296[#79296] +Metrics:: +* Supports percentage format in threshold alerts {kibana-pull}72701[#72701] +* Uses Notify Every in Alert Preview {kibana-pull}74401[#74401] +* Gets custom metrics working in inventory alerts with limited UI {kibana-pull}75073[#75073] +* Anomaly Detection setup flow for Metrics {kibana-pull}76787[#76787] +* Adds inventory view timeline {kibana-pull}77804[#77804] +* Adds anomalies to timeline {kibana-pull}78602[#78602] +* Adds ability to override datafeeds and job config for partition field {kibana-pull}78875[#78875] +* Overrides anomaly detection partition field {kibana-pull}79214[#79214] +Monitoring:: +* Fixes the messaging around needing TLS enabled {kibana-pull}72310[#72310] +* Adds loading page {kibana-pull}75362[#75362] +* Disk usage alerting {kibana-pull}75419[#75419] +* Design/UI improvements {kibana-pull}76946[#76946] +* Alert Telemetry for the Security app {kibana-pull}77200[#77200] +* Adds new elasticsearch client to telemetry plugin {kibana-pull}78046[#78046] +* Missing data alert {kibana-pull}78208[#78208] +* [Telemetry] Display collected security event sample {kibana-pull}78963[#78963] +* JVM memory usage alert {kibana-pull}79039[#79039] +* Navigational search UI metrics {kibana-pull}79238[#79238] +Operations:: +* Kibana no longer needs to optimize plugins for use in the browser when a plugin is installed. This means the --optimize flag is now deprecated and does nothing now. It will be removed in 8.0 {kibana-pull}73154[#73154] +* Docker containers now use CentOS 8.2 as the base image, upgrading from 7. {kibana-pull}74656[#74656] +* Docker images now include CJK fonts built in {kibana-pull}74806[#74806] +Platform:: +* Adds support for reading request ID from X-Opaque-Id header {kibana-pull}71019[#71019] +* Adds Kea.js support to Enterprise Search plugin {kibana-pull}72160[#72160] +* Adds solution-level side navigation {kibana-pull}74705[#74705] +* Adds Workplace Search side navigation {kibana-pull}74894[#74894] +* Adds support for version on create & bulkCreate when overwriting a document {kibana-pull}75172[#75172] +* Monitors the Task Manager Poller and automatically recovers from failure {kibana-pull}75420[#75420] +* Adds a new Enterprise Search overview plugin, which introduces and guides users to the App Search and Workplace Search plugins {kibana-pull}76734[#76734] +* The deprecated Dashboard Import API (POST /api/kibana/dashboards/import) now accepts filesizes up to the savedObjects.maxImportPayloadBytes configuration +which is 10MB by default {kibana-pull}77409[#77409] +Reporting:: +* Reporting configuration settings for time duration values allow "time unit" strings to be specified as well as number of milliseconds. +For byte size values, "byte size" strings are allowed as well as number of bytes. See the Reporting configuration documentation for more details {kibana-pull}74202[#74202] +* Reporting/diagnostics {kibana-pull}74314[#74314] +* Removes the light gray border around the image in PDF reports {kibana-pull}78036[#78036] +* Increases capture.timeouts.openUrl to 1 minute {kibana-pull}75207[#75207] +Security:: +* Hides management sections based on cluster/index privileges {kibana-pull}67791[#67791] +* xpack.encryptedSavedObjects.encryptionKey can now be rotated without losing access to existing encrypted Saved Objects (alerts, actions etc.). +Old key(s) can be moved to xpack.encryptedSavedObjects.keyRotation.decryptionOnlyKeys to be used only to decrypt existing objects while new or updated objects will be encrypted using new primary encryption key. +Administrators can also use dedicated API endpoint /api/encrypted_saved_objects/_rotate_key to trigger re-encryption of all existing objects with a new primary key so that old keys can be safely disposed {kibana-pull}72420[#72420] +* Groups features for space management {kibana-pull}74151[#74151] +* Allows passwords to be visible on security screens {kibana-pull}77394[#77394] +* Groups features for role management {kibana-pull}78152[#78152] +* Warns users when security is not configured {kibana-pull}78545[#78545] +* Sharing saved-objects phase 1.5 {kibana-pull}75444[#75444] +* [Detections] Handle conflicts on alert status update {kibana-pull}75492[#75492] +* Improves the experience when Kibana returns a 403 HTTP status code or the user tries to access a page/app they do not have access to. In those instances, a new user-friendly error page is shown. +The user will get the option to go back to the page from where they came, or log in as a different user. Previously the user would just see a simple JSON document containing a short error message +without the ability to do anything {kibana-pull}75538[#75538] +* Adds EQL search strategy {kibana-pull}78645[#78645] +* Fetches related events from the server {kibana-pull}78780[#78780] +* [Resolver] Requests data from new event api {kibana-pull}78782[#78782] +* Updates copy styling {kibana-pull}79313[#79313] +* Excludes cloud alias index from our query {kibana-pull}81551[#81551] +* Implements server-side sessions. {kib} now stores user session information in a dedicated {es} index. +By default, expired and invalid sessions are cleaned from the index every hour. +You can configure the cleanup interval with the `xpack.security.session.cleanupInterval` setting. +After the upgrade, all existing sessions are invalid and users must log back in to {kib}. +It's also no longer possible +to host different {kib} tenants on different ports of the same host. +Although this setup worked in the past, it was discouraged because browsers +share cookies across all applications hosted using the same host name, ignoring ports. +Cookies are now strictly tied to a particular tenant. {kibana-pull}68117[#68117] +Uptime:: +* Pings Redirects {kibana-pull}65292[#65292] +* Uses `service.name` to link from Uptime -> APM where available {kibana-pull}73618[#73618] +* One click simple monitor down alert {kibana-pull}73835[#73835] +* Singular alert {kibana-pull}74659[#74659] +* Creates new path for client side monitoring {kibana-pull}74740[#74740] +* Adds rum core web vitals {kibana-pull}75685[#75685] +* Visitors by region map {kibana-pull}77135[#77135] +* Url search {kibana-pull}77516[#77516] +* Js errors {kibana-pull}77919[#77919] +* Synthetics UI {kibana-pull}77960[#77960] +* OpenTelemetry icons and data telemetry {kibana-pull}78499[#78499] +* Adds percentile selector {kibana-pull}78562[#78562] +* Adds core web vitals in obsv homepage {kibana-pull}78976[#78976] +* Makes uptime ping histogram bar clickable to improve filtering {kibana-pull}79054[#79054] +* Adds type row to monitor detail page {kibana-pull}79556[#79556] +* Allow add alert Flyout initial values like name, tags {kibana-pull}76906[#76906] + +[float] +[[bug-v7.10.0]] +=== Bug fixes +Alerting:: +* Overwrites SOs when updating instead of partially updating {kibana-pull}73688[#73688] +* Reloads the Alerts List when alerts are deleted {kibana-pull}73715[#73715] +* Fixes alerting_api_integration/security_and_spaces tests failing if actions proxy set on for parallel process running using commands 'scripts/functional_tests_server' and 'scripts/functional_test_runner' {kibana-pull}75232[#75232] +* Adds validation to display an error when creating index action in alert with invalid document. {kibana-pull}75929[#75929] +* Avoids setting a default dedupKey on PagerDuty {kibana-pull}77773[#77773] +* Fixes React warnings in Suspense usage during Alert creation {kibana-pull}77777[#77777] +* Fixes alert add and edit flyout to not close when user clicks outside {kibana-pull}78860[#78860] +* Fixes error in UI in the Edit Flyout for PreConfigured Connectors {kibana-pull}78994[#78994] +* Makes savedObjectId field optional {kibana-pull}79186[#79186] +* Renames "Built-In Alerts" feature to "Stack Alerts" and "Actions" feature to "Actions and Connectors" {kibana-pull}79513[#79513] +* Fixes sorting of Alert Instance in Details page {kibana-pull}80103[#80103] +* Fixes migration issue for case specific actions, by extending email action migrator checks {kibana-pull}81673[#81673] +* Fixes docs in trigger alerting UI {kibana-pull}75363[#75363] +* Populates alert instances view with event log data {kibana-pull}68437[#68437] +* Displays a banner to users when some alerts have failures, added alert statuses column and filters {kibana-pull}79038[#79038] +* Formalizes alert status and add status fields to alert saved object {kibana-pull}75553[#75553] +APM:: +* Uses core.chrome to set window title {kibana-pull}73232[#73232] +* Chart units don't update when toggling the chart legends {kibana-pull}74931[#74931] +* Fixes overlapping transaction names {kibana-pull}76083[#76083] +* Avoids negative offset for error marker on timeline {kibana-pull}76638[#76638] +* Service Map: `Not Defined` option doesn't work properly {kibana-pull}77483[#77483] +* Uses model_plot as a signal for anomaly scores {kibana-pull}77756[#77756] +* Fixes service maps ML link zoom value {kibana-pull}77841[#77841] +* Fixes APM header wrapping {kibana-pull}78845[#78845] +* Catches health status error from ML {kibana-pull}80131[#80131] +* Hides service if only data is from ML {kibana-pull}80145[#80145] +* Fixes link to trace {kibana-pull}80993[#80993] +* Service map handle timeout with messaging {kibana-pull}82083[#82083] +* Scale transaction rate correctly {kibana-pull}82155[#82155] +Dashboard:: +* Sample data link does not work {kibana-pull}75262[#75262] +* Stores Expanded Panel Id in URL {kibana-pull}78684[#78684] +* Fixes embeddable title and description for reporting and dashboard tooltip {kibana-pull}78767[#78767] +* Fixes apps break on unrestorable session state in URL {kibana-pull}74264[#74264] +Discover:: +* Converts legacy sort to be compatible with multi sort {kibana-pull}76986[#76986] +* Context - Fix bug when document id contains a slash {kibana-pull}77435[#77435] +* Makes _source field not clickable {kibana-pull}78698[#78698] +* "View surrounding documents" encodes spaces in filters {kibana-pull}79283[#79283] +* Should not visualize unknown/conflict type fields {kibana-pull}81311[#81311] +Ingest Manager:: +* Fixes removing ingest pipelines from elasticsearch {kibana-pull}75092[#75092] +* Installs previous version of package if update fails {kibana-pull}76694[#76694] +* Agent Policy names are unique {kibana-pull}79201[#79201] +* Index pattern installation uses requested package version {kibana-pull}80079[#80079] +* Removes fields from index pattern during package uninstall {kibana-pull}80082[#80082] +* Allows default packages to be deleted from the default agent policy {kibana-pull}81535[#81535] +Kibana UI:: +* Removes duplicate string in search dropdown {kibana-pull}77429[#77429] +Lens and visualizations:: +* Lens fixes inconsistencies when switching with empty layer {kibana-pull}72809[#72809] +* Lens fixes bug in saving {kibana-pull}74483[#74483] +* Lens fixes table sorting bug {kibana-pull}74902[#74902] +* Lens fixes rollup related bugs {kibana-pull}75314[#75314] +* Lens fixes dimension popover design on mobile {kibana-pull}75866[#75866] +* Shows meta field data in Lens {kibana-pull}77210[#77210] +* Lens fixes unclear UI for bucket aggregation grouping order {kibana-pull}77331[#77331] +* Lens handles missing fields gracefully {kibana-pull}78173[#78173] +* Lens removes Over time suggestions for numeric intervals {kibana-pull}78442[#78442] +* Lens fixes display of multiple un-stacked bar series {kibana-pull}78525[#78525] +* Lens prevents values outside of range for number of top values {kibana-pull}78734[#78734] +* Lens fixes empty callout for empty/meta fields accordion {kibana-pull}79429[#79429] +* Lens fixes debouncing in visualization settings UI {kibana-pull}79625[#79625] +* Lens fixes chart switching for XY charts {kibana-pull}80297[#80297] +* Lens fixes URL query loss on redirect {kibana-pull}81475[#81475] +* TSVB fixes inaccurate Group By {kibana-pull}73683[#73683] +* TSVB ffixes bug on TopN weird behavior with zero values {kibana-pull}74942[#74942] +* TSVB fixes panel updates with back button {kibana-pull}75896[#75896] +* TSVB allows string fields on value count aggregation {kibana-pull}79267[#79267] +* Prevents pageload on TSVB drilldown {kibana-pull}78005[#78005] +* Data table fixes download filename when using split table {kibana-pull}74231[#74231] +* Bar chart fixes rendering of non-stacked bar {kibana-pull}74930[#74930] +* Bar chart fixes overlapping percentiles {kibana-pull}75315[#75315] +* Fix crash in input controls if index pattern is not available {kibana-pull}79431[#79431] +* Vega fixes unexpected change in autosizing behavior post upgrade {kibana-pull}77408[#77408] +* Timelion hides app from search results when the setting is disabled {kibana-pull}77763[#77763] +* In some old TSVB visualization saved objects, queries and filters can be stored. This is not possible anymore for a while and there is no way to edit them besides changing the JSON of the saved object, +but they were still applied to the rendered output. In 7.10, these leftover queries and filters will be removed automatically from the saved object. In almost all cases, no change is necessary. +If a visualization contained these local queries and filters deliberately, they should be converted to panel filters in the "Panel options" of the TSVB interface {kibana-pull}75137[#75137] +Logs:: +* Returns 403s rather than 500s for ML privilege errors {kibana-pull}74506[#74506] +* Correctly filters for log rate anomaly examples with missing dataset {kibana-pull}76775[#76775] +* Fixes logs permissions for alert management {kibana-pull}81199[#81199] +Machine Learning:: +* Updates broken job config callout error {kibana-pull}75481[#75481] +* Replaces all use of date_histogram interval with fixed_interval {kibana-pull}76876[#76876] +* Data frame analytics creation wizard: Fixes field loading race condition {kibana-pull}77326[#77326] +* Improves calendar ics file parsing {kibana-pull}78986[#78986] +* Data frame analytics creation wizard: Resolves clone usability issues {kibana-pull}79048[#79048] +* Fixes jobs so it limit job menu actions for jobs that are closing {kibana-pull}79303[#79303] +* Data frame analytics: Ensures clear error when index pattern missing {kibana-pull}79378[#79378] +* Avoids full page reload for links following CSV import {kibana-pull}79539[#79539] +* Classification results: Ensures confusion matrix doesn't span full width {kibana-pull}79790[#79790] +* Fixes anomaly detection jobs list load if call to load job messages fails {kibana-pull}79792[#79792] +* Sends secondary auth headers to _explain {kibana-pull}79814[#79814] +* Fixes job selection flyout {kibana-pull}79850[#79850] +* Datagrid: Ensures column content with 'boolean' schema is not capitalized {kibana-pull}80041[#80041] +* Fixes Anomaly Explorer charts time range to obey time picker range {kibana-pull}80317[#80317] +* Data frame analytics results: Ensures boolean values in confusion matrix are not capitalized {kibana-pull}80350[#80350] +* Fixes values for decision path not showing correctly for regression due to rounding {kibana-pull}80555[#80555] +* Fixes regression with some links not opening in new tab {kibana-pull}80785[#80785] +* Fixes callout message for total feature importance {kibana-pull}80881[#80881] +* Fixes exclude frequent in advanced wizard {kibana-pull}81121[#81121] + +Management:: +* Fixes the copy of the success notification that displays after creating or saving a watch {kibana-pull}73982[#73982] +* Data frame analytics / Transforms: Fixes job row actions menu invalid DOM nesting warning {kibana-pull}74499[#74499] +* Transforms: Unset doc title when app unmounts {kibana-pull}75539[#75539] +* Fixes a bug in Snapshot and Restore when creating a Snapshot Lifecycle Management policy, where the form could become locked if the user enter an invalid value and navigated to a previous step {kibana-pull}76540[#76540] +* The mappings editor in Index Management now supports configuring the positive_score_impact parameter for the rank_feature field type {kibana-pull}76824[#76824] +* Transforms: Fixes styling of preview grid pagination in summary step {kibana-pull}77789[#77789] +* Fixes a bug in the index template wizard, which resulted in an incorrect validation error when a user toggles between the dynamic templates and advanced settings tabs without providing any values {kibana-pull}78707[#78707] +* Checks for source indexPattern before opening clone wizard {kibana-pull}79383[#79383] +* Fixes an issue when editing the mappings of an index template and selecting the "Other" type {kibana-pull}79434[#79434] +* Transforms/Data frame analytics: Fixes data grid column sorting. {kibana-pull}80618[#80618] +* Transforms: Fixes tab ids for expanded row. {kibana-pull}80666[#80666] +* Fixes package upgrade breaking after first rollover before new data has arrived {kibana-pull}79887[#79887] +Maps:: +* Fixes swap hidden/show icons in layer action panel {kibana-pull}74549[#74549] +* Fixes double fetch when filters are modified {kibana-pull}74893[#74893] +* Fixes read only badge is no longer shown in nav for users with read-only permission {kibana-pull}76091[#76091] +* Fixes Hotlink for EMS-add-data card do not working {kibana-pull}76110[#76110] +* Removes obsolete link {kibana-pull}76419[#76419] +* Exposes map title and description to reporting and embeddable container {kibana-pull}79325[#79325] +* Uses default format when proxying EMS-files {kibana-pull}79760[#79760] +* Fixes refreshing the page causes loss of unsaved change {kibana-pull}81226[#81226] +* Fixes top-level Map page is called 'Kibana' {kibana-pull}81238[#81238] +* Fixes auto-refresh not auto fitting to bounds {kibana-pull}81251[#81251] +* Adds layer type preview icons {kibana-pull}78650[#78650] +* GeoJSON datasets link:https://github.com/elastic/ems-file-service/pull/192[#192] +Metrics:: +* Fixes inventory footer misalignment {kibana-pull}74707[#74707] +* Displays No Data context.values as [NO DATA] {kibana-pull}78038[#78038] +* Fixes a Chrome bug with Inventory View flickering at certain sizes {kibana-pull}81514[#81514] +Monitoring:: +* Ensures setup mode works on cloud but only for alerts {kibana-pull}73127[#73127] +* Fixes cluster link from cluster listing page {kibana-pull}75016[#75016] +* Only show Opt-In banner when user can change settings {kibana-pull}76883[#76883] +* Fixes dead links {kibana-pull}78696[#78696] +* Fixes cluster listing page in how it handles global state {kibana-pull}78979[#78979] +* Ensures alerting is optional {kibana-pull}79168[#79168] +* Adds in cluster version number for sec telemetry sender {kibana-pull}80545[#80545] +* Fixes sorting of alerts {kibana-pull}80546[#80546] +* Fixes a couple of issues with the cpu usage alert {kibana-pull}80737[#80737] +* Fixes alert defaults {kibana-pull}81207[#81207] +* Ensures some data is returned {kibana-pull}81375[#81375] +Platform:: +* Simplifies buffer tests to reduce flakiness {kibana-pull}73024[#73024] +* Handles case where buffer receives multiple entities with the same ID {kibana-pull}74943[#74943] +* Time out work when it overruns in poller {kibana-pull}74980[#74980] +* Fixes a bug that caused some applications to not correctly render when a trailing slash was included at the end of their URLs {kibana-pull}75074[#75074] +* Prevents Task Manager from trying to claim invalid tasks {kibana-pull}76891[#76891] +* Leverages original http request error {kibana-pull}79831[#79831] +* Supports special characters in ES password {kibana-pull}81564[#81564] +Querying & Filtering:: +* Fixes warning text doesn't get displayed on filters with custom filter name {kibana-pull}78617[#78617] +Reporting:: +* Allows any hostname for chromium proxy bypass {kibana-pull}74693[#74693] +* Fixes an issue with CSV Export where a job could fail if clearing the scroll ID failed in Elasticsearch {kibana-pull}76014[#76014] +* Fixes a bug where the downloading CSV from a saved search in a dashboard panel had no file name if the dashboard panels were hidden {kibana-pull}76031[#76031] +* Fixes the reporting exports to use the correct Space for advanced settings {kibana-pull}76998[#76998] +* Fixes a problem in the list of Reports jobs in Management would not refresh with the correct items immediately after deleting a report from the listing {kibana-pull}78516[#78516] +Security:: +* Displays useful error when role creation fails {kibana-pull}77600[#77600] +* Previously when user started SAML or OpenID authentication handshake, but didn't or couldn't finish it they weren't able to access Login Selector easily (e.g. to log in with another +authentication provider) unless they used /login URL directly or manually cleared the session cookies. That was a very confusing user experience. +The reason was that unauthenticated intermediate session that was created to support handshake forced Kibana to automatically restart the same handshake whenever user accessed Kibana. +We fixed that and now in certain cases we ignore unauthenticated intermediate session allowing user to easily access Login Selector whenever they need it {kibana-pull}79300[#79300] +* Kibana can now properly handle values for xpack.security.session.idleTimeout and xpack.security.session.lifespan that are larger than ~24 days {kibana-pull}79858[#79858] +* Properly encodes links to edit user page {kibana-pull}81562[#81562] +* Fixes display of multiple roles in table views {kibana-pull}81603[#81603] +* Node list and node detail tests {kibana-pull}74421[#74421] +* Improves simulator. Add more click-through tests and panel tests. {kibana-pull}74601[#74601] +* [Detections] Refactors signal ancestry to allow multiple parents {kibana-pull}76531[#76531] +* Fixes for the Ticket 78375 {kibana-pull}79004[#79004] +* Resolver Tree Events tests {kibana-pull}79344[#79344] +* Adds the correct class to truncate the names in Endpoint list {kibana-pull}79921[#79921] +* [Detections] Fixes remaining render and validation bug with query preview + tests {kibana-pull}80110[#80110] +* New events resolver {kibana-pull}80850[#80850] +* enable_APM-ci branch fixes {kibana-pull}81658[#81658] +Sharing:: +* Uses App Title for Display Instead of App Id {kibana-pull}75457[#75457] +Spaces:: +* Fixes infinite loading spinner on the spaces selector screen. In the case an error occurs while trying to load the spaces that the current user has access to, an error message will now be shown instead of the loading spinner {kibana-pull}79471[#79471] +Uptime:: +* Ml anomaly alert edit {kibana-pull}76909[#76909] +* Removes custom handling of license enabling {kibana-pull}82019[#82019] + +[float] +[[deprecation-v7.10.0]] +=== Deprecations +Monitoring:: +* "Internal Monitoring" deprecation warning {kibana-pull}72020[#72020] +Platform:: +* The /api/status endpoint response format is now deprecated and will change in 8.0. {kibana-pull}76054[#76054] +* These two config keys have been renamed and the old names will no longer work as of 8.0: cpu.cgroup.path.override => ops.cGroupOverrides.cpuPath and cpuacct.cgroup.path.override => ops.cGroupOverrides.cpuAcctPath {kibana-pull}76730[#76730] +Visualizations:: +* In 7.0 and later, *Timelion* app is deprecated. In 8.0 and later, *Timelion* app is removed from {kib}. {kibana-pull}74660[#74660] ++ +To prepare for the removal of *Timelion* app, you must migrate *Timelion* app worksheets to a dashboard. ++ +NOTE: Only *Timelion* app is deprecated. {kib} continues to support *Timelion* +visualizations in *Dashboard*, *Visualize*, and *Canvas*. ++ +To migrate a *Timelion* worksheet to a dashboard: + +. Open the main menu, click *Dashboard*, then click *Create dashboard*. + +. For each *Timelion* app worksheet, complete the following steps. + +.. On the dashboard, click *Create New*, then click *Timelion* on the *New Visualization* window. + +.. Open a new tab, open the *Timelion* app, select the chart you want to copy, then copy the chart expression. ++ +[role="screenshot"] +image::images/timelion-copy-expression.png[Timelion app chart] + +.. Go to *Timelion*, paste the chart expression in the *Timelion expression* field, then click *Update*. ++ +[role="screenshot"] +image::images/timelion-vis-paste-expression.png[Timelion advanced editor UI] + +.. In the toolbar, click *Save*. + +.. On the *Save visualization* window, enter the visualization *Title*, then click *Save and return*. ++ +The Timelion visualization panel appears on the dashboard. ++ +[role="screenshot"] +image::images/timelion-dashboard.png[Final dashboard with saved Timelion app worksheet] + +[float] +[[breaking-v7.10.0]] +=== Breaking changes +Lens and visualizations:: +* Deprecates schema-less specs in Vega {kibana-pull}73805[#73805] +Operations:: +* The bin/kibana-plugin CLI has been updated to work with the new Kibana Platform plugin format instead of the legacy plugin format {kibana-pull}74604[#74604] +Platform:: +* The legacy plugin system and the legacy plugin API have been removed. It is no longer possible to use third parties legacy Kibana plugins. Legacy plugin owners should migrate their plugins to the Kibana Platform plugin API {kibana-pull}77599[#77599] + +For more information, refer to <>. + +[[release-notes-7.9.3]] +== {kib} 7.9.3 + +For breaking changes, refer to <>. + +[float] +[[enhancement-v7.9.3]] +=== Enhancement +Reporting:: +* Increases openUrl timeout config default to 1min {kibana-pull}78322[#78322] + +[float] +[[bug-v7.9.3]] +=== Bug fixes +Discover:: +* Fixes scripted field error handling for non OSS env {kibana-pull}76476[#76476] +Lens and visualizations:: +* Shows tooltip on external pointer events {kibana-pull}77306[#77306] +Management:: +* Fixes a bug in the index template wizard, which resulted in an error when the user tries to save an existing +template or attempts to view the Elasticsearch request when the template does not have any mappings {kibana-pull}78653[#78653] +* Fixes index pattern creation when using cross cluster search with clusters running <7.9 {kibana-pull}80006[#80006] +Monitoring:: +* Fixes UX around an unavailable remote cluster {kibana-pull}79202[#79202] +* Synchronous `setup` and `start` methods {kibana-pull}79457[#79457] +* Removes license refresh from setup {kibana-pull}79518[#79518] +Platform:: +* Invalid `searchSourceJSON` causes saved object migration to fail {kibana-pull}78535[#78535] +* Changes legacy import 'version' field to optional {kibana-pull}79706[#79706] +Security:: +* Adds `xpack.security.sameSiteCookies` to docker allow list {kibana-pull}78192[#78192] +* Updates user table after user is deleted {kibana-pull}79491[#79491] + +[[release-notes-7.9.2]] +== {kib} 7.9.2 + +See also <>. + +[float] +[[enhancement-v7.9.2]] +=== Enhancement +Machine Learning:: +* Improves performance of job exists check {kibana-pull}77156[#77156] + +[float] +[[bug-v7.9.2]] +=== Bug fixes +Alerting:: +* Fixes alerts unable to create or update when the name has trailing whitepace {kibana-pull}76079[#76079] +Machine Learning:: +* Swim lane pagination for viewing by job ID {kibana-pull}76847[#76847] +* Fixes custom URLs processing for security app {kibana-pull}76957[#76957] +Management:: +* Fixes an issue in Snapshot and Restore UI where creating a policy, repository, or snapshot with a special character, +like a colon, in the name would result in a 404 when viewing details or editing any of the aforementioned {kibana-pull}76278[#76278] +* Indices that contain the characters % { [ @ no longer cause a 405 error in Index Management {kibana-pull}76584[#76584] +* Fixes an issue in the snapshot and restore policy creation form that allowed a policy to be created without an index specified {kibana-pull}76855[#76855] +* The snapshot and restore wizard now notifies users when a policy configured with a non-existing repository is being updated and requires that the user +select a new repository {kibana-pull}76861[#76861] +* Fixes an issue in the grok debugger where simulation error messages are not being displayed {kibana-pull}77499[#77499] +Maps:: +* Fixes drawing shapes in maps app broken in 7.9.1 {kibana-pull}76329[#76329] +Monitoring:: +* Prevents edit/create for Stack Monitoring alerts in Alerts Management {kibana-pull}77097[#77097] +* Fixes improper lodash syntax {kibana-pull}77105[#77105] +* Fixes UI error when alerting is not available {kibana-pull}77179[#77179] +Platform:: +* Fixes bug causing multiple overrides to only show the last confirm modal {kibana-pull}76482[#76482] +* Fixes remoteAddress being duplicated in userAgent field {kibana-pull}76751[#76751] +* Fixes an issue that caused savedObject migration errors to not being displayed in the logs {kibana-pull}77018[#77018] +* Fixes an issue where defaultAppId redirect could fire outside home app {kibana-pull}76415[#76415] +* Suppresses error logs when clients connect over HTTP instead of HTTPS {kibana-pull}77397[#77397] +Reporting:: +* Adds back in custom images for reporting + tests {kibana-pull}76810[#76810] +Security:: +* Adds Lens as a readable saved object for read-only dashboard users {kibana-pull}77067[#77067] +Uptime:: +* Fixes alerting false positives {kibana-pull}75577[#75577] + +[[release-notes-7.9.1]] +== {kib} 7.9.1 + +See also <>. + +[float] +[[bug-v7.9.1]] +=== Bug fixes +APM:: +* Pluralizes for occurrences vs occurrence {kibana-pull}74564[#74564] +* User can't navigate back home using browser nav when clicking link {kibana-pull}75755[#75755] +Dashboard:: +* Loses OriginatingApp Connection on Save After Create new {kibana-pull}74420[#74420] +* Don't Explore data action in dashboard_only mode {kibana-pull}73010[#73010] +Discover:: +* Don't show actions if Discover app is disabled {kibana-pull}73017[#73017] +* Fixes visualize a field through discover app {kibana-pull}73652[#73652] +* Fixes issue with query bar not taking full width in safari when selected {kibana-pull}74987[#74987] +Lens and visualizations:: +* Shows 'No data for this field' for empty field in accordion {kibana-pull}73772[#73772] +* Fixes performance degradation after lodash@4 upgrade {kibana-pull}75850[#75850] +Machine Learning:: +* Fixes file import button on basic license {kibana-pull}75458[#75458] +* Adds date picker back onto index based data visualizer page {kibana-pull}75658[#75658] +* Adds authorization header to data frame analytics job update request {kibana-pull}75899[#75899] +* Removes encoding for scheduled events labels {kibana-pull}75973[#75973] +* Anomaly Explorer / Single Metric Viewer: Fix error reporting for annotations {kibana-pull}74953[#74953] +Management:: +* The watch API considers an index action without a defined index name to be valid, but the Watcher UI +didn't validate accordingly. This resulted in a bug manifested as the UI rejecting attempts to create +Advanced Watches and Threshold Watches with this configuration, and as displaying watches configured +this way via Console with "Config error" states in the watches table. This change fixes the bug so that +the UI accepts watches that are configured with index actions without a defined index name {kibana-pull}74684[#74684] +* Fixes a bug in the index template wizard, which resulted in the UI crashing when the user tries to save an index template without visiting the "Mappings" step first {kibana-pull}75511[#75511] +* Fixes an issue in the mappings editor when trying to clear the "Field type" select dropdown {kibana-pull}76263[#76263] +Maps:: +* Fixes TMS not loaded in legacy maps {kibana-pull}73570[#73570] +* Fixes drawing shapes {kibana-pull}74689[#74689] +* Fixes layer sorting issue with hidden layers at map load {kibana-pull}76007[#76007] +Monitoring:: +* Fixes bug where Kibana crashes with collection disabled {kibana-pull}75335[#75335] +* Swallows errors in opt-in remote notification from the server {kibana-pull}75641[#75641] +Operations:: +* Adds map configurations to docker list {kibana-pull}75035[#75035] +* Fixes bug in keystore read process where it was trying to read the path.data directory instead of the keystore file {kibana-pull}75659[#75659] +Security:: +* Improves login selector UI to display more detailed error messages {kibana-pull}75642[#75642] +Uptime:: +* Fixes alerting false positives {kibana-pull}75577[#75577] + +[[release-notes-7.9.0]] +== {kib} 7.9.0 + +See also <>. + +Operations:: +* Moves kibana-keystore from data/ to config/ {kibana-pull}57856[#57856] + +[float] +[[enhancement-7.9.0]] +=== Enhancements +APM:: +* Shows `trace.id`, `transaction.id` and/or `error.id` in metadata table {kibana-pull}66376[#66376] +* Adds error rate chart to Transaction overview and detail views {kibana-pull}67327[#67327] +* Adds ThemeProvider to support dark mode {kibana-pull}68242[#68242] +* Triggers Lazy-load alert {kibana-pull}68806[#68806] +* Changes to duration formatting {kibana-pull}69039[#69039] +* Adds callout to inform users of high cardinality in unique transaction names {kibana-pull}69112[#69112] +* Creates API to return data to be used on the Overview page {kibana-pull}69137[#69137] +* Fixes confusing request/minute viz {kibana-pull}69143[#69143] +* Adds decimals only for numbers below 10 {kibana-pull}69334[#69334] +* Adds support for dark mode {kibana-pull}69362[#69362] +* Chart breakdowns {kibana-pull}69420[#69420] +* Quotes trace id to ensure a word is searched (#69500) {kibana-pull}69504[#69504] +* Adds error rates to Service Map popovers {kibana-pull}69520[#69520] +* Resubmits initial version {kibana-pull}69531[#69531] +* Adds 'Anomaly detection' settings page to create ML jobs per environment {kibana-pull}70560[#70560] +* Service maps anomaly detection integration by environment {kibana-pull}70932[#70932] +* Anomaly detection setup link with alert if job doesn't exist {kibana-pull}71229[#71229] +* Respects default time range defined in Kibana Advanced Settings {kibana-pull}71464[#71464] +* Uses HDR for percentiles {kibana-pull}64758[#64758] +Canvas:: +* Adds simple variables to workpads {kibana-pull}66139[#66139] +Dashboard:: +* Enables drilldowns for Lens visualizations {kibana-pull}65675[#65675] +* Improves positioning of cloned panels {kibana-pull}67461[#67461] +* Lens editor auto refresh {kibana-pull}65868[#65868] +Discover:: +* Multi-line kql bar {kibana-pull}70140[#70140] +Enterprise Search:: +* Workplace Search in Kibana MVP {kibana-pull}70979[#70979] +Ingest Management:: +* Adds support for datastream to each template {kibana-pull}66367[#66367] +* Improves server-side error handling {kibana-pull}67278[#67278] +* Adds ability to copy an agent config {kibana-pull}68737[#68737] +* Adds enroll agent action to config action menu {kibana-pull}68840[#68840] +* Adds ability to sort to agent configs and package configs {kibana-pull}70676[#70676] +Lens and visualizations:: +* Warns if leaving with unsaved visualization {kibana-pull}67689[#67689] +* Uses accordion menus in field list for available and empty fields {kibana-pull}68871[#68871] +* Adds "no data" popover {kibana-pull}69147[#69147] +* Last used Index pattern is saved to and retrieved from local storage {kibana-pull}69511[#69511] +* Fitting functions {kibana-pull}69820[#69820] +* Multiple y axes {kibana-pull}69911[#69911] +* Adds ability to set colors for y-axis series {kibana-pull}70311[#70311] +* Allows histogram fields in average and sum aggregations {kibana-pull}66891[#66891] +* Changes the error message on TSVB in order to be more user friendly {kibana-pull}67090[#67090] +* Allows the user to change the tooltip mode {kibana-pull}67775[#67775] +* Updates vega version {kibana-pull}68639[#68639] +* Adds support for histogram type {kibana-pull}68837[#68837] +* Enables "Explore underlying data" actions for Lens visualizations {kibana-pull}70047[#70047] +Logs:: +* Validates ML job setup time ranges {kibana-pull}66426[#66426] +* [Alerting] "Group by" functionality {kibana-pull}68250[#68250] +* ML log integration splash screen {kibana-pull}69288[#69288] +* Actions menu in log entry categorization page {kibana-pull}69567[#69567] +* Adds index names for the new indexing strategy {kibana-pull}70245[#70245] +* Adds category anomalies to anomalies page {kibana-pull}70982[#70982] +* Anomalies page dataset filtering {kibana-pull}71110[#71110] +* Shows log analysis ML jobs in a list {kibana-pull}71132[#71132] +Machine Learning:: +* Search should have a categorical option for job type {kibana-pull}65770[#65770] +* Adds linking to dataframe from job management tab {kibana-pull}65778[#65778] +* Adds optional ability to delete target index and index pattern when deleting {dfanalytics-job} {kib-pull}66934[#66934] +* {dfanalytics-cap}: Creation wizard part 1 {kib-pull}67564[#67564] +* Extends population preview chart to show actual and typical value {kibana-pull}67569[#67569] +* Adds minor refresh button to {dfanalytics} and {anomaly-detect} Job Messages tabs {kib-pull}67750[#67750] +* Keeps the edit rule flyout open if there are multiple rules {kibana-pull}68174[#68174] +* Model snapshot management {kibana-pull}68182[#68182] +* {dfanalytics-cap}: Creation wizard part 2 {kib-pull}68462[#68462] +* Removes sub navigation menu from the Anomaly Detection pages {kibana-pull}68663[#68663] +* Adds anomaly swim lane embeddable to the dashboard from the Anomaly Explorer page {kib-pull}68784[#68784] +* Allows editing of model_snapshot_retention_days {kibana-pull}69003[#69003] +* Anomaly Explorer swim lane pagination {kibana-pull}70063[#70063] +* Anomaly Detection: Annotations enhancements {kibana-pull}70198[#70198] +* Updates APM Module to Work with Service Maps {kibana-pull}70361[#70361] +* Changes all calls to ML endpoints to use internal user {kibana-pull}70487[#70487] +* {dfanalytics-cap}: add ability to edit job for fields supported by API {kib-pull}70489[#70489] +* {dfanalytics-cap}: adds prompt for destination index pattern creation {kib-pull}70651[#70651] +* Adds switch to enable model plot annotations independently {kibana-pull}70678[#70678] +* Adds peak_model_bytes to model size stats type {kibana-pull}70825[#70825] +* Anomaly swim lane embeddable navigation and filter actions {kibana-pull}71082[#71082] +* Adds siem_cloudtrail Module {kibana-pull}71323[#71323] +Management:: +* Management apps are now organized into buckets that support common workflow-oriented use-cases: data ingestion, data management, insights and alerting, security, Kibana management, and Stack management {kibana-pull}65796[#65796] +* The ES UI built a new component to assist with building ingest pipelines. Before, when building ingest pipelines, users would have to type and carefully curate JSON describing an ingest pipeline. With this new component a lot of +that burden is removed and improved access to ES processors is provided. This component is the foundation of an improved pipeline building experience {kibana-pull}66021[#66021] +* Transforms: Filter aggregation support {kibana-pull}67591[#67591] +* Adds a "Data Streams" tab to Index Management to help users manage their data streams {kibana-pull}67806[#67806] +* Transforms: Support sub-aggregations {kibana-pull}68306[#68306] +* Data Grid Histograms {kibana-pull}68359[#68359] +* Adds a snapshot policy name field to Delete phase of index lifecycle policy. This option ensures that the snapshot policy is executed before the managed index is deleted {kibana-pull}68505[#68505] +* Transform: Adds ability to create index pattern time field when creating transform {kibana-pull}68842[#68842] +* Transforms - Updated: Add ability to delete dest index & index pattern when deleting transform job {kibana-pull}68896[#68896] +* Transform: Table enhancements {kibana-pull}69307[#69307] +* Transform: Enable force delete if one of the transforms failed {kibana-pull}69472[#69472] +* A new tab called Component Templates is available in Index Management. It provides a way to manage Elasticsearch's component templates. Users can create, edit, clone, and delete a component template {kibana-pull}69732[#69732] +* The index templates tab allows users to manage both their legacy index templates and composable index templates. Users can create, edit, clone, and delete a composable index template {kibana-pull}70220[#70220] +* We updated the snapshot policy name field in Delete phase of index lifecycle policy. This component now display a list of existing snapshot policies and warns the user if their input doesn't match any existing policies {kibana-pull}70627[#70627] +Maps:: +* Displays ranged-data with bands {kibana-pull}60570[#60570] +* Adds styling and tooltip support to mapbox mvt vector tile sources {kibana-pull}64488[#64488] +* Allows adding multiple layers {kibana-pull}67544[#67544] +* Enables gridding/clustering/heatmaps for geo_shape fields {kibana-pull}67886[#67886] +* Security layer wizards {kibana-pull}68290[#68290] +* Surface geo_shape clustering gold feature {kibana-pull}68666[#68666] +* Layer wizard select re-design {kibana-pull}69313[#69313] +* Shows vector tile labels on top {kibana-pull}69444[#69444] +* Choropleth layer wizard {kibana-pull}69699[#69699] +* Increases DEFAULT_MAX_BUCKETS_LIMIT to 65535 {kibana-pull}70313[#70313] +* Shows joins disabled message {kibana-pull}70826[#70826] +* Exposes registerLayerWizard and registerSource in maps plugin start {kibana-pull}71553[#71553] +Metrics:: +* Adds support for multiple groupings to Metrics Explorer (and Alerts) {kibana-pull}66503[#66503] +* Adds sorting for name and value to Inventory View {kibana-pull}66644[#66644] +* Changes Metric Threshold Alert charts to use bar charts {kibana-pull}66672[#66672] +* Allows users to configure Inventory View palettes {kibana-pull}66948[#66948] +* Adds timestamp context variable {kibana-pull}67482[#67482] +* Adds back context variables with descriptions {kibana-pull}67487[#67487] +* Adds overrides to Snapshot API to support alert previews {kibana-pull}68125[#68125] +* Enhances Inventory View Tooltips {kibana-pull}69757[#69757] +* UX improvements for saved views {kibana-pull}69910[#69910] +* Register function for Observability homepage {kibana-pull}70529[#70529] +* Adds framework for recovery messaging to metric threshold alerts (non-functional) {kibana-pull}65339[#65339] +* Adds preview feature for metric threshold alerts {kibana-pull}67684[#67684] +* Adds inventory alert preview {kibana-pull}68909[#68909] +* Prefills alerts from the global dropdown {kibana-pull}68967[#68967] +* Adds context.reason and alertOnNoData to Inventory alerts {kibana-pull}70260[#70260] +Monitoring:: +* Collects number of visualization saved in the past 7, 30 and 90 days {kibana-pull}67865[#67865] +* Out of the box alerting {kibana-pull}68805[#68805] +Operations:: +* Node options from cfg file for production {kibana-pull}62468[#62468] +* Creates Linux aarch64 package {kibana-pull}69165[#69165] +Platform:: +* Switches to core application service {kibana-pull}63443[#63443] +* Adds docLinks to CoreSetup {kibana-pull}66631[#66631] +* New Enterprise Search Kibana plugin {kibana-pull}66922[#66922] +Querying & Filtering:: +* Resolves range date filter bugs and improve usability {kibana-pull}71298[#71298] +Security:: +* Allow saved objects to be searched across multiple spaces {kibana-pull}67644[#67644] +Uptime:: +* Uses ML Capabilities API to determine license type {kibana-pull}66921[#66921] +* Landing page for Observability {kibana-pull}67467[#67467] +* Monitor availability reporting {kibana-pull}67790[#67790] +* Creates "Add data" links in all Observability app headers {kibana-pull}69016[#69016] +* Observability overview page {kibana-pull}69141[#69141] +* Availability alert {kibana-pull}70284[#70284] +* Duration Anomaly Alert {kibana-pull}71208[#71208] + +[float] +[[bug-v7.9.0]] +=== Bug fixes +Alerting:: +* Adds lazy loading of alerting UI components {kibana-pull}65060[#65060] +* Fixes Connectors edit flyout retains state after being closed {kibana-pull}71911[#71911] +* Fixes Webhook connector doesn't retain added HTTP header settings {kibana-pull}71924[#71924] +APM:: +* Removes Missing permission page {kibana-pull}72030[#72030] +* Fixes linking errors to ML and Discover {kibana-pull}73758[#73758] +* Observability i18n fixes {kibana-pull}72984[#72984] +Canvas:: +* Fixes falsey/null value bug for dropdown choices {kibana-pull}69290[#69290] +Dashboard:: +* Shows drilldown context menu over chart tooltip {kibana-pull}67311[#67311] +* Loses OriginatingApp Connection on Save As {kibana-pull}72725[#72725] +* Sometimes when creating filters on a dashboard suggestions from default index patterns were shown by mistake {kibana-pull}72899[#72899] +* Handles listing errors gracefully {kibana-pull}66986[#66986] +* {kib} now sets the keep_alive parameter to 1m in _async_search requests to Elasticsearch to ensure that search requests are cancelled +if a user closes the browser or navigates outside of Kibana before a request completes {kibana-pull}73712[#73712] +Design:: +* Multiple chart actions context menu positioning fixes {kibana-pull}70705[#70705] +* Fixes accessibility issue in Uptime app nav links {kibana-pull}72926[#72926] +Discover:: +* Prevents whitespace wrapping of doc table header {kibana-pull}52861[#52861] +* Removes column from sorting array when removed from table {kibana-pull}65990[#65990] +* Validates timerange before submitting query to ES {kibana-pull}69363[#69363] +* Adds error and warning statuses to FilterBar filters {kibana-pull}66979[#66979] +* Forbids timezones not working in Elasticsearch {kibana-pull}70780[#70780] +Ingest Management:: +* Fixes clear filters on agents table not working {kibana-pull}71978[#71978] +Kibana UI:: +* New Kibana app link order {kibana-pull}66320[#66320] +* Fixes special clicks and 3rd party icon sizes in nav {kibana-pull}69767[#69767] +Lens and visualizations:: +* Keeps global filters, time range and refresh interval on refresh {kibana-pull}68075[#68075] +* Adds description property and check duplicate title on save {kibana-pull}68219[#68219] +* Keeps custom labels {kibana-pull}68498[#68498] +* Fixes delete button position in dimension panel for long labels {kibana-pull}69495[#69495] +* Fixes cross cluster bug and optimize existence query {kibana-pull}70132[#70132] +* Do not crash data panel on invalid KQL query {kibana-pull}70712[#70712] +* Handles failing existence check {kibana-pull}70718[#70718] +* Fixes overflow in printable report {kibana-pull}70723[#70723] +* Fixes switching with layers {kibana-pull}71982[#71982] +* Pins filters not applied when coming from different app {kibana-pull}73825[#73825] +* Fixes missing percentage column and wrong headers on export formatted csv {kibana-pull}66883[#66883] +* TSVB: handle division by zero in math agg {kibana-pull}67111[#67111] +* Fixes vega specification parsing {kibana-pull}67963[#67963] +* VEGA is missing scroll bars {kibana-pull}68766[#68766] +* Replaces the Custom Color Picker on TSVB with the EuiColorPicker {kibana-pull}68888[#68888] +* Fixes spec color highlighting not working on vega vis {kibana-pull}68995[#68995] +* Fixes Advanced Settings Panel number editing in Graph {kibana-pull}69672[#69672] +* Hide only duplicated consecutive ticks {kibana-pull}70981[#70981] +* Fixes TSVB table trend slope value {kibana-pull}71087[#71087] +* Fixes export table for table export links {kibana-pull}71249[#71249] +* Removes opacity from vislib bars {kibana-pull}71421[#71421] +* Fixes float percentiles line chart {kibana-pull}71902[#71902] +Logs:: +* Fixes display of dataset values in anomaly and category example rows {kibana-pull}71693[#71693] +* Handles modifier keys {kibana-pull}74237[#74237] +* Removes UUID from Alert Instances {kibana-pull}71340[#71340] + +Machine Learning:: +* Data frame analytics results: Do not hide query bar and table on query syntax error {kibana-pull}69196[#69196] +* Fixes anomaly chart and validation for one week bucket span {kibana-pull}69671[#69671] +* Anomaly Detection: Ensure 'Category examples' tab in the expanded table row can be seen {kibana-pull}70241[#70241] +* Fixes error toasts shown when starting or editing jobs {kibana-pull}71618[#71618] +* Fixes new job with must_not saved search {kibana-pull}71831[#71831] +* Fixes management section access denied {kibana-pull}71841[#71841] +* Ensure `monitor` cluster privilege not required to create data frame analytics job {kibana-pull}71934[#71934] +* Fixes job list crashing due to undefined processed records {kibana-pull}71966[#71966] +* Fixes datafeed start time is incorrect when the job has trailing empty buckets {kibana-pull}71976[#71976] +* Fixes HTML named characters encoding {kibana-pull}72060[#72060] +* Fixes annotations pagination & change labels from letters to numbers {kibana-pull}72204[#72204] +* Stops annotation flyout re-rendering on each keystroke {kibana-pull}72299[#72299] +* Fixes display of regression stop stats if one is NaN {kibana-pull}72412[#72412] +* Handling data recognizer saved object errors {kibana-pull}72447[#72447] +* Data frame analytics results: add index-pattern management link to 'click here' error prompt {kibana-pull}72470[#72470] +* Fixes layout of anomaly chart tooltip for long field values {kibana-pull}72689[#72689] +* Fixes link to index management from file data visualizer {kibana-pull}72863[#72863] +* Fixes deleting data frame analytics not showing index pattern check {kibana-pull}72904[#72904] +* Fixes recognizer wizard create job button {kibana-pull}73025[#73025] +* Fixes unnecessary deleting job polling {kibana-pull}73087[#73087] +* Disables machine learning if license feature is disabled {kibana-pull}73187[#73187] +* Data frame analytics results: ensure `View` link is only enabled when job has successfully completed {kibana-pull}73539[#73539] + +Management:: +* Inspect action shows on dashboard for every chart {kibana-pull}65998[#65998] +* Fixes an issue in Watcher, where a watch status or action status was incorrectly marked as "Error" {kibana-pull}67952[#67952] +* Error handling {kibana-pull}68809[#68809] +* Fixes an issue in Dev Tools Console where the example shown in the "Help" panel was formatted incorrectly {kibana-pull}71188[#71188] +* Fixes the alignment of the Timing field for Warm, Cold and Delete phases on the Index Lifecycle Policy edit page {kibana-pull}71273[#71273] +* Adopts data stream API changes {kibana-pull}71682[#71682] +* Fixes #66185 {kibana-pull}66186[#66186] +Maps:: +* Do not check count for blended layers when layer is not visible {kibana-pull}66460[#66460] +* Fixes mapbox glyphs error when EMS access is turned off {kibana-pull}67427[#67427] +* Fixes fit to bounds requests not getting canceled {kibana-pull}67629[#67629] +* Fixes cannot select Solid fill-color when removing fields {kibana-pull}70621[#70621] +* Fixes zoom in/zoom out buttons are not visible in dark mode {kibana-pull}72699[#72699] +* Fixes removing global filter from layer can cause app to start thrashing {kibana-pull}72763[#72763] +* Fixes cloned clustered documents layer returns error {kibana-pull}72975[#72975] +* Fixes data driven style properties not working when cloned layer contains joins {kibana-pull}73124[#73124] +* Fixes tile layer attibution text and attribution link validation errors {kibana-pull}73160[#73160] +* Fixes fit to data for Point to Point layer {kibana-pull}73563[#73563] +* Fixes #fit to bounds for ES document layers with joins {kibana-pull}73985[#73985] +* Removes no longer required div wrapper around ValidatedDualRange {kibana-pull}70188[#70188] +* Adds full precision GeoJSON version for TopoJSON only datastes link:[191] +Metrics:: +* Fixes asynchronicity and error handling in Snapshot API {kibana-pull}70503[#70503] +* Fixes evaluating rate-aggregated alerts when there's no normalized value {kibana-pull}73545[#73545] +* Removes UUID from Alert Instance IDs {kibana-pull}71335[#71335] +* Fixes a bug in Metric Threshold query filter construction {kibana-pull}70672[#70672] +* Displays Too Many Buckets error when previewing Inventory Alerts {kibana-pull}70508[#70508] +* Round metric threshold time buckets to nearest unit {kibana-pull}71172[#71172] +Monitoring:: +* Adds a case for Alerting if security/ssl is disabled {kibana-pull}71846[#71846] +* Checks for security feature first when entering setup mode {kibana-pull}73821[#73821] +Operations:: +* Manages pid folder {kibana-pull}68262[#68262] +Platform:: +* Sets wrap to the errorLink so it doesn't go outside of box {kibana-pull}67797[#67797] +* Fixes plugin lifecycle log to only include server plugins {kibana-pull}68686[#68686] +Querying & Filtering:: +* When using KQL or the filter bar, if a request is issued to Elasticsearch for suggestions for a value for a specific field, the request +will be cancelled when navigating away as well as when the input is updated (and a new request is issued {kibana-pull}69769[#69769] +Reporting:: +* Fixes a bug where the Kibana server could crash if the Reporting server-side headless browser crashes {kibana-pull}71989[#71989] +Sharing:: +* Adds panel flyout opens 2 flyouts {kibana-pull}65861[#65861] +Uptime:: +* Adds lazy loading to AlertType and Flyout components {kibana-pull}65678[#65678] +* Fixes metric query broken because of missing mapping {kibana-pull}68999[#68999] +* Fixes charts dark theme {kibana-pull}69748[#69748] +* Uses manual intervals for ping histogram {kibana-pull}72928[#72928] + +[float] +[[deprecation-v7.9.0]] +=== Deprecations +APM:: +* Removes watcher integration {kibana-pull}71655[#71655] +Platform:: +* Deprecates kibana.defaultAppId setting {kibana-pull}67635[#67635] + +[[release-notes-7.8.1]] +== {kib} 7.8.1 + +See also <>. + +[float] +[[security-update-7.8.1]] +=== Security updates +* In {kib} 7.8.1 and earlier, there is a denial of service (DoS) flaw in Timelion. Attackers can construct a URL that when viewed +by a {kib} user, the {kib} process consumes large amounts of CPU and becomes unresponsive, +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-7016[CVE-2020-7016]. ++ +You must upgrade to 7.8.1. If you are unable to upgrade, set `timelion.enabled` to `false` in your kibana.yml file to disable Timelion. + +* In all {kib} versions, region map visualizations contain a stored XSS flaw. Attackers that can edit or create region map visualizations can obtain sensitive information +or perform destructive actions on behalf of {kib} users who view the region map visualization, +https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-7017[CVE-2020-7017]. ++ +You must upgrade to 7.8.1. If you are unable to upgrade, set `xpack.maps.enabled`, `region_map.enabled`, and `tile_map.enabled` to `false` in kibana.yml to disable map visualizations. + +[float] +[[bug-v7.8.1]] +=== Bug fixes +Alerting:: +* Disables multiple select for preconfigured connectors to avoid requesting bulk delete on them {pull}69459[#69459] +* Fixes adding an extra space character on selecting alert variable in action text fields {pull}70028[#70028] +APM:: +* Fixes service maps not loading when there are no APM ML jobs {pull}69240[#69240] +* Fixes service maps load failure when user doesn't have ML permissions {pull}70138[#70138] +Discover:: +* Sorts filter fields by items that start with typed characters {pull}68585[#68585] +* Adds error and warning statuses to FilterBar filters, according to the following scenarios {pull}66979[#66979] +Lens and visualizations:: +* Fixes Date Histogram error when index does not have a time field {pull}69934[#69934] +Logs:: +* Avoids CCS-incompatible index name resolution {pull}70179[#70179] +Machine Learning:: +* Fixes expanded row bug when job has no datafeed {pull}68074[#68074] +* Fixes forever loading indicators in expanded data frame analytics list {pull}69422[#69422] +Management:: +* Updates the "Learn about timing" documentation link when creating a policy in Index Lifecycle Management {pull}68923[#68923] +* Adds AggConfig.toSerializedFieldFormat {pull}69114[#69114] +* Fixes a bug in Cross-Cluster Replication where the "Status" column in the follower indices table did not update after pausing or resuming a follower index {pull}69228[#69228] +* Fixes a bug in Index Lifecycle Management where it was not possible to clear the index priority value when saving a policy {pull}70154[#70154] +* Fixes a bug in Cross-Cluster Replication where the user was prompted with an error message when attempting to use the UI with missing cluster privileges. The user should now be prompted +with a message indicating what privileges are missing {pull}70158[#70158] +* Ignores url.url fields above 2048 characters {pull}69863[#69863] +Maps:: +* Fixes mb-style interpolate style rule {pull}68413[#68413] +* Fixes unable to edit heatmap metric {pull}70606[#70606] +Metrics:: +* Fixes fatal error when no data is available for Metric Threshold Alerts {pull}68678[#68678] +* Fixes EuiTheme type issue {pull}69735[#69735] +Monitoring:: +* Addresses a few longstanding issues with APM Stack Monitoring {pull}69052[#69052] +* Makes sure we fetch all collection status {pull}67172[#67172] +* Adds Cloud as an optional dependency {pull}69050[#69050] +* Fixes links missing a hash {pull}69861[#69861] +Operations:: +* Adds spaces settings {pull}69019[#69019] +Platform:: +* Don't allow empty string for server.basePath config {pull}69377[#69377] +Reporting:: +* Don't set a min-length on encryption key for reporting {pull}69827[#69827] +SIEM:: +* Eliminates Superfluous Untitled Timelines {pull}65783[#65783] +* Fixes 7.8 upgrade issue within rules where you can get the error "params invalid: [lists]: definition for this key is missing" {pull}69434[#69434] +* Excludes glob-only (*) Index Pattern from map layers {pull}69736[#69736] + +[[release-notes-7.8.0]] +== {kib} 7.8.0 + +[float] +[[breaking-changes-7.8.0]] +=== Breaking changes + +See also <>. + +Dashboard:: +* Fixes back button by removing panels from url in dashboard in view mode {kib-pull}62415[#62415] +Metrics:: +* Refactors action messaging to report on No Data state {kib-pull}64365[#64365] + +[float] +[[known-issues-7.8.0]] +=== Known issue + +SIEM:: +* When you duplicate a rule with a deleted action connector, the duplication fails {kib-issue}69142[#69142] + +[float] +[[enhancement-7.8.0]] +=== Enhancements +Alerting:: +* Adds query support to the Event Log {kib-pull}62015[#62015] +* Removes edit alert button from alerts list {kib-pull}64643[#64643] +* Implements actions server API for supporting preconfigured connectors {kib-pull}62382[#62382] +* Adds UI for pre-configured connectors. {kib-pull}63074[#63074] +APM:: +* Adda new Service map external icons {kib-pull}63844[#63844] +* Improves the selected node style {kib-pull}64279[#64279] +* Adds tooltip explaining Group ID {kib-pull}60425[#60425] +* Uses navigateToApp for infra/metrics/uptime links {kib-pull}65712[#65712] +* Observability real user monitoring solution layer {kib-pull}64949[#64949] +* Spans reparenting to support inferred spans {kib-pull}63695[#63695] +* Marks an Agent configuration as applied without etag attribute {kib-pull}63967[#63967] +* Agent remote config validation for Java agent configs {kib-pull}63956[#63956] +* Annotations API {kib-pull}64796[#64796] +* Adds Error Exception Type Column {kib-pull}59596[#59596] +* Service map anomaly indicators {kib-pull}64718[#64718] +Canvas:: +* Adds Top Menu {kib-pull}59982[#59982] +* Adds refresh and autoplay options to view menu {kib-pull}64375[#64375] +* Adds edit menu {kib-pull}64738[#64738] +* Reduces report generation time by re-using headless browser page in background {kib-pull}63301[#63301] +Dashboard:: +* Adds duplicate panel feature {kib-pull}61367[#61367] +* Return to dashboard after editing embeddable {kib-pull}62865[#62865] +Lens and visualizations:: +* Triggers a filter action on click in datatable visualization {kib-pull}63840[#63840] +* Enables include/exclude in Terms agg for numeric fields {kib-pull}59425[#59425] +* Allows user to drag and select a subset of the timeline in the chart (aka brush interaction) {kib-pull}62636[#62636] +* Uses default {kib} palette for split series {kib-pull}62241[#62241] +* Removes duplicate refresh button from vis editor menu {kib-pull}63633[#63633] +* Binds all time fields to the time picker {kib-pull}63874[#63874] +* Uses Top 5 instead of Top 3 for first suggestion {kib-pull}64726[#64726] +* Adds pie and treemap charts {kib-pull}55477[#55477] +Machine Learning:: +* Wizards with dynamic model memory estimation {kib-pull}60888[#60888] +* Shows better file structure finder explanations {kib-pull}62316[#62316] +* Adds configurable file size to file data visualizer {kib-pull}62752[#62752], {kib-pull}63502[#63502], {kib-pull}64427[#64427] +* Lists global calendars on the job management page {kib-pull}63124[#63124] +* Improves parsing of large uploaded files {kib-pull}62970[#62970] +* Enables mml estimation in data recognizer module setup {kib-pull}64900[#64900] +* Updates memory estimate after adding exclude fields {kib-pull}62850[#62850] +* Replaces table with data grid {kib-pull}63650[#63650] and {kib-pull}63757[#63757] +* Fixes feature importance {kib-pull}61761[#61761] +* Adds embeddable anomaly swimlane {kib-pull}65180[#65180] +* Improves progress reporting for analytics jobs {kib-pull}65305[#65305] +Management:: +* Adds Ingest Node Pipelines UI {kib-pull}62321[#62321] +* Adds Transforms single column wizard {kib-pull}64436[#64436] +* Edits transform flyout {kib-pull}65033[#65033] +* Adds docs_per_second to transform edit form {kib-pull}65365[#65365] +Maps:: +* Separates layer wizards for Clusters and heatmap {kib-pull}60870[#60870] +* Allows updating requestType for ESGeoGridSource {kib-pull}62365[#62365] +* Adds date-fields to metrics selection {kib-pull}62629[#62629] +* Shows create filter button for top-term tooltip property {kib-pull}62461[#62461] +* Turns on blended layer for geojson upload {kib-pull}63200[#63200] +* Updates geospatial filters to use geo_shape query for geo_point fields {kib-pull}62966[#62966] +* Min and max zoom map settings {kib-pull}63714[#63714] +* Shows spatial filters on map to provide context when for active filters {kib-pull}63406[#63406] +* Fits geo_shape to bounds {kib-pull}64303[#64303] +* Disables edit layer button when flyout is open for add layer or map settings {kib-pull}64230[#64230] +* Do not display EMS or {kib} layer wizards when not configured {kib-pull}64554[#64554] +* Initial location map settings {kib-pull}64336[#64336] +* Adds categorical palettes with 20 and 30 categories {kib-pull}64701[#64701] +* Adds oil rig icon from @elastic/maki {kib-pull}64364[#64364] +* Highlights selected layer in TOC {kib-pull}61510[#61510] +* Adds global fit to data {kib-pull}64702[#64702] +Metrics:: +* View log in context modal {kib-pull}62198[#62198] +* Refreshes the design for Inventory View, Episode 1 {kib-pull}64026[#64026] +* Adds Charts to Alert Conditions {kib-pull}64384[#64384] +* Adds 99th and 95th percentiles to Metric Explorer {kib-pull}64699[#64699] +* Adds category data quality warning based on ML job stats {kib-pull}60551[#60551] +* Adds dataset filter to ML module setup screen {kib-pull}64470[#64470] +* Alerting {kib-pull}62806[#62806] +* Enhances Alerts management page {kib-pull}64654[#64654] +* Adds inventory metric threshold alerts {kib-pull}64292[#64292] +* Adds outside range comparator {kib-pull}63993[#63993] +Platform:: +* Uses brotli compression for some KP assets {kib-pull}64367[#64367] +Reporting:: +* Adds a new config flag to encode with BOM for our CSVs {kib-pull}63006[#63006] +* Adds config flag to escape formula CSV values {kib-pull}63645[#63645] +Security:: +* Every provider can now be configured with the access agreement message (markdown syntax) that will be presented to the +users after login. Users won't be able to use Kibana until they acknowledge this agreement {kib-pull}63563[#63563] +* Login Selector UI was refined and can now offer much more customization options {kib-pull}64142[#64142] +SIEM:: +* Enhances threat hunting for Filter for/out value, Show top field, Copy to Clipboard, Draggable chart legends {kib-pull}61207[#61207] +* Adds drag between ANDs in timeline queries / add to timeline {kib-pull}65228[#65228] +* Creates template timeline {kib-pull}63136[#63136] +* Adds lists feature flag and list values to the REST interfaces {kib-pull}60171[#60171] +* Adds an error aggregator by error reason and a way to filter them {kib-pull}63513[#63513] +* Adds large list support using REST endpoints {kib-pull}62552[#62552] +* Server cutover to New Platform {kib-pull}63430[#63430] +* Updates list values in REST interfaces {kib-pull}62320[#62320] +* Updates KQL/Lucene search to include lists exceptions {kib-pull}63264[#63264] +* Updates rule.lists to be rule.exceptions_list {kib-pull}63717[#63717] +* Moves All Rules tabs to match other tabs UI {kib-pull}63920[#63920] +* Minor updates to monitoring table with unit tests {kib-pull}64020[#64020] +* Moves jira to a gold license {kib-pull}67178[#67178] +Uptime:: +* Adds cert API request and runtime type checking {kib-pull}63062[#63062] +* Updates TLS settings {kib-pull}64111[#64111] +* TLS alerting {kib-pull}63913[#63913] +* Adds new nav {kib-pull}64018[#64018] +* Certificate expiration threshold settings {kib-pull}63682[#63682] +* Certificates page {kib-pull}64059[#64059] +* Filters in create alert flyout {kib-pull}64753[#64753] +* Moves status filter to monitor list {kib-pull}65049[#65049] + +[float] +[[bug-7.8.0]] +=== Bug fixes +Alerting:: +* TaskManager tasks scheduled without attempting to run {kib-pull}62078[#62078] +* Only fetching TaskManager's available tasks once per call to fillPool {kib-pull}61991[#61991] +* Restores migrations of old tasks in TM {kib-pull}65978[#65978] +* Fixes pre-configured docs link points to the wrong page and functional tests configs {kib-pull}68606[#68606] +APM:: +* Custom links section inside the Actions menu is showing outside of the menu {kib-pull}65428[#65428] +* Removes link from active page in the breadcrumb {kib-pull}65473[#65473] +* Agent configuration: Bug makes it possible to create invalid configurations {kib-pull}65508[#65508] +* Scope APM alert creation to environment {kib-pull}65681[#65681] +* Cannot click through to details of an error on the waterfall page if the error is missing `transaction.id` {kib-pull}66386[#66386] +* Removes service maps badge row and num instances in popover {kib-pull}65492[#65492] +* Handle ML integration when ML is disabled {kib-pull}66158[#66158] +* Fixes 'Enable watcher error reports' 400 error {kib-pull}68465[#68465] +* Updates apm index pattern {kib-pull}65424[#65424] +* Ensures that `/api/apm/security/indices_privileges` doesn't fail when security is disabled {kib-pull}64627[#64627] +* Fixes query bar Japanese translation {kib-pull}68037[#68037] +* Service map fix focused node edges on unselect {kib-pull}63655[#63655] +* Fixes duplicate index patterns {kib-pull}64883[#64883] +Canvas:: +* Bug/pagination enabled empty workpad {kib-pull}62050[#62050] +Dashboard:: +* Improves dashboard loading error handling {kib-pull}66372[#66372] +Design:: +* Adds max-height to recently viewed links {kib-pull}66297[#66297] +Discover:: +* match_all query disappears when typed into Lucene query bar {kib-pull}62194[#62194] +* KQL removes leading zero and breaks query {kib-pull}62748[#62748] +* Shows doc viewer action buttons on focus {kib-pull}64912[#64912] +* Fixes renaming of saved search not displayed in breadcrumb {kib-pull}67577[#67577] +* Replaces EuiTooltip by native title for better performance {kib-pull}68280[#68280] +* Clicking cancel in saved query save modal doesn't close it {kib-pull}62774[#62774] +Graph:: +* Changes the copy from blacklist to blocklist {kib-pull}65419[#65419] +Kibana UI:: +* Updates home link click handler {kib-pull}68132[#68132] +* Updates Canvas location in nav {kib-pull}65519[#65519] +* Fixes Recently Viewed links allowing them to close the nav when clicked {kib-pull}66280[#66280] +Lens and visualizations:: +* Fixes redirect after reload {kib-pull}66328[#66328] +* Auto interval on date histogram is getting displayed as timestamp per… {kib-pull}59171[#59171] +* Fixes visualize and lens telemetry {kib-pull}67749[#67749] +* Removes redundant formatting of percentage column {kib-pull}64948[#64948] +* Uses correct text color in metric vis on dark background {kib-pull}67481[#67481] +* Fixes the problem on adding color rules {kib-pull}67763[#67763] +* Fixes bug where suggestions didn't use filters {kib-pull}63293[#63293] +* Only show copy on save for previously saved docs {kib-pull}63535[#63535] +* Fixes escaping of field names {kib-pull}63509[#63509] +* Makes average the default metric when dragging a field directly {kib-pull}63416[#63416] +* Fixes bug in field list when _source contained fields with dots {kib-pull}63752[#63752] +* Allows table to scroll horizontally {kib-pull}63805[#63805] +* Migrates timelion vis {kib-pull}62819[#62819] +* TSVB Validation fix color rule validation {kib-pull}67759[#67759] +Machine Learning:: +* Fixes the limit control on the Anomaly explorer page {kib-pull}65459[#65459] +* Hides selector helper in Anomaly Explorer swimlane {kib-pull}65522[#65522] +* Fixes dashboard URLs for auditbeat module {kib-pull}65707[#65707] +* Fixes vertical overflow on Single Metric Viewer page {kib-pull}66413[#66413] +* Catches unknown index pattern errors {kib-pull}61935[#61935] +* Disables data frame anaylics clone button based on permission {kib-pull}64830[#64830] +* Disables calendar all job switch {kib-pull}65635[#65635] +* Shows warning when the model memory limit is higher than the memory available in the ML node {kib-pull}65652[#65652] +* Removes assignment_explanation when cloning job {kib-pull}68226[#68226] +* Ensures at least one field is included in analysis before data frame analytics job is created {kib-pull}65320[#65320] +* Anomaly Explorer: if filter includes wildcard ensure matching swimlanes are not masked {kib-pull}65384[#65384] +* Fixes reordering in view by swimlane when overall cell selected {kib-pull}65290[#65290] +* Fixes anomaly charts for rare detectors when model plot is enabled {kib-pull}66075[#66075] +* Adds job timing stats to anomaly jobs {kib-pull}65696[#65696] +* Fixes anomaly dot plotted in wrong location in Single Metric Viewer {kib-pull}66071[#66071] +Management:: +* Fixes error when deleting snapshots behind reverse proxy {kib-pull}66147[#66147] +* Fixes bug when editing retention of slm policy {kib-pull}67137[#67137] +* Fixes fetch policies query {kib-pull}67827[#67827] +* Adds missing time unit labels {kib-pull}68205[#68205] +* Fixes pagination bugs in CCR and Remote Clusters {kib-pull}65931[#65931] +* Cleans up doc title when navigating away from Snapshot Restore {kib-pull}67906[#67906] +* Fixes boolean cell values in analytics table result views and transforms wizard {kib-pull}62618[#62618] +* Index pattern management - field list - localization functions returning empty strings {kib-pull}64055[#64055] +Maps:: +* Fixes replaceLayerList to handle case where map is not intialized {kib-pull}62202[#62202] +* Safely handles empty string and invalid strings from EuiColorPicker {kib-pull}62507[#62507] +* Do not show circle border when symbol size is zero {kib-pull}62644[#62644] +* Fixes attribution overflow with exit full screen button {kib-pull}62699[#62699] +* Creates NOT EXISTS filter for tooltip property with no value {kib-pull}62849[#62849] +* Fixes bug where toggling Scaling type does not re-fetch data {kib-pull}63326[#63326] +* Fixes double fetch when filter pill is added {kib-pull}63024[#63024] +* Fixes term join agg key collision {kib-pull}63324[#63324] +* Fixes date labels {kib-pull}63909[#63909] +* Removes SLA percentage metric {kib-pull}65718[#65718] +* Removes dateline check for geo_shape queries, split geo_bounding_box queries that cross dateline into 2 boxes {kib-pull}64598[#64598] +* Handles case where fit to bounds does not match any documents {kib-pull}66307[#66307] +* Returns bounding box for static feature collection without joins {kib-pull}66607[#66607] +* Fixes legend icon color for custom categorial palettes {kib-pull}67141[#67141] +Metrics:: +* Disables search bar when live stream is on {kib-pull}65491[#65491] +* Ensures live stream always gets latest entries {kib-pull}67935[#67935] +* Fixes time picker layout issues on Inventory View {kib-pull}66094[#66094] +* Fixes validation for threshold values {kib-pull}66281[#66281] +* Prevents component errors from breaking the whole UI {kib-pull}65456[#65456] +* Fixes mistake in container ip field name {kib-pull}66198[#66198] +* Fixes time state bug {kib-pull}67630[#67630] +* Require filterQuery to be ES JSON {kib-pull}64937[#64937] +* Debounce onChange in alert creation UI {kib-pull}65167[#65167] +* Fixes default metric alert interval for new conditions {kib-pull}66610[#66610] +Platform:: +* Fixes inconsistent search behaviour in Advanced Settings {kib-pull}64510[#64510] +* SavedObjects bulkCreate API should return migrationVersion and strip the type & namespace from the id {kib-pull}65150[#65150] +* Fixes task manager cancel warning {kib-pull}63756[#63756] +* New Kibana app link order {kib-pull}67991[#67991] +Security:: +* Fix authentication loop when upgrading Kibana from 6.8 to 7.7+ {kib-pull}67687[#67687] +* Previously, users couldn't log in with SAML Identity Provider Initiated flow (e.g. from Okta Dashboard) if they already had +an existing, but expired session. Now it should be possible {kib-pull}59686[#59686] +* Fixes EncryptedSavedObjectsClientWrapper fails on stripEncryptedAttributes for saved object with errors {kib-pull}61385[#61385] +* Adds username/password validation to login form {kib-pull}60681[#60681] +SIEM:: +* Fixes import bug with non existent signals index {kib-pull}65595[#65595] +* Restricts ML rule modification to ML Admins {kib-pull}65583[#65583] +* Fixes timeline buildGlobalQuery {kib-pull}68320[#68320] +Uptime:: +* Refreshes index and also show more info to user regarding index/data {kib-pull}62606[#62606] +* Updates uptime ml job id to limit to 64 char {kib-pull}64394[#64394] +* Enables deselection of stale filters {kib-pull}65523[#65523] +* Unmounts uptime app properly {kib-pull}66950[#66950] + +[float] +[[deprecation-7.8.0]] +=== Deprecations +Platform:: +* Deprecates IE11 support {kib-pull}66512[#66512] +Security:: +* Deprecates {kib} user in favor of kibana_system user {kib-pull}63186[#63186] + +[[release-notes-7.7.1]] +== {kib} 7.7.1 + +See <>. + +[float] +[[security-update-7.1.1]] +=== Security update +In {kib} 5.4.0 and later, TSVB visualizations contain a stored XSS flaw. Attackers that can +edit and create TSVB visualizations can obtain sensitive information, or perform +destructive actions, on behalf of the {kib} users who edit the TSVB visualization, CVE-2020-7015. + +You must upgrade to 7.7.1. If you are unable to upgrade, set `metrics.enabled:false` in your kibana.yml file to disable TSVB. + +[float] +[[bug-7.7.1]] +=== Bug fixes +Alerting:: +* Fixes bug with no possibility to edit the index name after adding {kib-pull}64033[#64033] +* Corrects validation and errors handling in PagerDuty action {kib-pull}63954[#63954] +* Fixes saving doc count alerts {kib-pull}63750[#63750] +* Fixes issue when connectors dropdown not showing all avaliable connectors {kib-pull}63636[#63636] +* Fixes inability to clear numeric field in a "Group over top docs" condition {kib-pull}63543[#63543] +* Handles when an Alerting Task fails due to its Alert object being deleted mid flight {kib-pull}63093[#63093] +APM: +* Encodes spaces when creating ML job {kib-pull}63683[#63683] +Canvas:: +* Fixes bring to front shortcut label {kib-pull}67374[#67374] +* Fixes add page CSS animation bug {kib-pull}66496[#66496] +Dashboard:: +* Shows visualization in Safari in dashboard fullscreen {kib-pull}66894[#66894] +* Fixes saved object share link {kib-pull}66771[#66771] +* Don't lose dashboard/visualize/discover state when navigating to other applications {kib-pull}66766[#66766] +Discover:: +* Don't lose dashboard/visualize/discover state when navigating to other applications {kib-pull}66766[#66766] +Lens and visualizations:: +* Fixes redirect on reload {kib-pull}66491[#66491] +* Timelion graph is not refreshing content after searching or filtering {kib-pull}67023[#67023] +* Don't lose dashboard/visualize/discover state when navigating to other applications {kib-pull}66766[#66766] +* Fixes redirect on reload {kib-pull}66491[#66491] +* Shows missing values on chart setting {kib-pull}66375[#66375] +* Usage of custom plugins using the @plugin statement and inline JavaScript in less code used in the TSVB Markdown +visualization is not allowed anymore. Using it will simply not apply the styles {kib-pull}65467[#65467] +* Fixes std deviation band mode {kib-pull}64413[#64413] +* Reloads on ui state change and fix ui state for tsvb {kib-pull}63699[#63699] +Machine Learning: +* Fixes watch creation {kib-pull}65956[#65956] +* Fixes new job wizard with multiple indices {kib-pull}64567[#64567] +* Fixes optional plugin dependency types {kib-pull}64450[#64450] +* Ensures both keyword/text types are excluded for selected excluded field {kib-pull}62712[#62712] +Management:: +* Fixes an integration issue with the security plugin in Ingest Pipelines and Snapshot and Restore that would incorrectly +report requiring security to be enabled when the plugins should work normally without security. +This affects the default docker distribution {kib-pull}67308[#67308] +* Preserves saved object references when saving the object {kib-pull}66584[#66584] +* Fixes detail panel for indices with % in the name {kib-pull}66435[#66435] +* Setting dev_tools.enabled: false in kibana.yml will no longer crash Kibana {kib-pull}66276[#66276] +* Fixes `mappings` keyword in Index Management plugin (Index detail pane, Mapping tab) {kib-pull}66012#66012] +Maps:: +* Handle cross cluster index _settings resp {kib-pull}66797[#66797] +* Fixes edit filter {kib-pull}64586[#64586] +Metrics:: +* Migrating Docker network fields {kib-pull}65133[#65133] +* Removes APM Hard Dependency {kib-pull}64952[#64952] +* Fixes for editing alerts in alert management {kib-pull}64597[#64597] +* Fixes alerting when a filter query is present {kib-pull}64575[#64575] +* Allows users to create alerts from the central Alerts UI {kib-pull}63803[#63803] +* Remove remaining field filtering {kib-pull}63398[#63398] +Monitoring:: +* Uses custom route to ensure global state is preserved {kib-pull}63891[#63891] +* Ensures time picker is actually disabled {kib-pull}63709[#63709] +* Fixes server response errors {kib-pull}63181[#63181] +Platform:: +* Allows any type for customResponseHeaders config {kib-pull}66689[#66689] +Security:: +* Allows IdP initiated SAML login with session containing expired token {kib-pull}59686[#59686] +SIEM:: +* Updates alert apiKey when the rule is updated {kib-pull}67364[#67364] +* Fixes Network Map empty tooltip {kib-pull}66828[#66828] +* Changes find_statuses route HTTP method from GET to POST {kib-pull}63508[#63508] +Uptime:: +* Updates duration chart query filters {kib-pull}63620[#63620] + + +[[release-notes-7.7.0]] +== {kib} 7.7.0 + +See <>. + +[float] +[[security-update-7.7.0]] +=== Security updates +* In 7.7.0 to 7.6.2, the Upgrade Assistant contains a prototype pollution flaw. An authenticated attacker with +privileges to write to the {kib} index can insert data that could cause {kib} to execute arbitrary code. This +could lead to an attacker executing code with the permissions of the {kib} process on the host system, CVE-2020-7012. ++ +By default, the Upgrade Assistant flaw is mitigated in all {kib} instances accessed through {ess}. ++ +For all other installations, you must upgrade to 7.7.0. If you are unable to upgrade, set `xpack.upgrade_assistant_enabled:false` in your kibana.yml file to disable the Upgrade Assistant. + +* In 7.7.0 and earlier, TSVB contains a prototype pollution flaw. Authenticated attackers with privileges to create +TSVB visualizations can insert data that could cause {kib} to execute arbitrary code. This +could lead to an attacker executing code with the permissions of the {kib} process on the host system, CVE-2020-7013. ++ +By default, the Upgrade Assistant flaw is mitigated in all {kib} instances accessed through {ess}. ++ +For all other installations, you must upgrade to 7.7.0. If you are unable to upgrade, set `metrics.enabled:false` in your kibana.yml file to disable TSVB. + +[float] +[[known-issues-7.7.0]] +=== Known issues + +SIEM:: +* When you deactivate an action within a rule, the rule fails {kib-issue}64870[#64870] +* When you add a timestamp to the PagerDuty action, the rule fails {kib-issue}64871[#64871] + +Management:: +* Editing Saved Objects (eg. Dashboards) via the "Inspect" JSON editor in Management corrupts objects {kib-issue}66542[#66542] + +Configuration:: +* The `server.customResponseHeaders` option prevents {kib} from starting if headers are set using a type other than string. +To fix this, convert your boolean and number headers to strings. For example, use `my-header: "true"` instead of `my-header: true`. +{kib-issue}66146[#66146] + +[float] +[[enhancement-7.7.0]] +=== Enhancements +Alerting:: +* Notifies user when security is enabled but TLS is not {kib-pull}60270[#60270] +* Displays warning when a permanent encryption key is missing and hides alerting UI appropriately {kib-pull}62772[#62772] +* Edits alert flyout {kib-pull}58964[#58964] +* Moves index params fields to connector config {kib-pull}60349[#60349] +* Adds the AlertDetails page {kib-pull}55671[#55671] +* License checks for actions plugin {kib-pull}59070[#59070] +APM:: +* Updates monospace font family variable {kib-pull}57555[#57555] +* Shows missing permissions message to the user on the Services overview {kib-pull}56374[#56374] +* Settings list page for managing custom actions {kib-pull}56853[#56853] +* Divides "Actions menu" into sections to improve readability {kib-pull}56623[#56623] +* Creates settings page to manage Custom Links {kib-pull}57788[#57788] +* Creates custom link from Trace summary {kib-pull}59648[#59648] +* Writes tests for the Custom Link API {kib-pull}60899[#60899] +* Threshold alerts {kib-pull}59566[#59566] +* Adds additional (java) options {kib-pull}59860[#59860] +* Sync badge {kib-pull}55113[#55113] +* Client.ip to metadata for RUM transactions {kib-pull}56546[#56546] +Canvas:: +* Adds Lens embeddables {kib-pull}57499[#57499] +* Switches to using EUI SuperDatePicker in time filter element {kib-pull}59249[#59249] +* Adds Visualize embeddable {kib-pull}60859[#60859] +* Adds argument to open all links in new tab within markdown element {kib-pull}57017[#57017] +* Updates esdocs datasource {kib-pull}59512[#59512] +* Improves expression autocomplete {kib-pull}52035[#52035] +Dashboard:: +* Use Elasticsearch `_async_search` instead of `_search` when it is available (excluding TSVB, Timelion, and Vega) {kib-pull}59224[#59224} +* When queries run more than 10 seconds, show a pop-up to allow users to run the queries beyond the configured Elasticsearch query timeout or cancel the queries {kib-pull}60706[#60706] +* Dashboard/add panel flow {kib-pull}59918[#59918] +* Moves the "Create New" button in add panel flyout to the top to make it more visible to the user {kib-pull}56428[#56428] +Lens and visualizations:: +* Creates Lens filters on click with bar, line, area charts {kib-pull}57261[#57261] +* Allows number formatting within Lens {kib-pull}56253[#56253] +* Shows a warning when you have partially configured a visualization, such as a bar chart with only an X axis {kib-pull}58279[#58279] +* Improves suggestion logic when dragging fields into the chart {kib-pull}60687[#60687] +* Disallows duplicate percentiles {kib-pull}58299[#58299] +* EUICodeEditor for Visualize JSON {kib-pull}58679[#58679] +* Supports Histogram Data Type {kib-pull}59387[#59387] +* Median aggregation labels now show "Median" instead of "50th percentile of" in Visualize. Custom labels are also used {kib-pull}58521[#58521] +* Adds positive_rate as a new aggregation to TSVB {kib-pull}59843[#59843] +* Makes linked saved search work when user navigates back using browser back button {kib-pull}59690[#59690] +* Visualization editor UI has been updated to the new styles, consistent with the rest of the platform and a more logical left-to-right flow of creating content {kib-pull}49864[#49864] +Logs:: +* Uses the Super date picker in the log stream {kib-pull}54280[#54280] +* Adds expandable rows with category examples {kib-pull}54586[#54586] +* Shows navigation bar while loading source configuration {kib-pull}59997[#59997] +Machine Learning:: +* Processes delimited files like semi-structured text {kib-pull}56038[#56038] +* Supports multi-line JSON notation {kib-pull}58870[#58870] +* Validates manual model memory input {kib-pull}59056[#59056] +* Clones analytics job {kib-pull}59791[#59791] +* Uses a new ML endpoint to estimate a model memory {kib-pull}60376[#60376] +* Module setup with dynamic model memory estimation {kib-pull}60656[#60656] +* Adds text fields to datafeed start modal {kib-pull}55560[#55560] +* Categorization examples privilege check {kib-pull}57375[#57375] +* Adds filebeat config to file dataviz {kib-pull}58152[#58152] +* Global calendars {kib-pull}57890[#57890] +* Adds indices_options to datafeed {kib-pull}59119[#59119] +* Displays multi-class results in evaluate panel {kib-pull}60760[#60760] +* Adds support for date_nanos time field in anomaly job wizard {kib-pull}59017[#59017] +* Uses EuiDataGrid for outlier result page {kib-pull}58235[#58235] +* Supports multi-line JSON notation in advanced editor {kib-pull}58015[#58015] +* Adds support for percentiles aggregation to Transform wizard {kib-pull}60763[#60763] +* Adds clone feature to transforms list {kib-pull}57837[#57837] +* Uses EuiDataGrid for transform wizard {kib-pull}52510[#52510] +* Replaces KqlFilterBar with QueryStringInput {kib-pull}59723[#59723] +Management:: +* The Remote Clusters UI added support for enabling "proxy" mode when creating or editing a remote cluster {kib-pull}59221[#59221] +* Adds filter for ILM phase to Index Management {kib-pull}57402[#57402] +* Creates Painless Lab app {kib-pull}57538[#57538] +* Moves out of legacy {kib-pull}55331[#55331] +* Moves out of legacy and migrates server side to New Platform {kib-pull}55690[#55690] +* Updates Console progress bar {kib-pull}56628[#56628] +* Auto follow pause & resume {kib-pull}56615[#56615] +* Supports triple quoted JSON strings and Painless highlighting to Watcher and SearchProfiler {kib-pull}57563[#57563] +* Server-side batch reindexing {kib-pull}58598[#58598] +* Better handling of closed indices {kib-pull}58890[#58890] +* Advanced settings UI change to centralize save state {kib-pull}53693[#53693] +* The autocomplete in the dev console now supports many different types of Elasticsearch pipeline processors {kib-pull}60553[#60553] +Maps:: +* Improves Layer Style UI {kib-pull}58406[#58406] +* Shows field type icons in data driven styling field select {kib-pull}55166[#55166] +* Style icons by category {kib-pull}55747[#55747] +* Adds type icons to SingleFieldSelect component {kib-pull}56313[#56313] +* Disables style forms when they are not applied due to other style settings {kib-pull}55858[#55858] +* Autocompletes for custom color palettes and custom icon palettes {kib-pull}56446[#56446] +* Allows simultaneous opening of multiple tooltips {kib-pull}57226[#57226] +* Adds Top term aggregation {kib-pull}57875[#57875] +* Direct Discover "visualize" to open Maps application {kib-pull}58549[#58549] +* Top term percentage field property {kib-pull}59386[#59386] +* Adds UI to disable style meta and get top categories from current features {kib-pull}59707[#59707] +* Adds draw control to create distance filter {kib-pull}58163[#58163] +* Blended layer that switches between documents and clusters {kib-pull}57879[#57879] +* Default ES document layer scaling type to clusters and show scaling UI in the create wizard {kib-pull}60668[#60668] +* Disables add layer button when flyout is open {kib-pull}54932[#54932] +* Supports categorical styling for numbers and dates {kib-pull}57908[#57908] +Metrics:: +* Setup commonly used time ranges in timepicker {kib-pull}56701[#56701] +* Custom Metrics for Inventory View {kib-pull}58072[#58072] +* Alerting for metrics explorer and inventory {kib-pull}58779[#58779] +* Creates a new menu for observability links {kib-pull}54847[#54847] +* Creates Metric Threshold Alert Type and Executor {kib-pull}57606[#57606] +Monitoring:: +* Supports shipping directly to the monitoring cluster {kib-pull}57022[#57022] +Platform:: +* Improves validation in truncate field formatter editor {kib-pull}56521[#56521] +* Variable support for interpreter {kib-pull}54788[#54788] +Reporting:: +* Handles page setup errors and capture the page, don't fail the job {kib-pull}58683[#58683] +* Adds the ability to search and delete historical reports in Management > Kibana > Reporting {kib-pull}60077[#60077] +SIEM:: +* Recent cases widget {kib-pull}60993[#60993] +* Adds custom reputation link {kib-pull}57814[#57814] +* Exports timeline {kib-pull}58368[#58368] +* Rule activity monitoring {kib-pull}60816[#60816] +* Removes has manage api keys requirement {kib-pull}62446[#62446] +* Adds release notes link and updates one UI section {kib-pull}60825[#60825] +* Adds rule notifications {kib-pull}59004[#59004] +* Version 7.7 rule import {kib-pull}61903[#61903] +* Creates ML Rules {kib-pull}58053[#58053] +* Case workflow api schema {kib-pull}51535[#51535] +* Service Now {kib} Action {kib-pull}53890[#53890] +* API with io-ts validation {kib-pull}59265[#59265] +* Status / Batch update {kib-pull}59856[#59856] +* Imports timeline {kib-pull}60880[#60880] +* Bug/clean up phase I {kib-pull}61354[#61354] +* Cases clean up Phase II {kib-pull}61750[#61750] +* Modifies gap detection util to accept all dateMath formats {kib-pull}56055[#56055] +* Adds note markdown field to backend {kib-pull}59796[#59796] +* Adds rule markdown field to rule create, detail, and edit flows {kib-pull}60108[#60108] +* Adds rule markdown to timeline global notes {kib-pull}61026[#61026] +* ServiceNow executor {kib-pull}58894[#58894] +* ServiceNow action improvements {kib-pull}60052[#60052] +Security:: +* Uses links instead of click handlers when switching spaces {kib-pull}57730[#57730] +* Introduce a login selector screen when multiple auth providers are enabled {kib-pull}53010[#53010] +* Warn when using deprecated roles {kib-pull}57209[#57209] +* Support for subfeature privileges {kib-pull}60563[#60563] +Telemetry:: +* Application Usage implemented in @kbn/analytics {kib-pull}58401[#58401] +* Server-side Migration to NP {kib-pull}60485[#60485] +* Use EuiTokens for ES field types {kib-pull}57911[#57911] +* Adds 7 day metrics to Application Usage telemetry {kib-pull}59846[#59846] +Uptime:: +* Adds Settings Page {kib-pull}53550[#53550] +* Adds Alerting UI {kib-pull}57919[#57919] +* Adds configurable page size to monitor list {kib-pull}60573[#60573] +* Adds Green Icon for all up Monitors {kib-pull}56770[#56770] +* Implements drag and select on charts {kib-pull}57089[#57089] +* Fix/filter group autocomplete {kib-pull}57686[#57686] +* Ml detection of duration anomalies {kib-pull}59785[#59785] + +[float] +[[bug-7.7.0]] +=== Bug fixes +Alerting:: +* Retains empty AlertsList when filter has removed all items {kib-pull}60501[#60501] +* Fixes alert threshold line disappears {kib-pull}61499[#61499] +* Cleanup action task params objects after successful execution {kib-pull}55227[#55227] +* Disables action plugin functionality when ESO plugin is using an ephemeral encryption key {kib-pull}56906[#56906] +* Makes slack param validation handle empty messages {kib-pull}60468[#60468] +* Makes user and password secrets optional {kib-pull}56823[#56823] +APM:: +* Changes "url" to "urls" in APM agent instructions {kib-pull}60790[#60790] +* Uses ES Permission API to check if a user has permissions to read from APM indices {kib-pull}57311[#57311] +* Filters are not prefilled when the custom link flyout is opened from a transaction page {kib-pull}61650[#61650] +* .apm-agent-configuration is not created if {kib} is started while ES is not ready {kib-pull}61610[#61610] +* Don’t include UI filters when fetching a specific transaction {kib-pull}57934[#57934] +* Uses docLinks API for APM doc links {kib-pull}61880[#61880] +* Updates APM index pattern {kib-pull}61265[#61265] +Canvas:: +* Toggles footer editable controls when you turn off edit mode #52786 {kib-pull}58044[#58044] +* Fixes map embeddables not showing up on PDF reports {kib-pull}61149[#61149] +* Limits rows in debug element {kib-pull}60804[#60804] +Dashboard:: +* Puts embed param into short url instead of behind it {kib-pull}58846[#58846] +* Allows markdown in error embeddable {kib-pull}62427[#62427] +Discover:: +* Removes flickering when opening filter bar popover {kib-pull}56222[#56222] +* Retains pinned filters when loading and clearing saved queries {kib-pull}54307[#54307] +Graph:: +* Specifies valid licenses for the Graph feature {kib-pull}55911[#55911] +* Improves graph missing workspace error message {kib-pull}58876[#58876] +Lens and visualizations:: +* Filters out pinned filters from saved object of Lens {kib-pull}57197[#57197] +* Adds using queries/filters for field existence endpoint {kib-pull}59033[#59033] +* Fixes display single bar in XYChart Bar Vis {kib-pull}61452[#61452] +* Resetting a layer generates new suggestions {kib-pull}60674[#60674] +* Fixes disabled switches in the editor {kib-pull}62911[#62911] +* Fixes broken Handlebar documentation links {kib-pull}55866[#55866] +* Shows timepicker in Timelion and TSVB {kib-pull}58857[#58857] +* Makes Vega remove filter work {kib-pull}58871[#58871] +* Makes d3 place nicely with object values {kib-pull}62004[#62004] +* Fixes position calculation of ticks in non-horizontal axes {kib-pull}62309[#62309] +Logs:: +* Correctly update the expanded log rate table rows {kib-pull}60306[#60306] +Machine Learning:: +* Handles Empty Partition Field Values in Single Metric Viewer {kib-pull}61649[#61649] +* Fixes job wizard model memory limit warnings {kib-pull}62331[#62331] +* Files data viz fix index pattern warning after index change {kib-pull}57807[#57807] +* Uses real datafeed ID for datafeed preview {kib-pull}60275[#60275] +* Disables start trial option when license management ui is disabled {kib-pull}60987[#60987] +* Fixes jobs list filter in url {kib-pull}61822[#61822] +* Fixes job ID in edit job flyout {kib-pull}61840[#61840] +* Fixes reporting of http request errors {kib-pull}61811[#61811] +* Ensures confusion matrix label column is correct {kib-pull}60308[#60308] +* Ensures column in correct position after reselect {kib-pull}61342[#61342] +* Ensures query bar syntax errors are shown {kib-pull}61333[#61333] +* Ensures job state is up to date {kib-pull}61678[#61678] +* Increases number of items that can be paged in calendars and filters lists {kib-pull}61842[#61842] +* Uses index pattern field format if one exists {kib-pull}61709[#61709] +* Ensures filter works as expected {kib-pull}62041[#62041] +* Ensures destination index pattern created {kib-pull}62450[#62450] +* Fixes page heading structure {kib-pull}56741[#56741] +* Fixes handling of index pattern with special characters {kib-pull}59884[#59884] +* Fixes to error handling for analytics jobs and file data viz {kib-pull}60249[#60249] +* Fixes Anomaly Explorer swimlane label and chart tooltips {kib-pull}61327[#61327] +* Prevents training_percent of 0 for analytics job {kib-pull}61789[#61789] +* Removes duplicate page main landmarks {kib-pull}56883[#56883] +* Fixes license check {kib-pull}58343[#58343] +* Clears {kib} index pattern cache on creation or form reset {kib-pull}62184[#62184] +Management:: +* Adds support for additional watch action statuses {kib-pull}55092[#55092] +* Fixes the Upgrade Assistant where the reindexing of an index was incorrectly marked as "Done", when it still required to be reindexed. This scenario could occur if a user reindexed an index, deleted it, then restored a snapshot of the index of an older version {kib-pull}60789[#60789] +* Fixes several invalid documentation links in the Snapshot and Restore UI {kib-pull}61331[#61331] +* Fixes for console error handling and loading of autocomplete {kib-pull}58587[#58587] +* Fixes a bug that caused Grokdebugger simulation to break in non-Default Kibana spaces {kib-pull}61423[#61423] +* Fixes an issue where Console would not render the request output if localStorage quota was reached {kib-pull}62424[#62424] +* Fixes a bug with Console's Copy As cURL functionality that would not properly escape single quotes in JSON string values which created issues with copying SQL queries from Console to cURL {kib-pull}63229[#63229] +* System index templates can't be edited {kib-pull}55229[#55229] +* Not possible to edit a watch that was created with the API if the ID contains a dot {kib-pull}59383[#59383] +* Fixes console a11y failures {kib-pull}57520[#57520] +Maps:: +* Do not show border color for icon in legend when border width is zero {kib-pull}57501[#57501] +* Uses blended layer when linking discover to maps {kib-pull}61467[#61467] +* Fixes tooltip overflow {kib-pull}61564[#61564] +* Cleans up unsaved state check {kib-pull}61705[#61705] +* Fixes regression in loading left join fields {kib-pull}63325[#63325] +* Fixes cross origin error for icon spritesheets when Kibana secured via OAuth proxy {kib-pull}53896[#53896] +* Correctly open layer settings from add layer wizard {kib-pull}48971[#48971] +Metrics:: +* Limits group by selector to only 2 fields {kib-pull}56800[#56800] +* Uses CPU Usage limits for Kubernetes pods when available {kib-pull}58424[#58424] +* Fixes toolbar popover for metrics table row {kib-pull}56796[#56796] +Monitoring:: +* Handles setup mode if security is disabled {kib-pull}53306[#53306] +* Protects against no monitoring data near end of time series {kib-pull}61273[#61273] +* Adds new config for logging index name {kib-pull}56920[#56920] +Platform:: +* Rollup index pattern error: must match one rollup index {kib-pull}56732[#56732] +* In scripted fields, unable to switch the `Type` {kib-pull}59285[#59285] +* Duplicates query filters in es request {kib-pull}60106[#60106] +* Bugfix dashboard unpins filters {kib-pull}62301[#62301] +* Fixes plugin enabled config options {kib-pull}60998[#60998] +* Fixes tabifyAggResponse {kib-pull}61214[#61214] +* Fixes parse interval {kib-pull}62267[#62267] +* Avoid 'app not found' flickering while awaiting for mount {kib-pull}56483[#56483] +* Creates empty string filters when value not specified {kib-pull}57442[#57442] +* Range aggregations now use the field formatter from the index pattern, instead of no formatter {kib-pull}58651[#58651] +Reporting:: +* Fixes error handling for job handler in route {kib-pull}60161[#60161] +Security:: +* Handling a 404 when the space's telemetry collector runs {kib-pull}55921[#55921] +SIEM:: +* Allows Import timeline for authorised users {kib-pull}61438[#61438] +* Imports timeline schema update {kib-pull}61622[#61622] +* Fixes bug with timeline templates not working {kib-pull}60476[#60476] +* Fixes export of single rule and the icons {kib-pull}62394[#62394] +* Updates process and TLS tables to use ECS 1.5 fields {kib-pull}60854[#60854] +Telemetry:: +* Fixes bug introduced in #55859 {kib-pull}57441[#57441] +* UI Metrics use findAll to retrieve all Saved Objects {kib-pull}59891[#59891] +Uptime:: +* Updates heartbeat index name for 7.7 {kib-pull}62172[#62172] +* Shows only total in snapshot heading {kib-pull}58376[#58376] +* Fixes PingList pagination {kib-pull}61481[#61481] +* Fixes es query function null reference errors {kib-pull}61465[#61465] +* Fixes issue with Kibana Icon in Uptime App {kib-pull}56837[#56837] +* Adds tests for pages {kib-pull}56736[#56736] + +[float] +[[deprecation-7.7.0]] +=== Deprecations +Monitoring:: +* Changes all configs to `monitoring.*` {kib-pull}54919[#54919], {kib-pull}56215[#56215] +Platform:: +* Migrates Vega and Graph configs to new platform {kib-pull}57011[#57011] + +[[release-notes-7.6.2]] +== {kib} 7.6.2 + +See <>. + +[float] +[[known-issue-7.6.2]] +=== Known issue + +Configuration:: +* The `server.customResponseHeaders` option prevents {kib} from starting if headers are set using a type other than string. +To fix this, convert your boolean and number headers to strings. For example, use`my-header: "true"` instead of `my-header: true`. +{kib-issue}66146[#66146] + +[float] +[[bug-7.6.2]] +=== Bug fixes +Discover:: +* Fixes infinite loop for view single document on discover {kib-pull}60236[#60236] +Machine Learning:: +* Shows view series link in anomalies table for machine_learning_user role {kib-pull}59549[#59549] +* Fixes bucket span estimators loading of max_buckets setting {kib-pull}59639[#59639] +Management:: +* Improperly defined Watcher Logging Action text parameters will now be handled elegantly by {kib} instead of causing {kib} to crash {kib-pull}60169[#60169] +* Fixes the namespace for indices autocompletion {kib-pull}59043[#59043] +* We fixed a bug in Console's proxy that would always override the "host" header {kib-pull}59143[#59143] +* Spacing between rendered shards {kib-pull}60238[#60238] +Maps:: +* Adds missing license to requests in maps embeddables {kib-pull}59207[#59207] +* Fixes custom color ramp on save {kib-pull}59953[#59953] +Metrics:: +* Ensures inventory view buckets never drop below 60 seconds {kib-pull}58503[#58503] +Monitoring:: +* Ensures we use the monitoring cluster for retrieving xpack info {kib-pull}59075[#59075] +Operations:: +* Fixes the watchers usage in the log rotation {kib-pull}60956[#60956] +Platform:: +* Edits to filter's custom label are ignored {kib-pull}59169[#59169] +* Fixes a bug that could cause saved object migrations to fail when an {es} snapshot is currently in progress {kib-pull}58884[#58884] +Security:: +* Fixes base path prepending for session storage short url redirects {kib-pull}59871[#59871] +SIEM:: +* Default the Timeline events filter to show All events {kib-pull}58953[#58953] +* Fixes dragging entries to the Timeline while data is loading may trigger a partial page reload {kib-pull}59476[#59476] +* Detection Fix typo in Adobe Hijack Persistence rule {kib-pull}58804[#58804] +* Fixes rule delete/duplicate actions {kib-pull}59306[#59306] +* Fixes minor UI bug on all rules table pagination {kib-pull}59094[#59094] +Visualizations:: +* Adds validation support for legacy filter values {kib-pull}58436[#58436] +* Fixes text color when using custom background color {kib-pull}60261[#60261] + +[[release-notes-7.6.1]] +== {kib} 7.6.1 + +See <>. + +[float] +[[known-issue-7.6.1]] +=== Known issue + +Configuration:: +* The `server.customResponseHeaders` option prevents {kib} from starting if headers are set using a type other than string. +To fix this, convert your boolean and number headers to strings. For example, use `my-header: "true"` instead of `my-header: true`. +{kib-issue}66146[#66146] + +[float] +[[security-fix-7.6.1]] +=== Security issues +In {kib} 7.6.0 and earlier, Node.js contains the following security issues: + +* The TLS handling code for Node.js includes a Denial of Service (DoS) issue. Successful exploitation of the flaw could result in {kib} crashing. Refer to https://www.elastic.co/community/security/, CVE-2019-15604. ++ +There are no known workarounds for this issue. + +* There are issues with how Node.js handles malformed HTTP headers. The malformed headers could result in an HTTP request smuggling attack when {kib} is running behind a proxy that is vulnerable to HTTP request smuggling attacks. Refer to https://www.elastic.co/community/security/, CVE-2019-15605 and CVE-2019-15606. ++ +For instructions on how to mitigate HTTP request smuggling attacks, contact your proxy vendor. + +Administrators running {kib} in an environment with untrusted users should upgrade to {kib} 7.6.1, which updates Node.js to 10.19.0. + +[float] +[[enhancement-7.6.1]] +=== Enhancements +SIEM:: +* Imports rules unit tests {kib-pull}57466[#57466] + +[float] +[[bug-7.6.1]] +=== Bug fixes +APM:: +* Fixes cloud env in APM tutorial {kib-pull}57817[#57817] +* Adds `xpack.apm.enabled` key to config schema {kib-pull}57539[#57539] +* X-axis labels on Error occurrences chart are incorrect based on {kib} timezone {kib-pull}55686[#55686] +Canvas:: +* Sanitizes workpad before sending to API {kib-pull}57704[#57704] +Lens and visualizations:: +* Fixes bugs in Lens filters (#56441) {kib-pull}56648[#56648] +* Makes field stats work for index patterns without time fields {kib-pull}56759[#56759] +* Fixes auto refresh in visualizations and Lens {kib-pull}57667[#57667] +Machine Learning:: +* Fixes Data Visualizer responsive layout {kib-pull}56372[#56372] +* Fixes overall stats for saved search on the Data Visualizer page {kib-pull}57312[#57312] +* Fixes jobs list default refresh {kib-pull}57086[#57086] +* Updates schema definition for create route {kib-pull}56979[#56979] +* Fixes brush visibility. {kib-pull}57564[#57564] +* Fixes chart resize after browser refresh {kib-pull}57578[#57578] +* Fixes hiding date picker for settings pages {kib-pull}57544[#57544] +Management:: +* Allows support for nested multi-fields {kib-pull}58203[#58203] +* Fixes performance bottleneck for large JSON payloads {kib-pull}57668[#57668] +* Fixes filter deprecations search filter {kib-pull}57541[#57541] +Maps:: +* Sets filter.meta.key to geoFieldName so query passes filterMatchesIndex when ignoreFilterIfFieldNotInIndex is true {kib-pull}56692[#56692] +* Fixes document source top hits split by scripted field {kib-pull}57481[#57481] +* Only request field in docvalue_fields when the field supports doc values {kib-pull}57372[#57372] +Monitoring:: +* Fixes issue when index pattern has no fields {kib-pull}58242[#58242] +* Fixes inaccuracies in Logstash pipeline listing metrics {kib-pull}55868[#55868] +Platform:: +* Limits fetching index patterns {kib-pull}56603[#56603] +* Fixes browser date format {kib-pull}57714[#57714] +* Prepends basePath in getUrlForApp {kib-pull}57316[#57316] +* Uses app id instead of pluginId to generate navlink from legacy apps {kib-pull}57542[#57542] +* Retries ES API calls that fail with 410/Gone to prevent {kib} from crashing at startup {kib-pull}56950[#56950] +* Removes injected reference from home app {kib-pull}57836[#57836] +Security:: +* Logout should redirect to the login screen at the server base path {kib-pull}56786[#56786] +* Adds xpack.encryptedSavedObjects.encryptionKey to docker allow-list {kib-pull}58291[#58291] +* Fixes short url in spaces {kib-pull}58313[#58313] +SIEM:: +* Backend end-to-end tests {kib-pull}57166[#57166] +* Removes internal tags when copying signals from rules {kib-pull}57744[#57744] +* Fixes return codes where some were rule_id instead of id {kib-pull}57939[#57939] +* Fixes Host Details Events Table to only show events for specified Host {kib-pull}57388[#57388] +Uptime:: +* Uses scripted metric for snapshot calculation {kib-pull}58247[#58247] + +[[release-notes-7.6.0]] +== {kib} 7.6.0 + +See also <>. + +[float] +[[known-issue-7.6.0]] +=== Known issue + +* When you use the default `dateFormat:tz: browser` setting, the timestamps appear in UTC instead of the local time of the user browser. To use the local time of the user browser, set `dateFormat:tz:` to the timezone of the user. {kib-issue}57457[#57457] +* The `server.customResponseHeaders` option prevents {kib} from starting if headers are set using a type other than string. +To fix this, convert your boolean and number headers to strings. For example, use `my-header: "true"` instead of `my-header: true`. +{kib-issue}66146[#66146] + +[float] +[[enhancement-7.6.0]] +=== Enhancements +APM:: +* Updates apm index pattern {kib-pull}54095[#54095] +* Adds service name to jvm {kib-pull}50830[#50830] +* Adds filter option to Metadata table {kib-pull}48520[#48520] +* Updates Error occurrences graph tooltip to display start and end for bucket period {kib-pull}49638[#49638] +* Pagination of top 10 trace samples {kib-pull}51911[#51911] +* Makes it possible to link directly to a trace with just the trace.id {kib-pull}51450[#51450] +* Transaction page throws unhandled exception if transactions doesn't have `http.request` {kib-pull}53760[#53760] +* Adds `message` fields to metadata table {kib-pull}54017[#54017] +* Shows errors on the timeline instead of under the transaction {kib-pull}53756[#53756] +* Traces with identical transactions names are combined, even though they are from different services {kib-pull}54247[#54247] +* Uses indexPatternsService for kuery bar suggestions {kib-pull}49169[#49169] +* Migrates server routes to NP {kib-pull}49455[#49455] +* Adds `service.version` filter to transaction views {kib-pull}52748[#52748] +* Adds version annotations to timeseries charts {kib-pull}52640[#52640] +* Error stack trace improvements {kib-pull}49254[#49254] +* Performance comparison charts by user agent (browser) {kib-pull}49582[#49582] +* Adds UI Indices runtime configuration {kib-pull}48079[#48079] +* Updates apm index pattern {kib-pull}54693[#54693] +* Clears cache when updating indices via UI {kib-pull}51767[#51767] +Canvas:: +* Enables Embeddable maps {kib-pull}53971[#53971] +* Uses compressed forms in sidebar {kib-pull}49419[#49419] +Dashboard:: +* Redesigns empty screen {kib-pull}53681[#53681] +* Adds visualization from dasbhoard empty screen {kib-pull}52670[#52670] +* Redesigns empty screen in readonly mode {kib-pull}54073[#54073] +* Adds Lens to Dashboard {kib-pull}53110[#53110] +* Improves "Create new" UI in dashboard {kib-pull}49189[#49189] +Discover:: +* Refactors discover index pattern selector to Lens `ChangeIndexPattern` Component {kib-pull}51973[#51973] +* Adds nested field support to KQL {kib-pull}47070[#47070] +* Supports nested fields in existing filter types {kib-pull}49537[#49537] +* Disables/enables filter with click+shift on a filter badge {kib-pull}52751[#52751] +* Possibility to filter when testing scripted fields (#35379) {kib-pull}44220[#44220] +* Adds label and icon to nested fields in the doc table {kib-pull}54199[#54199] +Graph:: +* Improves error message on graph requests {kib-pull}54230[#54230] +* Adds sample data {kib-pull}54558[#54558] +Lens:: +* Allows numeric terms aggs {kib-pull}50177[#50177] +* Adds support for scripted fields and default index pattern {kib-pull}53948[#53948] +* Loads Lens together with kibana app {kib-pull}50164[#50164] +* Disables saving visualization until there are no changes to the document {kib-pull}52982[#52982] +* Adds clear layer feature {kib-pull}53627[#53627] +* Adds support for scripted fields and aliases to the existence API {kib-pull}54064[#54064] +Logs:: +* Log rate setup index validation {kib-pull}50008[#50008] +* Adds categories table to the categorization tab {kib-pull}53004[#53004] +* Disables ML job setup form while setup is pending {kib-pull}54705[#54705] +Machine Learning:: +* Updates Anomaly Detection job wizard button styles, page panel and titles {kib-pull}53340[#53340] +* Improves processing of groups in data recognizer wizard {kib-pull}49310[#49310] +* Indicates missing required privileges for import in File Data Visualizer {kib-pull}50147[#50147] +* Stats bar for data frame analytics {kib-pull}49464[#49464] +* Adds the job message tab to data frame analytics {kib-pull}50468[#50468] +* Reactive time-range selection in Single Metric Viewer {kib-pull}51008[#51008] +* Adds Custom URLs and Calendars to the Job wizards {kib-pull}51281[#51281] +* Performs cardinality check on enabling the model plot {kib-pull}51915[#51915] +* Fetches the latest job messages and enables sorting by time {kib-pull}52388[#52388] +* Persists the time range brush when expanded to full width {kib-pull}54020[#54020] +* Supports search for partitions on Single Metric Viewer {kib-pull}53879[#53879] +* APM modules configs for RUM Javascript and NodeJS {kib-pull}53792[#53792] +* Model memory limit calculator enhancements for multi-metric job wizard {kib-pull}54573[#54573] +* Data Visualizer redesign {kib-pull}54358[#54358] +* Formatting for additional timing and model size stats {kib-pull}55062[#55062] +* Adds ML node warning to overview and analytics pages {kib-pull}50766[#50766] +* Enables lat_long detector function in advanced wizard {kib-pull}50787[#50787] +* Categorization wizard {kib-pull}53009[#53009] +* Regression results view {kib-pull}49667[#49667] +* Auto-populate model_memory_limit {kib-pull}50714[#50714] +* Reruns evaluate endpoint for search bar queries {kib-pull}50991[#50991] +* Adds search bar {kib-pull}51235[#51235] +* Creates classification jobs via the UI {kib-pull}51619[#51619] +* Adds description field to job creation and display in jobs list {kib-pull}52217[#52217] +* Creates classification jobs results view {kib-pull}52584[#52584] +* Adds 'excludes' input field to form {kib-pull}53856[#53856] +* Adds link to docs {kib-pull}54189[#54189] +* Uses field caps api to set column type {kib-pull}54543[#54543] +* Truncates text in Overview page 'Latest timestamp' column {kib-pull}50004[#50004] +* Color Range Legend component {kib-pull}52794[#52794] +Management:: +* Support scheme field when creating a Threshold alert with a Webhook action {kib-pull}53757[#53757] +* Adds Mappings Editor to Index Template Wizard {kib-pull}47562[#47562] +* SearchProfiler to NP {kib-pull}48795[#48795] +* Upgrade Assistant to New Platform Ready {kib-pull}50163[#50163] +* License Management to New Platform {kib-pull}51886[#51886] +* New Platform (NP) Migration {kib-pull}50908[#50908] +* Console with better SQL support {kib-pull}51446[#51446] +* Allows User to Cleanup Repository from UI {kib-pull}53047[#53047] +* Updates advanced settings text for usage data {kib-pull}52657[#52657] +Maps:: +* Makes grid rectangles the default symbolization for geo grid source {kib-pull}50169[#50169] +* Focuses inputs when editor opens popovers {kib-pull}51487[#51487] +* Uses style metadata to calculate symbolization bands {kib-pull}51713[#51713] +* Better style defaults {kib-pull}52420[#52420] +* Vector style UI redesign {kib-pull}53946[#53946] +* Allows editing EMS basemap selection {kib-pull}53631[#53631] +* Adds text halo color and width style properties {kib-pull}53827[#53827] +* Adds labels to sample data maps {kib-pull}54671[#54671] +* Adds categorical styling {kib-pull}54408[#54408] +* Hides map visualization types with default kibana.yml settings {kib-pull}49103[#49103] +* Hides header panel in embeddable panel {kib-pull}50728[#50728] +Metrics:: +* Calculates interval based on the dataset's period {kib-pull}50194[#50194] +* Ports graphql query for snapshot and node details to hapijs {kib-pull}50730[#50730] +* Adds ability to filter snapshot view by account and region {kib-pull}53307[#53307] +* Adds inventory metadata api with regions and accounts {kib-pull}52660[#52660] +* Removes graphql types {kib-pull}54176[#54176] +* Adds AWS Metricsets to Inventory Models {kib-pull}49983[#49983] +Monitoring:: +* Fetches shard data more efficiently {kib-pull}54028[#54028] +* Displays APM server memory in bytes {kib-pull}54275[#54275] +Operations:: +* Adds support for log rotation {kib-pull}49750[#49750] +Monitoring:: +* h1 elements for accessibility {kib-pull}52276[#52276] +Platform:: +* Allows routes to define some payload config values {kib-pull}50783[#50783] +* Moves IndexPatterns into the NP {kib-pull}51199[#51199] +* Moves configuration validation to new platform {kib-pull}51880[#51880] +* Improves "Browser client is out of date" error message {kib-pull}50296[#50296] +Reporting:: +* Converts main Reporting index to TS {kib-pull}49129[#49129] +* Removes any types and references to Hapi {kib-pull}49250[#49250] +* Updates some runtime validations {kib-pull}53975[#53975] +Security:: +* Role Mappings UI {kib-pull}53620[#53620] +* Adds message to login page {kib-pull}51557[#51557] +* Updates Node.js to version 10.18.0 {kib-pull}52865[#52865] +* Improves session idle timeout, add session lifespan {kib-pull}49855[#49855] +* Adds support for certificates in PKCS#12 (P12) key stores {kib-pull}53810[#53810] +SIEM:: +* New Overview Page {kib-pull}54783[#54783] +* Adds DNS histogram {kib-pull}50409[#50409] +* Adds alerts table {kib-pull}51959[#51959] +* Histogram enhancement {kib-pull}54544[#54544] +* Dns histogram enhancement {kib-pull}54902[#54902] +* Tests for search_after and bulk index {kib-pull}50129[#50129] +* Adds ecs threat properties to rules {kib-pull}51782[#51782] +* Sets Signal status open closed REST API {kib-pull}52356[#52356] +* Search signals index {kib-pull}52661[#52661] +* Adds created_at and updated_at timestamps to rules {kib-pull}53137[#53137] +* Rule Status Monitoring {kib-pull}54452[#54452] +* Adds filtering abilities to the KQL REST API {kib-pull}49451[#49451] +* REST API Additions {kib-pull}50514[#50514] +* REST API improvements and changes from UI/UX feedback {kib-pull}50797[#50797] +* Adds of risk score, output index, rule copying, and more {kib-pull}51190[#51190] +* Adds signal data index per spaces through index naming conventions {kib-pull}52237[#52237] +* Adds privileges API endpoint {kib-pull}52707[#52707] +* Adds a tags service and optimizes alert_id lookups {kib-pull}52838[#52838] +* Adds prepackaging rules capability {kib-pull}53062[#53062] +* Adds timeline_id string to rules {kib-pull}53343[#53343] +* Bulk REST API for create, update, and delete {kib-pull}53543[#53543] +* Import/Export REST endpoints {kib-pull}54332[#54332] +* Time gap detection and logging {kib-pull}54547[#54547] +* Adds Rules Table {kib-pull}50839[#50839] +* Adds Signals Table and additional configuration options to StatefulEventsViewer {kib-pull}52044[#52044] +* Adds support for apm-* to the network map {kib-pull}54876[#54876] +* HTTP Requests table {kib-pull}49955[#49955] +* Adds Authentications histogram {kib-pull}48260[#48260] +* Adds hosts and network anomalies histogram {kib-pull}50295[#50295] +* Detection engine placeholders {kib-pull}50220[#50220] +* Adds SavedQuery in Timeline {kib-pull}49813[#49813] +* Adds creation rule {kib-pull}51376[#51376] +* Adds edit on rule creation {kib-pull}51670[#51670] +* Adds MITRE ATT&CK {kib-pull}52398[#52398] +* Details and Edit view for a rule {kib-pull}53252[#53252] +* Permission II {kib-pull}54292[#54292] +* Adds status to rule details {kib-pull}54812[#54812] +* From signals to timeline {kib-pull}54769[#54769] +* Detections create prepackage rules {kib-pull}55403[#55403] +* Feedback to user about generated encryption key {kib-pull}56464[#56464] +Uptime:: +* Updates snapshot counts {kib-pull}48035[#48035] +* Migrates Uptime server routing to new platform {kib-pull}51125[#51125] +* Adds tags dropdown to Overview filters group {kib-pull}50837[#50837] +* New monitor list expanded row {kib-pull}46567[#46567] +* Adds options to disable zoom, hide tool tips, widgets/overlays in embeddable maps {kib-pull}50663[#50663] +* New details panel and location map {kib-pull}50518[#50518] +* Lists external linking {kib-pull}53098[#53098] +* Monitor details page left side title {kib-pull}53529[#53529] +* Monitor SSL Certificate Color version for warning {kib-pull}54040[#54040] + +[float] +[[bug-7.6.0]] +=== Bug fixes +APM:: +* Upgrades APM migration script v1 support {kib-pull}52824[#52824] +* Adds missing semi-colon to styled component {kib-pull}51436[#51436] +* Quick fix for ACM to ensure more than 10 items are displayed {kib-pull}52262[#52262] +* Sets no of ticks based on available width for chart {kib-pull}50904[#50904] +* Make sure errors per minute are reported correctly {kib-pull}54751[#54751] +* Fixes firefox SVG NaN errors when rendering charts {kib-pull}56578[#56578] +* Fixes initial error sort field {kib-pull}56577[#56577] +* Empty message "No data available" for Labels and User metadata sections missing {kib-pull}49846[#49846] +Canvas:: +* Fixes axisConfig position argument UI {kib-pull}50717[#50717] +* Fixes #45896 {kib-pull}50229[#50229] +* Fixes bugs with full screen filters {kib-pull}54792[#54792] +* Fixes the Copy Post Url link {kib-pull}54831[#54831] +* Fixes color and toggle accessibility {kib-pull}54661[#54661] +Dashboard:: +* Removes double handler {kib-pull}53707[#53707] +* Decodes url params, so they are not encoded twice {kib-pull}54738[#54738] +* Changes background color to align with EUI color {kib-pull}54060[#54060] +* Fixes hide 'edit' button for mobile for dashboards {kib-pull}50639[#50639] +Discover:: +* Fixes histogram min interval {kib-pull}53979[#53979] +* Improves kql error message handling and avoid fetching twice {kib-pull}54239[#54239] +* Fixes double fetch errors {kib-pull}54701[#54701] +* Fixes pagination controls should not scroll horizontally for saved search {kib-pull}50764[#50764] +* Don't throw exception when refreshing fields of an index pattern {kib-pull}55836[#55836] +* Fixes filter pill label for filters with negated alias {kib-pull}50743[#50743] +* Filters scripted fields preview field list to source fields {kib-pull}53826[#53826] +* Fixes operator overflowing out popover {kib-pull}50030[#50030] +Graph:: +* Only show explorable fields {kib-pull}54101[#54101] +Lens:: +* Modifies merge tables to use the same logic as auto date {kib-pull}52931[#52931] +* Selects Records field when count operation is chosen {kib-pull}53911[#53911] +* Shows keyword fields for pre-7.3 index patterns {kib-pull}52410[#52410] +* Fixes sorting crash when removing a Y axis that is being used for sorting {kib-pull}52694[#52694] +* Shows fields when using index pattern without time field {kib-pull}54804[#54804] +* Fixes bugs in Lens filters {kib-pull}56441[#56441] +Logs:: +* Adds missing headers in Logs & metrics {kib-pull}52405[#52405] +* Uses the correct icons and labels in the feature cont… {kib-pull}55292[#55292] +* Allows Logs/ML integration result access with machine… {kib-pull}55884[#55884] +* Fixes the scale of the search markers {kib-pull}55731[#55731] +Machine Learning:: +* Fixes escape special characters for Lucene query language {kib-pull}50494[#50494] +* Keeps rule editor flyout open on refresh {kib-pull}53458[#53458] +* Fixes counters and percentages for array fields on the Data Visualizer page {kib-pull}55209[#55209] +* Fixes tooltip's persistence on mouse leave {kib-pull}55694[#55694] +* Fixes Anomaly Explorer swimlane tooltip issue {kib-pull}55827[#55827] +* Fixes the annotation area tooltip offset {kib-pull}55955[#55955] +* Fixes info content detector field selection {kib-pull}51914[#51914] +* Job validation loading spinner {kib-pull}54450[#54450] +* Improves job wizards with datafeed aggregations {kib-pull}55180[#55180] +* Fixes missing job_type in job messages search {kib-pull}55330[#55330] +* Fixes module setup error for insufficient index pattern privileges {kib-pull}55989[#55989] +* Ensures advanced editor can be validated when empty {kib-pull}52831[#52831] +* Ensures advanced editor validates model memory unit correctly {kib-pull}54011[#54011] +* Ensures result field columns can be deselected and re-selected {kib-pull}54766[#54766] +* Only render tablist if it contains tabs {kib-pull}54838[#54838] +* Improves handling of text fields {kib-pull}55002[#55002] +* Filters out docs with no prediction data from results table {kib-pull}54826[#54826] +* Fixes word wrap in Overview page sidebar on IE {kib-pull}50668[#50668] +* Fixes lat_long anomalies table links menu and value formatting {kib-pull}50916[#50916] +* Fixes loading of Data Visualizer with KQL saved search {kib-pull}51882[#51882] +* Corrects URL of the create job tips docs page {kib-pull}53576[#53576] +* Displays anomaly actual in chart tooltip when model plot enabled {kib-pull}54364[#54364] +* Fixes permissions checks for Data Visualizer create job links {kib-pull}55431[#55431] +* Fixes empty table header cell and duplicate ID accessibility issues {kib-pull}54917[#54917] +* Accessibility fix for structural markup on table rows {kib-pull}55075[#55075] +Management:: +* {kib} should allow a min_age setting of 0ms in ILM policy phases {kib-pull}53719[#53719] +* Adds try/catch when parsing index filter from URI {kib-pull}56051[#56051] +* Passes termOrder and hasTermsAgg properties to serializeThresholdWatch function {kib-pull}54391[#54391] +* Adds support for capitalized date formats in snapshot names {kib-pull}53751[#53751] +* Index Lifecycle Policies show wrong unit in {kib} UI {kib-pull}55228[#55228] +* Theme and Mode imports {kib-pull}50473[#50473] +* Proxy fallback {kib-pull}50185[#50185] +* Fixes load from remote {kib-pull}52814[#52814] +* Fixes suggested value for time_zone in range query {kib-pull}53841[#53841] +* Handle double quote special case {kib-pull}54474[#54474] +* Fixes handling of bad profile data and update tab behavior {kib-pull}55806[#55806] +* Fixes icon path in tutorial introduction {kib-pull}49684[#49684] +* Fixes index templates editor to support mappings types {kib-pull}55804[#55804] +Maps:: +* Fixes regression preventing maps telemetry from populating & remove task manager logic {kib-pull}52834[#52834] +* Categorical palettes {kib-pull}54918[#54918] +* Do not re-fetch data on empty filter setting changes {kib-pull}49382[#49382] +* Fixes removal of multi fields for tooltip field selection {kib-pull}49816[#49816] +* Prevents users from overflowing URL when filtering by shape {kib-pull}50747[#50747] +* Only provide visibility check when vector layer has joins {kib-pull}51388[#51388] +* Fixes too_many_buckets_exception for top hits {kib-pull}51497[#51497] +* Only show styles that apply to layer feature types in legend {kib-pull}52335[#52335] +* Fixes tooltips for CCS {kib-pull}52793[#52793] +* Passes getFieldFormatter to DynamicTextProperty {kib-pull}53937[#53937] +* Expands extent filter to tile boundaries {kib-pull}54276[#54276] +* Fixes warning about missing key in react element {kib-pull}55372[#55372] +* Fixes join metric field selection bugs {kib-pull}56044[#56044] +* Adds mapbox-gl-rtl-text library for RTL languages {kib-pull}54842[#54842] +* Ensures the query-object is populated {kib-pull}49917[#49917] +* Delays vector tile layer syncing until spritesheet is loaded {kib-pull}48955[#48955] +* Sanitizes attribution {kib-pull}52309[#52309] +* Only show legend when layer is visible {kib-pull}53781[#53781] +* Shows custom color ramps in legend {kib-pull}53780[#53780] +* Enforces file-type check in file dialog {kib-pull}55063[#55063] +Metrics:: +* Fixes Metrics Explorer exception when deleting metric {kib-pull}55893[#55893] +* Fixes title truncation in Metrics Explorer {kib-pull}55917[#55917] +* Passes relevant shouldAllowEdit capabilities into SettingsPage {kib-pull}49781[#49781] +* Don't allow duplicate saved views with the same name {kib-pull}52040[#52040] +* Adds aria labels to fields {kib-pull}54510[#54510] +Monitoring:: +* Fixes Logstash pipelines page in multi-cluster environment {kib-pull}50166[#50166] +* Improves permissions required around setup mode {kib-pull}50421[#50421] +* Adds error state for unstructured logs {kib-pull}53299[#53299] +* Ensures setup mode work in a CCS environment {kib-pull}54361[#54361] +* Clarifies that these auth settings are for sending data {kib-pull}48437[#48437] +Operations:: +* Adds missing docker settings {kib-pull}56411[#56411] +* Prevents xpack.task_manager.index being set to .tasks {kib-pull}52002[#52002] +Platform:: +* Displays changed field formats without requiring hard page refresh. {kib-pull}52874[#52874] +* {kib} 7.0.0 URL field formatter doesn't render relative hyperlinks properly {kib-pull}53265[#53265] +* Interpreter conversion of string to number should throw on NaN #27788 {kib-pull}50063[#50063] +* Cancels discarded KQL value suggestion requests {kib-pull}51411[#51411] +* Performs successful Elasticsearch version check before migrations {kib-pull}51311[#51311] +Reporting:: +* Do not fail the report if request is aborted {kib-pull}52344[#52344] +* Fixes map tiles not loading by using Chrome's Remote Protocol {kib-pull}55137[#55137] +* Corrects the docvalue_fields params in the search query Download CSV from Dashboard Panel {kib-pull}52833[#52833] +Security:: +* Uses the server's basePath when building the SAML ACS {kib-pull}51391[#51391] +* Fixes elasticsearch.ssl.alwaysPresentCertificate default {kib-pull}52242[#52242] +* Forces line-break if username is a solid long string {kib-pull}50807[#50807] +* Fixes infinite redirect loop when multiple cookies are sent {kib-pull}50452[#50452] +* Honors configured base path when logging out {kib-pull}50946[#50946] +SIEM:: +* Fixes Empty `Source` / `Destination` shown when only ports are populated {kib-pull}50843[#50843] +* Removes placeholder from pinned event tooltips {kib-pull}52361[#52361] +* Adds filter feature and fixes misc bugs around false values {kib-pull}50999[#50999] +* Fixes a bug to allow empty query string when filters are set {kib-pull}51398[#51398] +* Adds signal to ECS event.kind and fixes status in signals {kib-pull}51772[#51772] +Uptime:: +* Removes react-router-dom warning in browse {kib-pull}52008[#52008] +* Fixes broken functional tests in `master` {kib-pull}54395[#54395] +* Donut chart loader position centered vertically {kib-pull}50219[#50219] +* Fixes monitor list pagination arrows {kib-pull}51912[#51912] +* Expanded list update most recent error timestamp {kib-pull}51935[#51935] +* Feature/monitor details view avoid empty column {kib-pull}51892[#51892] +* Feature/expandable row in details ping list {kib-pull}51890[#51890] +* Date picker will use commonly used ranges from advance settings {kib-pull}52944[#52944] +* Fixes broken Duration chart on Monitor Page {kib-pull}54251[#54251] +* Ping List Disable expand row if no body present {kib-pull}54898[#54898] +* Fixes Date Range picker stop refresh button {kib-pull}55499[#55499] +* Ping histogram uses auto date histogram {kib-pull}55605[#55605] +* Uses dynamic index pattern in Uptime {kib-pull}55446[#55446] +* Refreshes absolute date ranges for Ping Histogram {kib-pull}56381[#56381] +Visualizations:: +* Adds domain fit option for 0 opacity TSVB line charts {kib-pull}54314[#54314] +* Adds default filename when exporting CSV {kib-pull}54003[#54003] +* Fixes height of CodeEditor - Safari {kib-pull}56050[#56050] +* Fixes missing labels on certain axes and label filter configurations {kib-pull}47563[#47563] +* Formats CSV properly {kib-pull}54127[#54127] +* Flags nested fields as non-aggregatable {kib-pull}51774[#51774] + +[float] +[[deprecation-7.6.0]] +=== Deprecations +Metrics:: +* Deprecates the override fields in settings {kib-pull}54206[#54206] +Security:: +* Additional validation for elasticsearch username {kib-pull}48247[#48247] + + +[[release-notes-7.5.2]] +== {kib} 7.5.2 + +See <>. + +[float] +[[bug-7.5.2]] +=== Bug fixes + +Console:: +* Handles double quote special case {kib-pull}54474[#54474] + +Dashboard, Discover, Visualize:: +* Fixes icon path in tutorial introduction {kib-pull}49684[#49684] +* Fixes filter pill label for filters with negated alias {kib-pull}50743[#50743] +* Adds domain fit option for 0 opacity TSVB line charts {kib-pull}54314[#54314] + +Machine Learning:: +* Corrects URL of the create job tips docs page {kib-pull}53576[#53576] + +Management:: +* {kib} 7.0.0 URL field formatter doesn't render relative hyperlinks properly {kib-pull}53789[#53789] +* Fixes index pattern without timefield filter application {kib-pull}54757[#54757] + +Maps:: +* Fixes regression that prevents maps telemetry from populating. Removes unneeded task manager logic {kib-pull}52834[#52834] + +Monitoring:: +* Adds error state for unstructured logs {kib-pull}53299[#53299] +* Ensures setup mode works in a ccs environment {kib-pull}54361[#54361] + +Security:: +* Fixes search field visibility on space selector screen {kib-pull}54115[#54115] +* Forces line break if username is a solid long string {kib-pull}50807[#50807] + +[float] +[[regression-7.5.2]] +=== Regression +Watcher:: +* Passes termOrder and hasTermsAgg properties to serializeThresholdWatch function {kib-pull}54391[#54391] ++ +A regression was introduced into 7.5.0 that caused a particular configuration of Threshold Watches +to fail or erroneously trigger if they were created or edited in 7.5. If you've +created or edited a Threshold Watch with a "GROUPED OVER" condition set to `top` with {kib} 7.5.0, +you'll need to upgrade to a version of {kib} that contains this fix and recreate +these watches. ++ +The easiest way to do this is to go to the edit screen of the +Threshold Watch in the UI and simply click the *Save* button. This will recreate the +watch with the proper configuration. No other changes to the watch will be necessary on your part. ++ +[role="screenshot"] +image::images/rn_7.5.2.png[] + +[[release-notes-7.5.1]] +== {kib} 7.5.1 + +[float] +[[breaking-7.5.1]] +=== Breaking changes + +See <>. + +[float] +[[enhancement-7.5.1]] +=== Enhancements +Machine Learning:: +* Enables lat_long detector function in advanced wizard {kib-pull}50787[#50787] +* Truncates text in Overview page 'Latest timestamp' column {kib-pull}50004[#50004] +* Adds ML node warning to overview and analytics pages {kib-pull}50766[#50766] +Monitoring:: +* Refactors the enter setup mode button {kib-pull}51103[#51103] + +[float] +[[bug-7.5.1]] +=== Bug fixes +APM:: +* Fixes ACM to ensure more than 10 items are displayed {kib-pull}52262[#52262] +* Fixes watcher integration {kib-pull}51721[#51721] +Canvas:: +* Fixes axisConfig position argument UI {kib-pull}50717[#50717] +Discover:: +* Fixes histogram min interval {kib-pull}52758[#52758] +Machine Learning:: +* Fixes escape special characters for Lucene query language {kib-pull}50494[#50494] +* Fixes info content detector field selection {kib-pull}51914[#51914] +* Fixes word wrap in Overview page sidebar on IE {kib-pull}50668[#50668] +* Fixes lat_long anomalies table links menu and value formatting {kib-pull}50916[#50916] +* Fixes loading of data visualizer with KQL saved search {kib-pull}51882[#51882] +Maps:: +* Fixes a cross-site scripting (XSS) flaw in Coordinate and Region Map +visualizations. An attacker could create a malicious visualization that +executes JavaScript in a victim’s browser when the visualization, or dashboard +containing the visualization, was viewed. Since Kibana 7.0.0, Content Security +Policy (CSP), which prevents attackers from using this flaw, is enabled by +default. However, an attacker can still inject arbitrary HTML into the page. +See https://www.elastic.co/community/security/, CVE-2019-7621. +* Prevents users from overflowing URL when filtering by shape {kib-pull}50747[#50747] +* Delays vector tile layer syncing until spritesheet is loaded {kib-pull}48955[#48955] +* Sanitizes attribution {kib-pull}52309[#52309] +Monitoring:: +* Fixes Logstash pipelines page in multi-cluster environment {kib-pull}50166[#50166] +* Improves permissions required around setup mode {kib-pull}50421[#50421] +Operations:: +* Prevents xpack.task_manager.index being set to .tasks {kib-pull}52002[#52002] +* Fixes elasticsearch.ssl.alwaysPresentCertificate default {kib-pull}52242[#52242] +Querying & Filtering:: +* Fixes operator overflowing out popover {kib-pull}50030[#50030] +Uptime:: +* Removes react-router-dom warning in browse {kib-pull}52008[#52008] +Lens:: +* Shows keyword fields for pre-7.3 index patterns {kib-pull}52410[#52410] + +[[release-notes-7.5.0]] +== {kib} 7.5.0 + +[float] +[[breaking-7.5.0]] +=== Breaking changes +See also <>. + +Code:: +* Removes experimental code app {kib-pull}49404[#49404] +Platform:: +* Default to _search instead of _msearch in courier {kib-pull}45174[#45174] + +[float] +[[enhancement-7.5.0]] +=== Enhancements +APM:: +* More descriptive page titles {kib-pull}44296[#44296] +* Removes 0 suffix if array contains only one element {kib-pull}47036[#47036] +* Changing status code colors on trace summary {kib-pull}47114[#47114] +* Shows `span.http.response.status_code` and `span.http` object in Span details flyout {kib-pull}47322[#47322] +* Metadata sections should show message when no data is available {kib-pull}47842[#47842] +* Removes rest_total_hits_as_int and changing hits.total type {kib-pull}47814[#47814] +* Consistent flyout headers {kib-pull}46312[#46312] +* Always show transaction breakdown {kib-pull}46684[#46684] +* JVM List view & JVM metrics page {kib-pull}46779[#46779] +* Garbage collection metrics charts {kib-pull}47023[#47023] +* Replaces ui/kfetch with core.http {kib-pull}47635[#47635] +* One-line trace summary {kib-pull}44842[#44842] +* Documentation and alignment for impact column {kib-pull}47602[#47602] +* Keywords to select legend color in TPM graph {kib-pull}47628[#47628] +* Updates index pattern {kib-pull}48066[#48066] +* Increases breadcrumb `max` setting {kib-pull}46595[#46595] +* Agent configuration GA {kib-pull}46995[#46995] +Canvas:: +* Adds ability to share workpads in other websites {kib-pull}46278[#46278] +Discover:: +* Updates filter of fields UX allowing user to select and remove fields {kib-pull}47847[#47847] +* Shows field type name when hovering over them (#35391) {kib-pull}44208[#44208] +* De-angularize index pattern selection {kib-pull}46347[#46347] +* De-angularize side bar search field {kib-pull}46679[#46679] +* Replaces Discover chart with elastic-charts {kib-pull}43788[#43788] +Graph:: +* Removes the current inline-save menu from Graph and switches to a save modal as used in Visualize and Discover {kib-pull}44261[#44261] +* Settings EUI-ification {kib-pull}44587[#44587] +* EUI-ification of search bar {kib-pull}45351[#45351] +* Kql support for query bar {kib-pull}45364[#45364] +* Moves the field manager to react and EUI {kib-pull}45384[#45384] +* Empty workspace overlay {kib-pull}45547[#45547] +Logs:: +* Adapt log entry rate data visualizations {kib-pull}47558[#47558] +* Ensures 'unknown' setupStatus is handled {kib-pull}45887[#45887] +* Adds "Analyze in ML" buttons {kib-pull}48268[#48268] +* Changes 'View monitor status' to 'View status in Uptime' {kib-pull}44518[#44518] +* Improves live streaming behavior when scrolling {kib-pull}44923[#44923] +Machine Learning:: +* Enhances job id error message {kib-pull}45349[#45349] +* Severity cell with multi-bucket impact support {kib-pull}46002[#46002] +* Link to calendar settings from a job config {kib-pull}46141[#46141] +* Adds missing tooltips to Anomaly Explorer swimlane labels {kib-pull}46324[#46324] +* Custom urls enhancements {kib-pull}46433[#46433] +* Job type page {kib-pull}46933[#46933] +* Converts index and saved search selection to React {kib-pull}47117[#47117] +* Converts Recognizer job page to React {kib-pull}47429[#47429] +* Enhances created_by check for custom rules {kib-pull}47825[#47825] +* Checks unsaved changes for Job edit form {kib-pull}47926[#47926] +* Renders Custom URL as textarea on focus {kib-pull}48077[#48077] +* Adds advanced job wizard {kib-pull}46781[#46781] +* Reorganizes ML navigation with top and sub level tabs {kib-pull}45220[#45220] +* Overview tab for ML {kib-pull}45864[#45864] +* Regression creation and results view {kib-pull}48159[#48159] +* Displays MSE and rSquared in expanded row {kib-pull}48261[#48261] +* Moves ML "Data Frame Transforms" to Kibana management section "Transforms". {kib-pull}45880[#45880] +* Adds new SIEM auditbeat, winlogbeat and packetbeat modules {kib-pull}47848[#47848] +Management:: +* SLM retention UI {kib-pull}45193[#45193] +* Adds ability to execute snapshot retention manually {kib-pull}47150[#47150] +* Adds request flyouts to JSON watch form and Threshold Watch edit form {kib-pull}43232[#43232] +* SQL template with triple quote in completion {kib-pull}45248[#45248] +* Updates indentation behavior {kib-pull}45249[#45249] +* Adds IP, number, and boolean types to the static lookup field formatter {kib-pull}45585[#45585] +* Adds width and height as parameters to image url {kib-pull}46917[#46917] +* Integrates inside Template UI {kib-pull}47567[#47567] +* Adds json editor to edit field settings {kib-pull}47674[#47674] +* Console to NP ready {kib-pull}43346[#43346] +Maps:: +* Uses EuiPopover instead of mapbox tooltip {kib-pull}45938[#45938] +* Cancels SearchSource fetches that are no longer needed {kib-pull}44436[#44436] +* Provides isLoading and hasError feedback when legend is collapsed {kib-pull}47157[#47157] +* Uses pre-indexed shapes in shape filters when shape is stored in Elasticsearch {kib-pull}47171[#47171] +* Moves sort out of top hits configuration for ES documents source {kib-pull}47361[#47361] +* Provides drag-n-drop support to order tooltip properties {kib-pull}46631[#46631] +* Retrieves geo_point value from docvalue_fields instead of _source {kib-pull}47389[#47389] +* Increases tooltip max width and move feature pagination controls to top of tooltip {kib-pull}47645[#47645] +* Use field formatter to format value in legend {kib-pull}48132[#48132] +* Adds support for date fields in dynamic styles {kib-pull}47903[#47903] +* Use vector tiles for rendering EMS basemap {kib-pull}47867[#47867] +Metrics:: +* Adds bar chart option to Metrics Explorer {kib-pull}43728[#43728] +* Displays non-metric details on Node Detail page {kib-pull}43551[#43551] +* Adds Docker section to node details page {kib-pull}43627[#43627] +* Adds saved queries to maps {kib-pull}44442[#44442] +* Save and Load Views for Metrics Explorer and Inventory Page {kib-pull}46713[#46713] +* Converts button group to toggle. Refactor code structure for scalability {kib-pull}47083[#47083] +* Always display loading indicator when new data is loading {kib-pull}48038[#48038] +Monitoring:: +* Moves to OSS {kib-pull}45769[#45769] +* Metricbeat Migration Wizard {kib-pull}45799[#45799] +* Adds I/O metrics for Elasticsearch {kib-pull}45870[#45870] +Platform:: +* Moves highlight_html.js {kib-pull}45372[#45372] +* Moves as_pretty_string.js {kib-pull}45356[#45356] +* Timelion {kib-pull}44039[#44039] +* Adds url-param-decode to transform in string field {kib-pull}25694[#25694] +* Migrates field format utils to TS {kib-pull}47124[#47124] +Reporting:: +* Improves logging of doc-update events {kib-pull}45077[#45077] +* Removes Chrome stdout/stderr observables, Add Browser Logger observable {kib-pull}44359[#44359] +* Adds step to skip telemetry {kib-pull}48312[#48312] +SIEM:: +* Endgame events on the SIEM Overview page {kib-pull}47774[#47774] +* Endgame Row Renderers: DNS, File (FIM), Network, Security (Authentication), Process {kib-pull}48277[#48277] +* Adds events histogram {kib-pull}45403[#45403] +* Adds TLS to Network overview page {kib-pull}48062[#48062] +* Changed job links have the job configuration in the search when the user clicks on them {kib-pull}46084[#46084] +* Adds custom tooltip to map for dragging fields to timeline {kib-pull}46879[#46879] +* Show all SIEM ML Jobs in Anomaly Detection UI by default {kib-pull}48067[#48067] +* Updates Network Map layer styles {kib-pull}48284[#48284] +* Inspect tests {kib-pull}45833[#45833] +* Source/Destination Ip Table on Ip Details {kib-pull}47608[#47608] +* Op countries by source/dest tables {kib-pull}48179[#48179] +* Optimizes all hosts query {kib-pull}49409[#49409] +* Adds saved query in SIEM solution {kib-pull}47306[#47306] +Security:: +* Adds API Keys app to Management > Security {kib-pull}45740[#45740] +* Custom space avatar images {kib-pull}45148[#45148] +* Allows sorting on user/roles 'reserved' column {kib-pull}46283[#46283] +* Supports space-specific default routes {kib-pull}44678[#44678] +* Preserves URL fragment during SAML handshake {kib-pull}44513[#44513] +Stack services:: +* Adds opt-in to telemetry by default {kib-pull}50490[#50490] +* Updates telemetry banner prompt behavior {kib-pull}49644[#49644] +* Adds data privacy notice text to welcome screen with link to opt-out of telemetry {kib-pull}50189[#50189] +* Provides telemetry on opt-in status {kib-pull}50158[#50158] +* Adds configureable server side telemetry {kib-pull}50015[#50015] +* Adds kibana.yml configurations for telemetry default status and UI behavior {kib-pull}49798[#49798] +* Adds Ask Elastic and Give feedback links to help section {kib-pull}49797[#49797] +* Adds newsfeed {kib-pull}49579[#49579] +Uptime:: +* Query Overhaul + Pagination {kib-pull}42933[#42933] +* Adds certificate expiration dates to uptime GQL schema {kib-pull}43352[#43352] +* Adds TLS cert expiry to GQL schema for individual docs {kib-pull}44506[#44506] +* Adds Kuery Bar {kib-pull}43621[#43621] +* Duration chart gaps {kib-pull}45734[#45734] +* Adds zero monitors down heading {kib-pull}48257[#48257] +* Updates pings chart colors {kib-pull}46780[#46780] +Visualizations:: +* Replaces TSVB timeseries charts with elastic-charts {kib-pull}33558[#33558] +* Adds percentile and median aggregations for timestamp fields {kib-pull}46477[#46477] +* Adds gte and lt symbols in range filter fields and tooltip {kib-pull}46697[#46697] +* Don't use placeholder visualization name {kib-pull}46719[#46719] +* Adds Lens visualization editor {kib-pull}36437[#36437] + +[float] +[[bug-7.5.0]] +=== Bug fixes +APM:: +* Widen filter used in logs link {kib-pull}46252[#46252] +* Correctly plurarlize view in discover link {kib-pull}47618[#47618] +* Log stacktrace comes from _.error.log and not _error.exception[0] {kib-pull}48185[#48185] +Canvas:: +* Improves Canvas controls accessibility {kib-pull}48005[#48005] +Dashboard:: +* Improve dashboard filters display to use color as well as text for negated filters {kib-pull}49939[#49939] +Discover:: +* Add numeric_type option for correct sort order on mixed date and date_nanos fields {kib-pull}44212[#44212] +* Fix Maximum call stack size exceeded warnings {kib-pull}47829[#47829] +* Convert value provided to PhraseValueInput to string to prevent Exception with numeric values {kib-pull}45259[#45259] +* Remove redundant request to fetch index patterns {kib-pull}44998[#44998] +* Allow filter editor to open when selectedField is undefined {kib-pull}45402[#45402] +Graph:: +* Do not carry over diversity field when switching data source {kib-pull}47560[#47560] +Logs:: +* Use theme colors for the timeline background {kib-pull}46213[#46213] +* Address non-blocking nature of job deletion ML API {kib-pull}46040[#46040] +* Fix ML link for "unknown" partition {kib-pull}48779[#48779] +* Use full time range for the x-axis domain {kib-pull}48754[#48754] +* Fix initial accuracy of logs minimap click {kib-pull}48826[#48826] +Logstash:: +* Remove formatted message component in favor of i18n translate function {kib-pull}45658[#45658] +Machine Learning:: +* Set y-axis domain of the Single Metric Viewer according to the model plot {kib-pull}48411[#48411] +* Fix partitioning field value update {kib-pull}48655[#48655] +* Update Anomaly Explorer and SMV on the "Refresh" button click {kib-pull}48773[#48773] +* Overview Page - follow-ups {kib-pull}47637[#47637] +* Adds missing links to ML plugin from ML Analytics job list in Management app {kib-pull}48432[#48432] +* Ensure proper permissions check for empty prompt 'Create job' buttons {kib-pull}49067[#49067] +* Fixes reselection of same Anomaly Explorer swimlane cell {kib-pull}48626[#48626] +* Fix Group By and Aggregations validation in Transforms wizard {kib-pull}48514[#48514] +* Fix Transform pivot documentation link {kib-pull}48522[#48522] +* Show MSE and rSquared in expanded row only for regression jobs {kib-pull}48390[#48390] +* Fix custom results_field and prediction_field_name not considered in eval config {kib-pull}48599[#48599] +* Check source index contains numerical fields only once it has been selected {kib-pull}48843[#48843] +* Fix analytics source index selection {kib-pull}48731[#48731] +* Fix code editor console error {kib-pull}49193[#49193] +Management:: +* Migrate Console to use Node http instead of Hapi to support GET requests with bodies {kib-pull}46200[#46200] +* Fix leaky mappings subscription {kib-pull}45646[#45646] +* Fix Safari layout issue {kib-pull}47100[#47100] +* Fix stale value in editor shortcut command {kib-pull}48484[#48484] +* Fix disco filters #2 {kib-pull}50061[#50061] +Maps:: +* Parse geojson files in chunks to avoid thread blocking {kib-pull}46710[#46710] +* Fix adding filters in map embeddable {kib-pull}45187[#45187] +* Avoid resizing tooltip while loading next feature during pagination {kib-pull}47517[#47517] +* Clean features in locked tooltip after re-fetch {kib-pull}48016[#48016] +* Properly handle id collisions in {kib} index pattern {kib-pull}48594[#48594] +* Fix propType warnings for source with joins {kib-pull}48905[#48905] +* Ensure grid buckets are rendered correctly at high zoom levels {kib-pull}44421[#44421] +Metrics:: +* Tweak the z-index inventory toolbars {kib-pull}49642[#49642] +* Convert node detail page time range to date strings {kib-pull}43881[#43881] +* Add legends and points to charts on node detail page {kib-pull}43787[#43787] +* Limit Metric Explorer fields {kib-pull}43322[#43322] +* Create robust ID for contextual menus for inventory view {kib-pull}46358[#46358] +* Remove points from charts on Metrics Explorer and Detail Page {kib-pull}49500[#49500] +* Make sure that filter query bar can be set to null {kib-pull}50070[#50070] +* Use URL /infrastructure/metrics instead of /metrics {kib-pull}44532[#44532] +Monitoring:: +* Ensure cloud cannot see setup mode {kib-pull}49223[#49223] +* Standarize on 'JVM Heap' phrase for heap metrics {kib-pull}48093[#48093] +* Added resize listener after handler was created {kib-pull}49452[#49452] +Operations:: +* Use older systemd StartLimitInterval {kib-pull}47909[#47909] +* Variety of quick a11y fixes {kib-pull}46569[#46569] +* Main and nav landmark a11y fixes {kib-pull}48381[#48381] +* SearchSource: Fix docvalue_fields and fields intersection logic {kib-pull}46724[#46724] +Platform:: +* Time range per panel design fixes {kib-pull}46630[#46630] +* Use custom deep merging strategy on createCluster {kib-pull}48836[#48836] +* Honor current search criteria when exporting saved objects {kib-pull}47223[#47223] +* Allow plugins to register top nav menu items (regression fix) {kib-pull}48542[#48542] +* Index Pattern Date formatter - fixing sample data display {kib-pull}48259[#48259] +* Read warning to screen readers for duplicate saved objects {kib-pull}47568[#47568] +* Ignore missing references on saved object exports {kib-pull}47685[#47685] +* Kibana should start without task manager {kib-pull}48568[#48568] +* Fixes issue where query bar reverts changes on save if it hasn't been submitted {kib-pull}47908[#47908] +* Add event.dataset to sample web logs {kib-pull}48150[#48150] +Reporting:: +* Data read/write failures are error logs {kib-pull}45478[#45478] +* Cut down payload of _getPendingJobs query {kib-pull}47768[#47768] +* Fix Generating Reports with long `jobParams` RISON {kib-pull}45603[#45603] +SIEM:: +* Fix incorrect inspected query for kpi network {kib-pull}49695[#49695] +* Filter out "loading" from Panel to make it more React performant {kib-pull}46258[#46258] +* Start of deprecated lifecycle refactor {kib-pull}46293[#46293] +* Show getting started page on empty string or _all {kib-pull}47166[#47166] +* Top Countries network page tab change; fix column heading bug {kib-pull}48526[#48526] +* Events Histogram add time_zone argument to match Events Table {kib-pull}48821[#48821] +* Fields browser, auto selects category bugfix {kib-pull}48999[#48999] +* Fix bug that fails to match index patterns with leading wildcard {kib-pull}49735[#49735] +* Fix Firefox focus state in SIEM tab_navigation {kib-pull}45996[#45996] +* Fix AnomaliesNetworkTable and AnomaliesHostTable items count {kib-pull}48634[#48634] +Security:: +* Removes `<form>` tag that was breaking the EuiComboBox's enter key {kib-pull}48184[#48184] +* GUI enhancement: ability to sort the spaces table {kib-pull}46421[#46421] +Uptime:: +* Added aria label description for ping over time chart {kib-pull}46689[#46689] +* Use EuiSelect instead of ComboBox for ping history {kib-pull}49700[#49700] +* Handle filter dropdown button click {kib-pull}48650[#48650] +* Do not drop edge buckets {kib-pull}48157[#48157] +* Fix chart wrapping for monitor page {kib-pull}49268[#49268] +* Add different request lib to `telemetry_analytics` in place of `$http` {kib-pull}49671[#49671] +* Remove potential for flaky snapshot comparison in unit test {kib-pull}49928[#49928] +* Revert router base name for Uptime plugin {kib-pull}50095[#50095] +* Section headline should be inside panel {kib-pull}43468[#43468] +* Removed extra slash from integration urls {kib-pull}44469[#44469] +* Align uptime help menu with other apps {kib-pull}44536[#44536] +* App page title {kib-pull}44818[#44818] +* Show permission warning if no right for uptime {kib-pull}44968[#44968] +* Integration popup closes after refresh {kib-pull}45759[#45759] +* Make uptime filters responsive {kib-pull}46560[#46560] +* Update monitor list table description by adding aria-label for accessibility {kib-pull}46696[#46696] +* Change default status filter in ping list to all on monitor page {kib-pull}47108[#47108] +* Disable filter and Add link to location docs when no location exists {kib-pull}49175[#49175] +Visualizations:: +* Unable to deal with negative values {kib-pull}43581[#43581] +* Use correct color for circles in line chart {kib-pull}47715[#47715] +* Fix infinite loop in vega tooltips {kib-pull}47700[#47700] +* Improve error handling {kib-pull}47958[#47958] +* Show correct value in legend for step charts {kib-pull}47863[#47863] +* Input controls does not reset top level controls after clear {kib-pull}47937[#47937] +* Look up axis format from series instead of using default formatter {kib-pull}47696[#47696] +* Pass raw values and format afterwards {kib-pull}48090[#48090] + +[float] +[[deprecation-7.5.0]] +=== Deprecations +Discover:: +* De-angularize sidebar fields {kib-pull}47559[#47559] +Visualizations:: +* Deprecate scale metrics behavior {kib-pull}47599[#47599] + +[[release-notes-7.4.2]] +== {kib} 7.4.2 + +Also see <>. + +[float] +[[bug-7.4.2]] +=== Bug fix +Discover:: +* Fixes missing HTML formatting in Doc_Viewer {kib-pull}49326[#49326] +* Fixes the URL field formatter {kib-pull}46332[#46332] +Visualizations:: +* Fixes the loss of filters in TSVB after upgrade from 7.2 to 7.3 {kib-pull}48710[#48710] + + +[[release-notes-7.4.1]] +== {kib} 7.4.1 + +See also <>. + + +[float] +[[enhancement-7.4.1]] +=== Enhancements +Monitoring:: +* Server side pagination for ES Nodes listing table {kib-pull}47224[#47224] +[float] +[[bug-7.4.1]] +=== Bug fixes +Canvas:: +* Fixes workpad fullscreen view due to max-width limitation {kib-pull}47371[#47371] +Infrastructure:: +* Loads initial page state into the URL when empty for Metrics Explorer {kib-pull}45683[#45683] +* Removes internal Hapi request for `makeTSVBRequest` {kib-pull}45598[#45598] +Machine Learning:: +* Fixes selection of dedicated index when cloning job {kib-pull}46486[#46486] +* Fixes job clone time range auto selection {kib-pull}46582[#46582] +* Enables wizard start real time button only when job is closed {kib-pull}46127[#46127] +* Adds listener for time filter refresh to data visualizer {kib-pull}46708[#46708] +* Fixes view examples link in anomalies table {kib-pull}47954[#47954] +* Data Frame Analytics: Fixes permissions check {kib-pull}46110[#46110] +Management:: +* ILM: Deletes `min_age` field if warm phase on rollover is enabled {kib-pull}45412[#45412] +* Console: Fixes actions menu alignment {kib-pull}47227[#47227] +Monitoring:: +* Ensures all charts use the configured timezone {kib-pull}45949[#45949] +* Uses server side pagination for Logstash Pipelines page {kib-pull}46587[#46587] +* Fixes time filter woes {kib-pull}47486[#47486] +* Allows `isCollectionEnabledUpdated` to hang until data is available {kib-pull}46279[#46279] +Platform:: +* Fixes issue with `saved_objects` API overwriting saved object references if not specified {kib-pull}47248[#47248] +Reporting:: +* Fixes ESQueue worker error logging {kib-pull}46308[#46308] +* Fixes functionality of "Download CSV" from a Saved Search panel in a Dashboard {kib-pull}47891[#47891] +SIEM:: +* Fixes map global refresh when the time filter is set to an absolute value {kib-pull}47426[#47426] +Security:: +* Makes sure all URLs are relative on intake and execute {kib-pull}46528[#46528] +* Spaces: Fixes `SecureSpaceMessage` visibility {kib-pull}44829[#44829] +Uptime:: +* Fixes empty name filter {kib-pull}46962[#46962] +* Fixes jerky monitor list expanded row behavior {kib-pull}47080[#47080] + +[[release-notes-7.4.0]] +== {kib} 7.4.0 + +[float] +[[breaking-7.4.0]] +=== Breaking Changes +See also <>. + +Platform:: +* Use search instead of msearch when batching is disabled in courier {kib-pull}43923[#43923] + +[float] +[[enhancement-7.4.0]] +=== Enhancements +APM:: +* Surface http errors to users {kib-pull}42160[#42160] +* Transaction duration chart always shows duration in `ms` {kib-pull}42375[#42375] +* Use rounded bucket sizes for transaction distribution {kib-pull}42830[#42830] +* Show loading state on waterfall and avoid re-fetching distribution chart when changing bucket {kib-pull}44093[#44093] +* Make number of x ticks responsive to the plot width {kib-pull}44870[#44870] +* Persist table parameters to URL {kib-pull}39912[#39912] +* Local UI filters {kib-pull}41588[#41588] +* Use transaction indices to create ML job {kib-pull}43750[#43750] +* Update query input when url changes {kib-pull}43773[#43773] +* Only show "Clear filters" button when values are not empty {kib-pull}43967[#43967] +Canvas:: +* Format argument for the metric element {kib-pull}42007[#42007] +* Query default index when index is unspecified {kib-pull}41515[#41515] +* Added formatnumber and formatdate UIs to sidebar {kib-pull}43059[#43059] +* Add Monaco to the Canvas Expression Editor {kib-pull}41790[#41790] +Dashboard:: +* Reset dirty saved query on reload {kib-pull}43927[#43927] +Design:: +* Add {kib} App specific URL to the help menu (#34739) {kib-pull}42580[#42580] +Discover:: +* Add advanced setting to turn off search on Discover's initial page load {kib-pull}42036[#42036] +* Allow sorting on multiple columns in Discover {kib-pull}41918[#41918] +* Add icon for geo_shape fields in Discover {kib-pull}42087[#42087] +Infrastructure:: +* Add UI to customize Metrics Explorer chart style {kib-pull}41022[#41022] +* Add cloud metrics and cloud/host info to metadata endpoint {kib-pull}41836[#41836] +* Add APM to Metadata Endpoint {kib-pull}42197[#42197] +* Add AWS metrics to node detail page {kib-pull}42153[#42153] +* Clarify confusing message about time period {kib-pull}44168[#44168] +Logs:: +* Allow for jumping to the previous and next highlight {kib-pull}40010[#40010] +* Show highlighted log entries in the minimap {kib-pull}40745[#40745] +* Add a time cursor to the log minimap {kib-pull}39538[#39538] +* Make column configurations reorderable {kib-pull}41035[#41035] +* Add link from the sample web logs to the Logs UI {kib-pull}42635[#42635] +* Allow dragging of the log minimap to change visible logs {kib-pull}40092[#40092] + +Machine Learning:: +* Cards as links {kib-pull}45254[#45254] +* Adding datafeed timing stats to Job Management list {kib-pull}40993[#40993] +* Relaxing index pattern restriction on module setup {kib-pull}42619[#42619] +* Adding job overrides to the module setup endpoint {kib-pull}42946[#42946] +* Search bar on list page {kib-pull}41415[#41415] +* KQL bar for querying source data in creation wizard {kib-pull}41779[#41779] +* Creation wizard editor for source config {kib-pull}41937[#41937] +* {kib} management jobs list {kib-pull}42570[#42570] +* Adds Transform Analytics list to {kib} management {kib-pull}43151[#43151] +* Ensure proper title, tagline, and link to documentation {kib-pull}43418[#43418] +* DataFrame bulk actions {kib-pull}43331[#43331] +* Data Frames Summary Stats Bar {kib-pull}43986[#43986] +* Transform UI updates {kib-pull}44175[#44175] +* Converts index based data visualizer to React {kib-pull}42685[#42685] +* Enables cell range selection. {kib-pull}44066[#44066] +* Analytics jobs list. {kib-pull}42598[#42598] +* Analytics job creation. {kib-pull}43102[#43102] +* Outlier detection results page {kib-pull}43578[#43578] +* Advanced editor. {kib-pull}43989[#43989] +Management:: +* Index Templates UI list view {kib-pull}39922[#39922] +* Index Templates UI details view {kib-pull}41602[#41602] +* Index templates form wizard {kib-pull}42457[#42457] +* Show endpoint in JSON preview of index lifecycle policy editor. {kib-pull}42791[#42791] +* Add API endpoint to Rollup Job JSON summary. {kib-pull}42789[#42789] +* Add request flyout to Remote Clusters. {kib-pull}42900[#42900] +* Show requests for creating a follower index and creating/updating an auto-follow pattern in CCR. {kib-pull}42924[#42924] +* Option to start rollup job right after it gets created {kib-pull}41573[#41573] +* Clone an existing rollup job {kib-pull}41891[#41891] +* Metrics multiple selection {kib-pull}42927[#42927] +* Add SLM policies list and detail views {kib-pull}41302[#41302] +* Sorts the indexPatternDateFields which are listed in the date field dropdown on Date Histogram Step {kib-pull}41853[#41853] +* Delete and execute SLM policies {kib-pull}41934[#41934] +* SLM create and edit policies {kib-pull}43390[#43390] +* Form validation errors announce themself {kib-pull}39656[#39656] +* Switch default decimal places to 1 {kib-pull}43785[#43785] +* Add custom formatting for Date Nanos Format {kib-pull}42445[#42445] +Maps:: +* Change border color to be darker version of fill color {kib-pull}43211[#43211] +* Add attribution handling for TMS (config & UI-entry) and WMS {kib-pull}44147[#44147] +* Make default EMS tile layer auto select light or dark tiles based on isDark mode advanced setting {kib-pull}40892[#40892] +* Add filter bar to maps application {kib-pull}42756[#42756] +* Filter by shape {kib-pull}43141[#43141] +* Custom color ramp {kib-pull}41603[#41603] +* Add indicator when layer is filtered by search bar {kib-pull}43283[#43283] +* Add cancel draw button and draw instructions {kib-pull}43593[#43593] +* Pew pew source {kib-pull}41504[#41504] +* Load Maki icons from spritesheet {kib-pull}42499[#42499] +* Enable borders for icon symbols {kib-pull}43066[#43066] +* Provide indication in LayerTOC when results are incomplete {kib-pull}41271[#41271] +* Use EMS vector tiles {kib-pull}42846[#42846] +Monitoring:: +* Update APM metric titles {kib-pull}44091[#44091] +Platform:: +* Feature/default enable csv dashboard {kib-pull}44048[#44048] +* Chore/bump chromium webgl+kerberos {kib-pull}42751[#42751] +* Cancel visualize fetches when navigating away or re-fetching {kib-pull}42035[#42035] +* Ability to enable and disable alerts {kib-pull}40543[#40543] +* Per panel time range {kib-pull}43153[#43153] +* Promote many `debug` log events to `info` {kib-pull}43241[#43241] +* Instantiate a logger top level, and use it throughout the job {kib-pull}43636[#43636] +* Add capture.maxAttempts setting {kib-pull}44011[#44011] +Queries:: +* Implement saved queries and filters {kib-pull}39140[#39140] +Reporting:: +* Rewrite telemetry collection to use a single query {kib-pull}34327[#34327] +* Truncate base64 urls in logs {kib-pull}41304[#41304] +* Sanitize 409 error log message {kib-pull}42495[#42495] +Security:: +* PKI authentication in Kibana via Elasticsearch PKI realm {kib-pull}42606[#42606] +* OIDC authentication now supports the implicit flow {kib-pull}42069[#42069] +* Telemetry for csp configuration {kib-pull}43223[#43223] +* Copy Saved Objects to Spaces UI {kib-pull}39002[#39002] +* Allow for custom cluster privileges {kib-pull}43817[#43817] +SIEM:: +* Customizable columns, row renderers, and expandable events in the `Events` widget {kib-pull}44324[#44324] +* Adds events and Timeline Style / ID Updates {kib-pull}44965[#44965] +* Applies highlighting to the Timeline data providers drop area and flyout button {kib-pull}45173[#45173] +* Sets page titles to the current page you are on {kib-pull}42157[#42157] +* Update date picker after brush selection on charts {kib-pull}42440[#42440] +* Upgrades react-redux and utilize React.memo for performance gains {kib-pull}43029[#43029] +* Changes network to use ECS fields {kib-pull}44392[#44392] +* Adds a configuraton option for the default SIEM date time range {kib-pull}44540[#44540] +* Fixes the columns to not show duplicate information when on detail pages. {kib-pull}45031[#45031] +* Adds process_started ECS fields to Uncommon Process Table {kib-pull}45664[#45664] +* Adds Connections (Pewpew) Map to Network Page {kib-pull}43965[#43965] +* Adds telemetry for ML functionality {kib-pull}43926[#43926] +* Adds new jobs for SIEM ML Integration {kib-pull}44301[#44301] +* Moves installation of jobs from initial page load to opening of Anomaly Detection UI {kib-pull}45536[#45536] +* Adding new jobs to siem module {kib-pull}43783[#43783] +* Changes table widget loading to elastic user interface's loading content {kib-pull}41596[#41596] +* Changes hosts and network tables from load more to paginated {kib-pull}41532[#41532] +* Uses autonomous_system as new ECS field {kib-pull}43925[#43925] +* Makes ip details heading draggable {kib-pull}45179[#45179] +* Split into Source and Destination {kib-pull}43719[#43719] +* Inject/apply KQL changed in refresh button {kib-pull}45065[#45065] +* Improves the timeline performance by optimizing the width, removing wasted renderers, and adding a visibility sensor {kib-pull}43560[#43560] +Uptime:: +* Improve `useUrlParams` hook for Uptime app {kib-pull}41545[#41545] +Visualizations:: +* Introducing Timerange Data Mode for TSVB Metric Style Visualizations {kib-pull}37185[#37185] +* Allow other apps to list their custom visualizations in the Visualize app {kib-pull}43386[#43386] +* Threshold line on bar/line/area charts {kib-pull}42632[#42632] +* Adds capability to show percentages for data table columns {kib-pull}39572[#39572] + +[float] +[[bug-7.4.0]] +=== Bug fixes +APM:: +* Avoid APM failing to start when ml is disabled {kib-pull}42815[#42815] +* Fix missing RUM url {kib-pull}42940[#42940] +* Correctly pass service language for syntax highlighting {kib-pull}43771[#43771] +* Make sure histogram is responsive when resizing window {kib-pull}43759[#43759] +* Don't hide all legends if user has hidden one {kib-pull}43667[#43667] +* Fill in vertical gaps in breakdown metrics data {kib-pull}43663[#43663] +* Display all errors in child transactions/spans in trace overview {kib-pull}44274[#44274] +* Fix indefinite loading state in agent settings for unauthorized user roles {kib-pull}44970[#44970] +Canvas:: +* Adds support for uppercase cluster names in esdocs and other datasource bug fixes {kib-pull}44311[#44311] +Dashboard:: +* No reload on changes to disabled filters in dashboard {kib-pull}41144[#41144] +* Update assumption that panelIndex may be missing {kib-pull}44793[#44793] +Design:: +* Update heading hierarchy for instructions {kib-pull}41970[#41970] +Discover:: +* Fix TypeError at Discover's context view {kib-pull}43661[#43661] +Filters:: +* Fix truncation of long filter bar items {kib-pull}43874[#43874] +* Keep disabled state on filter edit {kib-pull}42346[#42346] +* Put filters back in the filter context where they belong {kib-pull}42095[#42095] +Graph:: +* Replace all occurences of placeholder in drilldown URL template {kib-pull}41673[#41673] +Infrastructure:: +* Replace EUI Charts with Elastic Charts on node detail page {kib-pull}41262[#41262] +* Use {kib} date format for chart headers {kib-pull}41715[#41715] +* Change contextual menu position on infrastructure view {kib-pull}41810[#41810] +* Cleanup loading states for node detail page. {kib-pull}43311[#43311] +Logs UI:: +* Fix rendering of complex field column values {kib-pull}44906[#44906] +* Announce name of column on remove column button {kib-pull}41695[#41695] +* Sentence case copy changes {kib-pull}43215[#43215] +Machine Learning:: +* Allow zero delay for transforms wizard {kib-pull}45115[#45115] +* Fix jobs list loading when auto refresh is off {kib-pull}42076[#42076] +* Allow index patterns containing commas in recogniser modules {kib-pull}43686[#43686] +* File data viz limiting uploaded doc chunk size {kib-pull}44768[#44768] +* Fixing job management expanded rows in dark mode {kib-pull}45159[#45159] +* Adjusting module jobs model memory limit {kib-pull}45502[#45502] +* Ensure Anomaly Explorer chart label badge can be seen {kib-pull}44259[#44259] +* Fix {kib} management stats bar style {kib-pull}44658[#44658] +* Ensure preview table displays scripted fields and timestamps are formatted correctly. {kib-pull}44701[#44701] +* Enable data visualizer link on job types page for non-time index {kib-pull}44667[#44667] +* Fixes messages in data frame action request notifications {kib-pull}44872[#44872] +* Fixes JSON pane. {kib-pull}42816[#42816] +* Fix IE11 issue, update types. {kib-pull}43743[#43743] +* Fixes table sorting. {kib-pull}43859[#43859] +Management:: +* Fix rendering `undefined` from job status map {kib-pull}41438[#41438] +* Added doc_values to list of completion items for mapping {kib-pull}42581[#42581] +* Fix date_nanos formatting for formats without fractional seconds {kib-pull}43114[#43114] +Maps:: +* Reverse the attribution order so left-to-right order matches top-to-bottom {kib-pull}44415[#44415] +* Set complete on index pattern creation {kib-pull}44423[#44423] +* Unknown provider regionMapsConfigProvider {kib-pull}42821[#42821] +* Only color legend icon with dynamic color when dynamic config is complete {kib-pull}41607[#41607] +* Populate _id in tooltip {kib-pull}41684[#41684] +* Only show top hits checkbox if index has date fields {kib-pull}43056[#43056] +* Reposition tooltip when tooltip size changes {kib-pull}43152[#43152] +* Exclude index pattern from draw tools and shape filtering when layer ignores global filter {kib-pull}43380[#43380] +* Increase tooltip max width so create filter button not clipped {kib-pull}43602[#43602] +* Add i18n wrappers around missed text {kib-pull}43635[#43635] +* Only display fields contained in _source for Documents source term join left field options {kib-pull}44386[#44386] +* Fix side panel scrolling in safari {kib-pull}44700[#44700] +* Name space dynamic property style names to avoid collisions {kib-pull}44676[#44676] +* Unmount map embeddable component on destroy {kib-pull}45183[#45183] +* Set mapbox Popup maxWidth {kib-pull}45253[#45253] +Monitoring:: +* Ensure we pass down all the parameters for fetching logs {kib-pull}43869[#43869] +* Issue 25323: Fixed error catch and route handling v2 {kib-pull}44800[#44800] +* Respect xpack.monitoring.show_license_expiration {kib-pull}45537[#45537] +Operations:: +* Configurable global socket timeouts {kib-pull}31603[#31603] +* Only provide obsoleteIndexTemplatePattern to the default index migrator to avoid race conditions {kib-pull}42016[#42016] +Platform:: +* Modify I18nProvider so that it does not generate new React components {kib-pull}43556[#43556] +* Fix rawChecksums in chromium build and rename for clarity {kib-pull}44665[#44665] +* Resolve filter index references when importing saved objects {kib-pull}42974[#42974] +Queries:: +* Saved query requires title {kib-pull}45029[#45029] +* Save query form validation on blur {kib-pull}43726[#43726] +Reporting:: +* Fix Relative Date format in CSV export {kib-pull}40544[#40544] +* Fix TypeError with pending job info {kib-pull}43924[#43924] +* Use pipes for communication with chrome to avoid networking snafus {kib-pull}42097[#42097] +Security:: +* Allow for hex color codes that include uppercase characters {kib-pull}43470[#43470] +* Prevent space identifier url example from overflowing panel {kib-pull}44871[#44871] +SIEM:: +* Toggle Column / Code Coverage and Cypress {kib-pull}42766[#42766] +* Show all popover items / Timeline flyout button rendering {kib-pull}45745[#45745] +* Upgrade elastic charts library - v12.0.2 {kib-pull}45853[#45853] +* Adds performance enhancements such by removing wasted renderers and adding incremental DOM rendering {kib-pull}43157[#43157] +* Fixes the Suricata row renderer not being activated {kib-pull}44728[#44728] +* Changes ML conditional links to use tabs, fixes a small bug with null filterQuery {kib-pull}45218[#45218] +* Fixes index substring incorrectly matching configured indices and failing to install ML job {kib-pull}43409[#43409] +* Fix timeline/kql search disparity {kib-pull}42843[#42843] +* Formats the bytes columns in timeline {kib-pull}43147[#43147] +* Capitalizes SIEM in {kib} Advanced Settings {kib-pull}44886[#44886] +* Removes expensive global CSS calculations of resize handle {kib-pull}43898[#43898] +Uptime:: +* Encode Monitor Id React Router params to validate {kib-pull}43113[#43113] +* Context Menu Improved for integrations links in monitors list {kib-pull}43068[#43068] +* Update monitor list configs for mobile view {kib-pull}43218[#43218] +Visualizations:: +* No longer registering Timelion feature if it's disabled {kib-pull}42193[#42193] +* Fix Timelion color error when filtering data {kib-pull}23876[#23876] +* Fix truncated formatting on tooltip {kib-pull}41769[#41769] +* Ensure visualizations in percentage mode respect the advanced settings percent format {kib-pull}39044[#39044] +* Fix duplicate fetch in Visualize {kib-pull}41204[#41204] + + +[[release-notes-7.3.2]] +== {kib} 7.3.2 + +See also <>. + +[float] +[[bug-7.3.2]] +=== Bug fixes +Monitoring:: +* Ensures all the parameters for fetching logs are passed down {kib-pull}43869[#43869] + +SIEM:: +* Fixes the Suricata row renderer not being activated {kib-pull}44728[#44728] +* When adding the 2*nth note on an event, does not unpin it {kib-pull}44941[#44941] +* Fixes duplicate columns in timeline and the errors on multiple click on pinned event {kib-pull}44010[#44010] + +Security:: +* In Spaces, allows for hex color codes that include uppercase characters {kib-pull}43470[#43470] + +Platform:: +* Resolves filter index references when importing saved objects {kib-pull}42974[#42974] + + + +[[release-notes-7.3.1]] +== {kib} 7.3.1 + +[float] +[[breaking-7.3.1]] +=== Breaking Changes + +See also <>. + +Platform:: +* Fixes import API so it doesn't override SavedObjectClient errors {kib-pull}41125[#41125] + +[float] +[[bug-7.3.1]] +=== Bug fixes +APM:: +* Makes sure tooltips for metric charts are synced {kib-pull}42139[#42139] +Canvas:: +* Fixes IE11 fullscreen behavior to properly position workpad {kib-pull}42544[#42544] +Discover:: +* Fixes a bug where selecting a period in the discover histogram did not result in a refresh. {kib-pull}43097[#43097] +Filters:: +* Fixes Firefox continuously changing filter position order when +applying more than 1 filter. See https://github.com/elastic/kibana/issues/41567[issue #41567]. +Geo:: +* Moves Geojson deep clone logic to Elasticsearch, making Geojson +upload more stable when uploading large geometries. {kib-pull}41835[#41835] +* Fixes maps Geojson upload hanging on index step {kib-pull}42623[#42623] +* Formats doc-ids as strings {kib-pull}42011[#42011] +* Modifies Fit-to-data action to fit to all visible features, even ones +without a corresponding result in the join. {kib-pull}42020[#42020] +Infra Logs UI:: +* Fixes section mapping bug in node detail page {kib-pull}41641[#41641] +* Fixes autocomplete to use proper derived index pattern {kib-pull}42287[#42287] +Machine Learning:: +* Fixes basic license redirect {kib-pull}41876[#41876] +* Fixes file datavisualizer mapping overrides {kib-pull}42047[#42047] +* Fixes ml when spaces feature is disabled {kib-pull}42564[#42564] +* Fixes check for watcher being enabled {kib-pull}43025[#43025] +Management:: +* Removes validation for email action body attribute in Watcher {kib-pull}42009[#42009] +* Fixes minor Console regressions introduced during EUIfication. {kib-pull}41089[#41089] +* Fixes issue when removing scripted fields {kib-pull}42838[#42838] +Monitoring:: +* Only fetches a single cluster data instead of all clusters when possible {kib-pull}42469[#42469] +* Uses async/await pattern which should address weird bug {kib-pull}42876[#42876] +* Uses fixed_interval explicitly for date_histogram aggregations {kib-pull}37023[#37023] +Operations:: +* Overrides `org.label-schema.license` Docker label {kib-pull}42836[#42836] +Platform:: +* Fixes CSV export of saved searches that have _source field {kib-pull}43123[#43123] +* Correctly sets `kibanaRoot` on {kib} plugin helpers for new generated plugins {kib-pull}42616[#42616] +* Fixes scaling logic to check agg type instead schema {kib-pull}42574[#42574] +Reporting:: +* Fixes an issue in the Reporting jobs listing page that sometimes prevented it from rendering {kib-pull}42419[#42419] +Visualizations:: +* Fixes problem in TSVB when group by "Everything" fails to calculate data with "Overall" metrics {kib-pull}42074[#42074] +* Fixes error when filters agg filters are a query_string query {kib-pull}43310[#43310] +* Fixes tooltip text overflow {kib-pull}41703[#41703] + +[[release-notes-7.3.0]] +== {kib} 7.3.0 + +[float] +[[breaking-7.3.0]] +=== Breaking Changes + +See also <>. + +Machine Learning:: +* Data Frame: Remove format from date_histogram configs. {kib-pull}39811[#39811] +Maps:: +* [Fixes #34662] Hide feature when it has no corresponding term join {kib-pull}36617[#36617] + +[float] +[[enhancement-7.3.0]] +=== Enhancements +Canvas:: +* Add new dashboard template {kib-pull}37520[#37520] +* Keyboard shortcuts for nudging elements {kib-pull}39208[#39208] +* [Fixes #27123] Zoom In/Out {kib-pull}38832[#38832] +* Add joinRows Canvas expression function {kib-pull}38680[#38680] +* [Fixes #27124] Fit Workpad to Window {kib-pull}39864[#39864] +* [Fixes #23061, #23144, #29526] Enable Canvas URL Parameters {kib-pull}40061[#40061] +* Alignment and distribution {kib-pull}39132[#39132] +* [Fixes #30841] Box select {kib-pull}32995[#32995] +Infrastructure:: +* Link to node detail page from Metrics Explorer {kib-pull}37136[#37136] +* Adds tooltip (with name / id) to Table view {kib-pull}38904[#38904] +* Improve accuracy of system network metrics {kib-pull}39513[#39513] +* Add default metrics to metrics explorer. {kib-pull}39787[#39787] +* Use max instead of avg for correct derivative in network metrics {kib-pull}41009[#41009] +Logs UI:: +* Add single phrase highlighting {kib-pull}39569[#39569] +* [Fixes #38167] Add "View in APM" link to log flyout actions menu {kib-pull}39540[#39540] +Machine Learning:: +* [Fixes #39240] When importing CSV through file data viz, omit empty values {kib-pull}39524[#39524] +* [Fixes #39242] Don't quote numbers when importing CSV in file data viz {kib-pull}39579[#39579] +* Adds data frame messages to data frames list {kib-pull}39609[#39609] +* Adds icon to data frame messages expanded row tab {kib-pull}39817[#39817] +* Adds Preview table tab to Data Frames list expanded row {kib-pull}39983[#39983] +* Data Frames list expanded row preview: Fixes transform list paging and sorting. {kib-pull}40163[#40163] +* [Fixes #37312] Only add ML links for sample data sets if full license {kib-pull}38120[#38120] +* [Fixes #37994] Adds check that forecast duration is no more than 3650 days {kib-pull}38408[#38408] +* Adds SIEM Auditbeat and metricbeat data recognizer modules {kib-pull}39678[#39678] +* [Fixes #28390] [Accessibility] Add job ID to select row checkbox aria-label in Jobs List {kib-pull}40149[#40149] +* Data Frames: Advanced editor {kib-pull}39659[#39659] +* Data Frames: Continuous mode support for wizard {kib-pull}39804[#39804] +* Data Frames: Updated progress reporting. {kib-pull}39920[#39920] +* Data Frames: Transform list refresh button. {kib-pull}40129[#40129] +* [Fixes #38776] Data Frames: Adds support for transform description {kib-pull}40153[#40153] +Management:: +* [Fixes #13804, #17894, #17956, #17969, #17978, #18008, #18008, #18031, #18047, #18052, #18151, #18191, #18245, #18246, #18256, #18268, #18271, #18296, #18353, #18506, #18508, #18532, #18536, #18794, #22615, #29167, #33207, #33917, #34932, #39828] EUIfy Watcher {kib-pull}35301[#35301] +* Add repository-azure autocompletion settings {kib-pull}37935[#37935] +* [Fixes #32132] Allow users to disable polling in Console {kib-pull}38949[#38949] +* [Fixes #15628] Add setting for disabling use of triple quotes in the Console output pane. {kib-pull}39114[#39114] +* Separate Console History panel from editor with a drop-shadow, and add a Close button {kib-pull}39972[#39972] +* [Fixes #39985] Accept triple quoted input in Search Profiler. {kib-pull}39984[#39984] +* Snapshot and Restore UI {kib-pull}39193[#39193] +* EUIfy Console - partially de-angularize and move custom views out of top_nav {kib-pull}39341[#39341] +* Console update autocomplete definitions {kib-pull}39508[#39508] +Maps:: +* [File upload] New plugin: file upload {kib-pull}36404[#36404] +* [File upload] Geojson upload {kib-pull}36410[#36410] +* [Fixes #35659] Heatmap color ramp select and legend details {kib-pull}37187[#37187] +* [Fixes #30738] Add support for Top Hits to Documents source {kib-pull}38052[#38052] +* [Fixes #30738] Symbolize points with maki icons {kib-pull}37822[#37822] +* Add Symbol orientation style property {kib-pull}39129[#39129] +* [Fixes #35978] Move set view to toolbar control, show zoom level in view control {kib-pull}38925[#38925] +* [Fixes #34399] Add Where clause to terms joins {kib-pull}39593[#39593] +* Increase document limit from 2048 to 10000 {kib-pull}39697[#39697] +* Remove beta labeling from application and docs {kib-pull}39871[#39871] +* [Fixes #31697] Custom labels for metric aggregations {kib-pull}39914[#39914] +* Replace legacy map visualizations with maps in sample data dashboards {kib-pull}35997[#35997] +* [Fixes #34026] Make EMS tooltips configurable {kib-pull}34325[#34325] +* [Fixes #29005] Add multiple feature selection in tooltips {kib-pull}39629[#39629] +Monitoring:: +* Removed dead code {kib-pull}39545[#39545] +* [Fixes #5429] Added a shortcut to ML jobs {kib-pull}39147[#39147] +Platform:: +* Query Filter \ Filter Manager: de-angularize and move to data plugin {kib-pull}37311[#37311] +* Introduce setting to disable batching in courier {kib-pull}39470[#39470] +Reporting:: +* Export Saved Search CSV as Dashboard Panel Action {kib-pull}34571[#34571] +* Check if CSV cells (including headers) start with known formula characters {kib-pull}37930[#37930] +SIEM:: +* Kpi on host details page {kib-pull}39681[#39681] +* Adds Machine Learning table anomalies, a pop over UI for anomalies, and machine learning details score {kib-pull}39483[#39483] +* Adds Machine Learning Permissions to hide or show UI elements based on the permissions {kib-pull}40119[#40119] +* Adds Machine Learning Anomaly Table to Host Details and Network Details {kib-pull}40223[#40223] +* Adds conditional linking within the application for machine learning jobs {kib-pull}40547[#40547] +* Adds ML Integration for Installing & Starting/Stopping embedded ML jobs {kib-pull}39766[#39766] +* Fix URL state request once initial state {kib-pull}38955[#38955] +* SIEM inspect query {kib-pull}39980[#39980] +* Enhance inspect modal {kib-pull}40530[#40530] +Security:: +* Hiding management link {kib-pull}38472[#38472] +* [Fixes #36626] Display message when logging out of Kibana {kib-pull}37234[#37234] +* [Fixes #38563] Allow roles to be cloned {kib-pull}39303[#39303] +* Make SAML realm name configurable {kib-pull}37346[#37346] +Uptime:: +* Summary based monitors Page {kib-pull}39751[#39751] +* [Fixes #38786, #57711] Add monitor summaries {kib-pull}38895[#38895] +* Replace deprecated EUI charts {kib-pull}34313[#34313] +* [Fixes #46] Add error callout for uptime filter bar {kib-pull}38140[#38140] +* Add telemetry collector {kib-pull}34437[#34437] +* Add link for logs host integration {kib-pull}38010[#38010] +* [Fixes #40589] Add link to Uptime documentation from header help menu {kib-pull}40645[#40645] +Visualize:: +* Visual Builder duration in second showing as number {kib-pull}35813[#35813] +* Get rid of default export on TSVB {kib-pull}36872[#36872] +* KQL in TSVB {kib-pull}36784[#36784] +* Add configs for terminate_after {kib-pull}37643[#37643] +* Enable use of KQL and autocomplete in filters agg editor {kib-pull}37287[#37287] +* Add automatic alignment to gauge visualisation {kib-pull}34845[#34845] +* Support Elasticsearch date_nanos datatype {kib-pull}36111[#36111] +* Support for date_nanos type timestamps in context view {kib-pull}38023[#38023] +* [Fixes #38424] Show link to Maps application in create new visualize menu {kib-pull}39191[#39191] +* Rename Visual Builder to TSVB {kib-pull}39125[#39125] +* [Fixes #7116] Show values of bars inside bar charts {kib-pull}36511[#36511] +* Add dateHistogramInterval utility {kib-pull}39091[#39091] + +[float] +[[bug-7.3.0]] +=== Bug fixes +APM:: +* [Fixes #34866] Fix encoding issue with forward slash in path {kib-pull}37072[#37072] +* [Fixes #34697] Distinguish between loading state and empty state {kib-pull}40651[#40651] +* [Fixes elastic/kibana#40477] [APM Tutorial] Fix APM Server link on Cloud {kib-pull}40711[#40711] +* [Fixes #40351] Make sure stacked area charts handle no data points incorrectly {kib-pull}40353[#40353] +Canvas:: +* [Fixes #41296] Apply global CSS to export workpad view {kib-pull}41298[#41298] +* [Fixes #39852] Native HTML5 drag&drop shouldn't kick in {kib-pull}39861[#39861] +* [Fixes #24773] Fix workpad list overflow {kib-pull}37345[#37345] +Discover:: +* [Fixes #41348] Bugfix for exception at discover context view using date_nanos {kib-pull}41353[#41353] +Infrastructure:: +* Support metrics for different docs in Metric Explorer {kib-pull}38153[#38153] +* [Fixes #38141] Allow Metrics Explorer to set KQL filters in TSVB {kib-pull}38280[#38280] +* [Fixes #36818] Metrics Explorer action menu should honor UI capabilities {kib-pull}36824[#36824] +* [Fixes #39809] Sync state with localStorage for Metrics Explorer {kib-pull}40099[#40099] +* [Fixes #40138] Convert bytes to bits before formatting for bits {kib-pull}40523[#40523] +* [Fixes #38130, #37694] Fix CSS to improve IE11 experience {kib-pull}40309[#40309] +* [Fixes #40251] Change GraphQL fetchPolicy for Inventory View {kib-pull}40814[#40814] +* [Fixes #40914] Fix Metric Explorer title truncation {kib-pull}40913[#40913] +* [Fixes #40493] Inventory should display nodes without names {kib-pull}40804[#40804] +* Make queries more robust against missing indices {kib-pull}38976[#38976] +* [Fixes #35975] Fixes text overflow for values in waffle map squares {kib-pull}39068[#39068] +* Add temporary workaround for too small max-width. {kib-pull}39890[#39890] +* [Fixes #39892] Remove queries for log-related metadata {kib-pull}40130[#40130] +* [Fixes #37362] Make arrays of values more readable in log columns {kib-pull}38692[#38692] +* [Fixes #38734] Capitalize 'explorer' in 'Metrics Explorer' {kib-pull}39101[#39101] +* [Fixes #35784] Shrink log stream when window is resized {kib-pull}38937[#38937] +* [Fixes #39913] Widen Group By dropdown and add tooltips to custom metrics {kib-pull}40692[#40692] +Logs UI:: +* [Fixes #39991] Fixes "sticky filter" problem {kib-pull}40226[#40226] +* [Fixes #39944] Fix inaccuracy when jumping to a faraway time target {kib-pull}40303[#40303] +Machine Learning:: +* Data Frame: Disable link to create new data frame job when no permissions {kib-pull}40268[#40268] +* Data Frame: ensure pivot preview works with comma-separated index patterns {kib-pull}40282[#40282] +* [Fixes #40562] Single Metric View: ensure charts loaded correctly when using scripted fields {kib-pull}40682[#40682] +* [Fixes #18076] Fixes loading of Single Metric Viewer if partition field is text {kib-pull}37975[#37975] +* [Fixes #37974] Close job after forecast errors if starting from closed {kib-pull}38253[#38253] +* [Fixes #38661] Show time range button on index data viz when not on full license {kib-pull}38789[#38789] +* [Fixes #38559] Increase max data frame transforms in list from 100 to 1000 {kib-pull}38973[#38973] +* [Fixes #39770] Fixes results time range if anomalies occur after data stops {kib-pull}40503[#40503] +* [Fixes #32304] Fixes positioning of annotations brush after window resize {kib-pull}40780[#40780] +* [Fixes #33416] Fixes positioning of Single Metric zoom when at start of range {kib-pull}40854[#40854] +* [Fixes #41135] Fixes model memory limit for metricbeat system module jobs {kib-pull}41747[#41747] +* Data Frame: Rename target index to destination index. {kib-pull}39239[#39239] +* [Fixes #38872] Data Frame: Fixes crash of the source table for complex field values. {kib-pull}39878[#39878] +* Data Frame: Fixes transform list paging and sorting. {kib-pull}40009[#40009] +* [Fixes #38654] Data Frame: Fix form validation {kib-pull}40427[#40427] +* [Fixes #38395] Data Frame: Fixes search triggering onChange on every keystroke. {kib-pull}40607[#40607] +* [Fixes #40960] Fix loading forecasts from anomaly job list. {kib-pull}41034[#41034] +* Data Frame: Fix source table for cells of type object. {kib-pull}41234[#41234] +Management:: +* [Fixes #33424, #18851] [IM] Improve UX for permissions error {kib-pull}38916[#38916] +* [Fixes #34751, #19249] [LICENSE] Check permissions before loading license management actions {kib-pull}39183[#39183] +* [Fixes #21484] [IM] warn user before closing or deleting kibana index {kib-pull}39018[#39018] +* [Fixes #38940] Fix Console bug caused by rapidly opening and closing the History tab. {kib-pull}38950[#38950] +* [Fixes #38562] Fix Search Profiler's 'Index' input's placeholder color contrast accessibility. {kib-pull}38952[#38952] +* [Fixes #36983] Fix field autocomplete suggestions in Console {kib-pull}38948[#38948] +* [Fixes #40254] Fix aggs autocompletion in Console. {kib-pull}40816[#40816] +* [Fixes #39087] Remove config from IndexPattern instance {kib-pull}40146[#40146] +* Fix `Rollup` tag not showing on rollup index patterns in list {kib-pull}40297[#40297] +Maps:: +* [Fixes #38021] Use coalesce to ensure number always passed to interpolate for data driven size styling {kib-pull}38427[#38427] +* Provide IntlProvider to map listing page {kib-pull}39459[#39459] +* [Fixes #37369] Do not allow save when map has unsaved layer changes {kib-pull}39529[#39529] +* [Fixes #38962] Documents source - top hits - support script fields {kib-pull}39371[#39371] +* [Fixes #40307] Fix react typing for style property type {kib-pull}40518[#40518] +* Use custom labels in legend details {kib-pull}40308[#40308] +* Fix symbol anchor position {kib-pull}40524[#40524] +* [Fixes #40337] Use default locale as fallback for EMS tile layers {kib-pull}40433[#40433] +* [Fixes #40085] Show dialog to save map when leaving app {kib-pull}40215[#40215] +* Shuffle feature ids to avoid mapbox-gl crashes {kib-pull}40803[#40803] +* [Fixes #40646] Remove data on error {kib-pull}41358[#41358] +* [Fixes #41491] Coerce term join values to string {kib-pull}41503[#41503] +Monitoring:: +* Add log message for error scenario around missing licensing {kib-pull}40660[#40660] +* [Fixes #36738] Issue 36738: Added zoomout functionality to all charts {kib-pull}39072[#39072] +* [Fixes #28471] Issue 28471: Added strict id checking {kib-pull}40673[#40673] +Operations:: +* Fixes an issue where headless_shell doesn't get properly closed (and … {kib-pull}40924[#40924] +* [Fixes #31549] Configurable global socket timeouts {kib-pull}31603[#31603] +Platform:: +* [Fixes #14544] Cancel Discover fetch requests if a new one is submitted {kib-pull}39963[#39963] +* [Fixes #38127] Add required default markdown visState {kib-pull}38390[#38390] +* Fixing custom vis types buildPipeline {kib-pull}39874[#39874] +Reporting:: +* Bugfix/reporting png is cancelled {kib-pull}37513[#37513] +* Addresses an issue where Chromium user-data-dirs aren't removed {kib-pull}40284[#40284] +SIEM:: +* Update translation {kib-pull}40038[#40038] +* Styling KQL bar {kib-pull}40487[#40487] +Security:: +* [Fixes #40014] Spaces API - default disabledFeatures to empty array {kib-pull}40017[#40017] +* [Fixes #39837] Feature Controls - only navigate to index pattern management if available {kib-pull}40067[#40067] +Uptime:: +* [Fixes #39679] Fix filter status bar location selection {kib-pull}41382[#41382] +* [Fixes #40171] [Bug] Handle all supported empty states {kib-pull}40194[#40194] +* Fix unsigned integer parsing error and add tests {kib-pull}40526[#40526] +* [Fixes #40582] Change page headlines to use h1 element {kib-pull}40637[#40637] +* [Fixes #40583] Add explicit alignments to table columns {kib-pull}40680[#40680] +* Fix duration chart for Safari {kib-pull}41619[#41619] +Visualize:: +* VisualBuilder Metric: Zero values ends in a changed behavior of the color rules {kib-pull}39583[#39583] +* Wrap long text inside of TSVB chart tooltip. {kib-pull}39630[#39630] +* [Fixes #34535] Adds time zone to date_range bucket aggregation {kib-pull}37576[#37576] +* [Fixes #39580] Corrects index pattern for fields in split_by_terms {kib-pull}39723[#39723 +* [Fixes #40351] Make sure stacked area charts handle no data points incorrectly {kib-pull}40353[#40353] +* Fix `Rollup` tag not showing on rollup index patterns in list {kib-pull}40297[#40297] +* [Fixes #37940] Don't show listing limit exceeded warning falsely {kib-pull}38246[#38246] +* Add default values for filter labels property for xy charts {kib-pull}38644[#38644] +* [Fixes #39788, #39655] Fix tooltip label name rendering in pie charts. {kib-pull}40105[#40105] +* Fix autorefresh in visualize editor {kib-pull}41657[#41657] +* [Fixes #41357] Bugfix displaying date_nanos formated min/max aggs {kib-pull}41472[#41472] +* [Fixes #39083] Fix visualization migration when savedSearchId is empty string {kib-pull}40172[#40172] +* Change help URL in timelion to point to current docs {kib-pull}39885[#39885] +* Check whether vis type exists {kib-pull}39803[#39803] +* [Fixes #28842] Fix issue with long values in TSVB static metric {kib-pull}40256[#40256] +* [Fixes #36295] Fix visualizations for rollups using fixed_interval or calendar_interval {kib-pull}39537[#39537] +* Fix bug in Filters aggregation and Terms aggregation with Other bucket {kib-pull}40698[#40698] + +[[release-notes-7.2.1]] +== {kib} 7.2.1 + +See also <>. + +[float] +[[enhancement-7.2.1]] +=== Enhancements +Machine Learning:: +* Only adds ML links for sample data sets if full license {kib-pull}38120[#38120] +* Adds check that forecast duration is no more than 3650 days {kib-pull}38408[#38408] +Observability:: +* Uptime: Adds error callout for filter bar {kib-pull}38140[#38140] + +[float] +[[bug-7.2.1]] +=== Bug fixes +Geo:: +* Uses default locale as fallback for EMS tile layers {kib-pull}40433[#40433] +Infra Logs UI:: +* Infra UI: Resets error when IP address changes to valid entry {kib-pull}38022[#38022] +Machine Learning:: +* Closes job after forecast errors if starting from closed {kib-pull}38253[#38253] +* Shows time range button on index data viz when not on full license {kib-pull}38789[#38789] +* Increases max data frame transforms in list from 100 to 1000 {kib-pull}38973[#38973] +* Data Frames: Fixes crash of the source table for complex field values {kib-pull}39878[#39878] +Management:: +* Console: Fixes field autocomplete suggestions {kib-pull}38948[#38948] +* Console: Fixes aggs autocompletion {kib-pull}40816[#40816] +* Console: Fixes bug caused by rapidly opening and closing the History tab {kib-pull}38950[#38950] +* Index Management: Improves user experiences for permissions error {kib-pull}38916[#38916] +* Index Management: Warns user before closing or deleting {kib} index {kib-pull}39018[#39018] +* License Management: Checks permissions before loading license management actions {kib-pull}39183[#39183] +* Search Profiler: Fixes placeholder color contrast accessibility in Index input {kib-pull}38952[#38952] +Monitoring:: +* Adds zoomout functionality to all charts {kib-pull}39072[#39072] +* Adds log message for error scenario around missing licensing {kib-pull}40660[#40660] +Security:: +* Feature Controls: Only navigates to index pattern management if available {kib-pull}40067[#40067] +* Spaces: Fixes scenario where a Space is created via the API without specifying any `disabledFeatures` {kib-pull}40017[#40017] +Visualize:: +* Fixes problem with `Rollup` tag not showing on rollup index patterns in list {kib-pull}40297[#40297] +* Fixes show listing limit so it no longer shows a false warning {kib-pull}38246[#38246] +* Fixes tooltip label name rendering in pie charts {kib-pull}40105[#40105] +* Fixes visualization migration when `savedSearchId` is an empty string {kib-pull}40172[#40172] +* Checks whether vis type exists {kib-pull}39803[#39803] +* Fixes visualizations for rollups using `fixed_interval` or `calendar_interval` {kib-pull}39537[#39537] +* Fixes custom vis types `buildPipeline` {kib-pull}39874[#39874] + + + +[[release-notes-7.2.0]] +== {kib} 7.2.0 + +[float] +[[breaking-7.2.0]] +=== Breaking Changes + +See <> for more information. + +Index Patterns:: +* Removes support for time-based interval index patterns with migration {kib-pull}35262[#35262] + +[float] +[[enhancement-7.2.0]] +=== Enhancements +Canvas:: +* Adds custom elements {kib-pull}34140[#34140] +* Adds static tags for elements {kib-pull}28779[#28779] +* Adds autoplay pages in fullscreen {kib-pull}35981[#35981] +* Adds new workpad templates {kib-pull}35745[#35745] +* Adds Ctrl + Enter shortcut for evaluating expressions {kib-pull}36138[#36138] +* Allows grouping of filters and group selection in the `filters` function {kib-pull}34889[#34889] + +Design:: +* Upgrades EUI to 9.2.1 and improves dark mode {kib-pull}32728[#32728] + +Geo:: +* Allows maps to be embeddable {kib-pull}31473[#31473] +* Registers `savedObjectMetaData` so Maps saved objects show up in dashboard add panel {kib-pull}32895[#32895] +* Populates WMS layers from `getCapabilities` response {kib-pull}32342[#32342] +* Splits settings into layer and source panels {kib-pull}33788[#33788] +* Adds layer-specific filtering {kib-pull}33209[#33209] +* Adds clone layer to layer actions {kib-pull}33853[#33853] +* Automatically disables filter by bounds for indexes with small doc counts {kib-pull}34456[#34456] +* Adds ability to expand and collapse Layer TOC {kib-pull}34506[#34506] +* Ignores global query layer setting {kib-pull}35542[#35542] +* Shows dynamic style ranges in legend {kib-pull}35417[#35417] +* Shows icon when layer is not visible in TOC {kib-pull}36250[#36250] +* Shows minusInCircle icon when layer has no data {kib-pull}36457[#36457] +* Only shows vector style properties used by source in editor {kib-pull}36280[#36280] +* Supports multiple basemap styles {kib-pull}36074[#36074] +* Locks tooltip in place with click {kib-pull}32733[#32733] +* Uses dual range component {kib-pull}32273[#32273] +* Adds filter actions to tooltips {kib-pull}33635[#33635] +* Adds draw filter action to layer {kib-pull}33686[#33686] +* Adds WKT and geohash string support {kib-pull}34472[#34472] + +Kibana Home & Add Data:: +* Injects anomalies into the Kibana sample datasets to enable ML sample jobs {kib-pull}36714[#36714] +* Allows plugins to register additional view data links in sample data {kib-pull}33052[#33052] + +Logs:: +* Adds customizable columns {kib-pull}34916[#34916] +* Adds column headers {kib-pull}36467[#36467] +* Adds flyout action menu with Uptime link {kib-pull}36721[#36721] + +Machine Learning:: +* Adds Kibana sample dataset data recognizer modules {kib-pull}35138[#35138] +* Adds File data viz filter to Index Management link {kib-pull}36166[#36166] +* Adds query bar to Anomaly Explorer for filtering of anomaly results for one or more influencers {kib-pull}31763[#31763] +* Adds the ability to add and remove filters in the Anomaly Explorer via the Anomalies table {kib-pull}33377[#33377] +* Adds the ability to add and remove filters in the Anomaly Explorer via the Top influencers list {kib-pull}33626[#33626] +* Converts Job Selector to React {kib-pull}35638[#35638] +* Always show time warning message in the delete modal in Job Management {kib-pull}36729[#36729] +* Makes layout of Edit Filter List consistent with other settings pages {kib-pull}33421[#33421] +* Adds created_by field to Auditbeat and APM data recognizer jobs {kib-pull}33863[#33863] +* Extends support for anomaly charts when model plot is enabled {kib-pull}34079[#34079] +* Increases the width of the text column in annotations table {kib-pull}34450[#34450] +* Replaces View Forecast button image with Single Metric icon {kib-pull}34563[#34563] +* Limits maximum annotation text length to 1000 characters {kib-pull}34540[#34540] +* Converts full time range selector control to EUI / React {kib-pull}35074[#35074] +* Uses KQL as the query language for custom URLs to Kibana pages {kib-pull}35469[#35469] +* Adds Metricbeat System data recognizer module {kib-pull}35580[#35580] +* Removes check for forecast duration of 8 weeks or less {kib-pull}35583[#35583] +* Adds links to ML jobs to the Kibana sample dataset View data menu {kib-pull}36702[#36702] +* Adds Data Frame UI {kib-pull}33427[#33427] + +Management:: +* Adds UI for Snapshot Repositories {kib-pull}34407[#34407] + +Monitoring:: +* Adds Telemetry sample data {kib-pull}33166[#33166] + +Platform:: +* Introduces UI PluginsService {kib-pull}32672[#32672] +* Adds basic server side export API for saved objects {kib-pull}30326[#30326] +* Adds basic server side import API for saved objects {kib-pull}32158[#32158] +* Returns import errors for saved objects referencing a missing index pattern or search {kib-pull}33005[#33005] +* Modifies saved object export API to support the exporting of nested dependencies {kib-pull}34225[#34225] +* Converts the saved objects UI to use new import / export API {kib-pull}33513[#33513] +* Allows any type of saved object to import / export {kib-pull}34896[#34896] + +Security:: +* Adds Feature Controls {kib-pull}31652[#31652] +* Adds OpenID Connect auth provider {kib-pull}36201[#36201] +* Converts account screen to React/EUI {kib-pull}35151[#35151] +* Exposes ability to deny ('except') access to fields via FLS {kib-pull}26472[#26472] +* Converts role listing page to React/EUI {kib-pull}30970[#30970] + +Uptime:: +* Adds support for location name in Uptime UI {kib-pull}36317[#36317] +* Integrates Uptime to Logging {kib-pull}35853[#35853] +* Cleans up design of Uptime app {kib-pull}31663[#31663] + +Visualize:: +* Allows multiple values for percentile ranks in Time Series Visual Builder {kib-pull}33642[#33642] +* Allows non numeric fields in Top Hits in Time Series Visual Builder {kib-pull}35661[#35661] +* Adds Include and Exclude fields to the Terms group in Time Series Visual Builder {kib-pull}34153[#34153] +* Adds ability to submit Save modals using the Enter key {kib-pull}34417[#34417] +* Improves KQL error messages {kib-pull}34900[#34900] +* Shows a reload dialog when users change a setting requiring a page reload {kib-pull}34780[#34780] +* Improves scripted field script editor {kib-pull}36064[#36064] +* Changes default quick ranges {kib-pull}35066[#35066] +* Adds basic rollup support to Visual builder {kib-pull}28762[#28762] + +[float] +[[bug-7.2.0]] +=== Bug fixes + +APM:: +* Moves the APM index creation from server startup {kib-pull}37965[#37965] +* Updates APM index pattern {kib-pull}36776[#36776] +* Fixes error occurrence panel and content {kib-pull}32808[#32808] +* Switches to visualization colour palette for histogram {kib-pull}31688[#31688] +* Condenses panel gutters and spacers {kib-pull}36337[#36337] +* Replaces the icon for the LibraryFrames toggle {kib-pull}36429[#36429] +* Fixes issues with metric charts when `noHits=true` {kib-pull}37524[#37524] +* Updates index pattern {kib-pull}38797[#38797] + +Beats Central Management:: +* Moves APIs to new return format {kib-pull}31660[#31660] +* Renames `api/canvas` endpoint to `api/interpreter` {kib-pull}34410[#34410] +* Updates tagcloud interpreter func arguments {kib-pull}33773[#33773] +* Updates markdownvis interpreter func arguments {kib-pull}34534[#34534] +* Moves UI out of index patterns service {kib-pull}36348[#36348] + +Canvas:: +* Fixes esdocs fields {kib-pull}34894[#34894] +* Fixes datasource preview modal size {kib-pull}36246[#36246] +* Allows 0 for min/max in AxisConfig {kib-pull}37119[#37119] +* Fixes fullscreen sizing on old workpads {kib-pull}37289[#37289] +* Adds Today to quick range {kib-pull}36698[#36698] +* Fixes broken elements in web logs sample data workpad {kib-pull}37931[#37931] +* Resolves issues with the mini color selector and updates Storybook to v5 {kib-pull}34075[#34075] +* Adds types to Renderers and the DropdownFilter {kib-pull}31299[#31299] +* Updates the Asset Manager to use Typescript and adds Storybook examples for ad-hoc testing {kib-pull}31341[#31341] +* Converts functions from arrow to function {kib-pull}35749[#35749] +* Adds strong types to Canvas functions in preparation for i18n {kib-pull}35087[#35087] +* Improves types `demodata` and `pointseries` in preparation for i18n {kib-pull}36055[#36055] +* Implements localization for Canvas functions {kib-pull}36252[#36252] +* Re-renders renderers on filter changes {kib-pull}34823[#34823] +* Restores removed class used for modal focus {kib-pull}36924[#36924] +* Simplifies layout engine integration {kib-pull}33702[#33702] +* Separates component/`-level of `workpad_page` {kib-pull}34983[#34983] +* Fixes invalid cursor position {kib-pull}36018[#36018] +* Adds snap to page borders and centerline {kib-pull}36102[#36102] +* Prioritizes relaxed resize/rotate over depth select {kib-pull}36479[#36479] +* Accesses the ever current interactive page layout in WorkpadApp {kib-pull}36692[#36692] +* Adds group/ungroup menu {kib-pull}36718[#36718] +* Improves Storybook performance {kib-pull}34757[#34757] +* Adds response streaming to Canvas batch requests {kib-pull}32027[#32027] + +Console:: +* Refetches autocomplete info after updating Dev Console settings {kib-pull}32587[#32587] +* Fixes issue with request body not being sent for Console DELETE requests {kib-pull}32407[#32407] + +Dashboard:: +* Allows embeddable to specify edit label {kib-pull}36296[#36296] +* Fixes courier:ignoreFilterIfFieldNotInIndex with chained input controls {kib-pull}36369[#36369] +* Fetches options for input control child select boxes {kib-pull}38148[#38148] +* Converts dashboard panels to Typescript {kib-pull}27167[#27167] + +Discover:: +* Fixes problem with Discover not using an index pattern when two patterns are created {kib-pull}38053[#38053] +* Enables optional use of the timezone set in Advanced Settings in queries {kib-pull}34602[#34602] + +Geo:: +* Changes tooltip to use description list for IE compatibility {kib-pull}37396[#37396] +* Excludes multi fields in tooltips and join field selection lists {kib-pull}34379[#34379] +* Only show fields that can be used in terms agg in join right field select {kib-pull}35098[#35098] +* Maintains style on source change when creating new layer {kib-pull}34755[#34755] +* Fixes i18n wrapping of ES search failure message {kib-pull}35923[#35923] +* Updates es_search_source to no longer request tooltip fields when fetching geojson {kib-pull}36059[#36059] +* Syncs layer list state to mapbox only once {kib-pull}37133[#37133] +* Sets scaled property values to -1 when there are no results {kib-pull}37121[#37121] +* Fixes defaulting to dark tiles when Kibana is in dark mode {kib-pull}37792[#37792] +* Fixes tooltip text overlap and text overflow {kib-pull}38271[#38271] +* Ensures that the labels extracted from WMS capabilities are unique {kib-pull}38311[#38311] +* Keeps query parameters for WMS Client in URL {kib-pull}34200[#34200] +* Fixes Join editor component logic to avoid infinite updates {kib-pull}37472[#37472] +* Fixes Join editor component logic to avoid infinite updates if index pattern is not found {kib-pull}37615[#37615] +* Uses field formatter for tooltips {kib-pull}33017[#33017] +* Adds ability to load EMS resources with CORS {kib-pull}34503[#34503] +* Uses mapbox feature-state for dynamic properties and upgrades mapbox-gl to 0.54 {kib-pull}36466[#36466] +* Fixes map embeddable test {kib-pull}34648[#34648] + +Graph:: +* Fixes default drilldown link on index pattern switch {kib-pull}34251[#34251] + +Infrastructure:: +* Fixes autocomplete overflow in Safari browser {kib-pull}36820[#36820] +* Adds legend settings for waffle map {kib-pull}32228[#32228] +* Adds the UI for the Metrics Explorer {kib-pull}34019[#34019] +* Adds the UI for the Metrics Explorer {kib-pull}35846[#35846] +* Adds links from Infrastructure to Uptime {kib-pull}35993[#35993] +* Adds a brush handler to the Metrics Explorer Charts {kib-pull}36235[#36235] +* Removes the Joi validation from the Metrics Explorer client side URL validation {kib-pull}36493[#36493] +* Appends filterQuery to TSVB filter {kib-pull}36644[#36644] +* Adds link-to page to route IP addresses to the host detail page {kib-pull}36149[#36149] +* Adds a check to the Metrics Explorer API endpoint for empty metrics {kib-pull}37508[#37508] +* Adds round up option to SuperDatePicker for the `to` field {kib-pull}37896[#37896] +* Fixes the Uptime link so it always displays for Docker and Kubernetes nodes {kib-pull}38125[#38125] +* Fixes the CSS for the Metrics Explorer chart title to properly overlap with the Actions menu {kib-pull}38059[#38059] +* Fixes group by “x” icon keyboard controls {kib-pull}31960[#31960] +* Changes Infrastructure navigation {kib-pull}32892[#32892] +* Uses EuiSuperDatePicker on the Metrics page {kib-pull}34427[#34427] +* Tweaks metrics time test handling {kib-pull}34869[#34869] +* Increases suggestions limit and allows scrolling in Autocomplete field {kib-pull}34706[#34706] +* Adds new graphql endpoint for snapshot data {kib-pull}34264[#34264] +* Waits for context menu to appear in functional tests {kib-pull}36163[#36163] +* Renames Snapshot to Inventory {kib-pull}36107[#36107] +* Enables telemetry for snapshot resolver {kib-pull}36354[#36354] +* Renames Snapshot to Inventory in page title {kib-pull}36432[#36432] +* Honors space when querying TSVB API {kib-pull}36765[#36765] +* Adds View Surrounding Logs functionality {kib-pull}35727[#35727] +* Changes popover position of Node context menu {kib-pull}36352[#36352] + +Kibana Home & Add Data:: +* Adds `utc_time` of sample web logs to list of timeFields so that it is dynamic {kib-pull}35879[#35879] + +Machine Learning:: +* Fixes File Data Visualizer index pattern match {kib-pull}34721[#34721] +* Rounds value when using max model memory limit {kib-pull}35223[#35223] +* Plots chart points for all anomalies where there is no metric data {kib-pull}32645[#32645] +* Fixes line wrap for jobs list timestamp cell in Firefox {kib-pull}34150[#34150] +* Updates forecasting progress bar only if value increases {kib-pull}34614[#34614] +* Fixes Java time access in ML watch Painless script {kib-pull}37074[#37074] +* Provides fix for constant polling of deleting job tasks {kib-pull}38013[#38013] +* Fixes check when opening ML from Kibana Sample Data sets if no ML jobs are created {kib-pull}38649[#38649] + +Management:: +* Disables grow for IE 11 for index pattern management header {kib-pull}37756[#37756] +* Internationalizes Rollup Jobs, Remote Clusters, and Watcher app titles. {kib-pull}34470[#34470] +* Removes rollup section in advanced settings for OSS {kib-pull}32814[#32814] +* Fixes Create Rollup Index Pattern button badge color error {kib-pull}32954[#32954] +* Fixes hanging UI when custom index pattern with existing ID created {kib-pull}36097[#36097] +* Bumps numeral.js to fix negative time formatting bug {kib-pull}35298[#35298] + +Monitoring:: +* Improves performance of the Logstash Pipeline Viewer {kib-pull}31293[#31293] +* Updates tests for Monitoring Logstash Pipeline Viewer performance improvements {kib-pull}33570[#33570] +* Sends encrypted telemetry data to telemetry service {kib-pull}33121[#33121] +* Checks for 6.7.2 instead of 6.7.3 in Telemetry {kib-pull}35814[#35814] +* Introduces Logs UI {kib-pull}31275[#31275] +* Determines the Metricbeat migration status logic {kib-pull}34871[#34871] +* Forces collectors to indicate when they are ready in Montoring/Telemetry {kib-pull}36153[#36153] +* Makes change so that once the buffer has events, the collector is always ready {kib-pull}36995[#36995] +* Fixes 500 error from /api/stats {kib-pull}36986[#36986] +* Removes improper usage of query {kib-pull}37099[#37099] +* Uses fixed_interval explicitly for date_histogram aggregations {kib-pull}37023[#37023] +* Creates license check only when there’s a separate monitoring cluster {kib-pull}33590[#33590] +* Adds uiCapabilities.logs check {kib-pull}35562[#35562] +* Creates a simple cancelable promise, and adds basic support for Typescript {kib-pull}36293[#36293] +* Fixes default message if value is invalid {kib-pull}36737[#36737] +* Fixes sorting of Monitoring nodes on CPU, Throttle, and Heap columns {kib-pull}36125[#36125] +* Swaps the anchor tag with EuiLink {kib-pull}37020[#37020] +* Typecasts the attr boolean to the correct type {kib-pull}37031[#37031] +* Fixes CPU calculation for APM {kib-pull}37230[#37230] +* Optimizes content to be more vertical for resizing consistency {kib-pull}37120[#37120] +* Uses i18n instead of injectI18n {kib-pull}37845[#37845] +* Adds a link to License Management {kib-pull}37771[#37771] + +Operations:: +* Reverts [kbn/es] pin 7.x snapshot to elastic/elasticsearch#39582 i… {kib-pull}32580[#32580] +* Exits if starting Kibana as root {kib-pull}21563[#21563] +* Uses default keys when running from source {kib-pull}36452[#36452] +* Allows running --dev without kibana.dev.yml {kib-pull}36400[#36400] +* Reenables github checks reporter {kib-pull}37280[#37280] +* Fixes inefficiencies in the dev/license_checker module and rewrites it in Typescript {kib-pull}37807[#37807] +* Adds exception to transpile normalize-url mode to es5 when bundled into the DLL {kib-pull}35804[#35804] +* Upgrades jQuery to 3.4.1 {kib-pull}35908[#35908] +* Enforces all packages to use the same Typescript version {kib-pull}32440[#32440] +* Fixes plugin generator package.json paths {kib-pull}33728[#33728] + +Platform:: +* Fixes version for plugin showing as undefined {kib-pull}36219[#36219] +* Adds Japanese locale {kib-pull}36940[#36940] +* Provides Initial framework for data plugin {kib-pull}34350[#34350] +* Fixes errors and adds more examples in export saved objects API docs {kib-pull}37991[#37991] +* Updates import saved objects API docs to use curl examples {kib-pull}37997[#37997] +* Fixes URLs from displaying too long in saved objects management UI {kib-pull}37987[#37987] +* Enforces the base path proxy to redirect requests that happen within a space {kib-pull}36300[#36300] +* Automatically strips xpack config when running --oss {kib-pull}36403[#36403] +* Removes unused ui/field_editor reference {kib-pull}34969[#34969] + +Reporting:: +* Includes the error object job decryption errors {kib-pull}32216[#32216] +* Consolidates startup self-checks {kib-pull}31931[#31931] +* Registers a single ESQueue worker, simultaneous poll for all export types {kib-pull}32839[#32839] +* Converts LevelLogger Logger to Typescript {kib-pull}34972[#34972] + +Security:: +* Updates index fields API to account for removed types in Role Management {kib-pull}35986[#35986] +* Loads capabilities from InjectedMetadata {kib-pull}36710[#36710] + +Uptime:: +* Adds integration links for Infrastructure UI {kib-pull}35847[#35847] +* Changes copy on empty state component {kib-pull}33044[#33044] +* Removes Object.assign from helper function {kib-pull}33860[#33860] +* Adds new context for Uptime {kib-pull}34006[#34006] +* Supports URL parameters {kib-pull}35375[#35375] +* Adds Uptime to APM integration {kib-pull}34892[#34892] +* Reduces the bucket size for the monitor list query {kib-pull}36071[#36071] +* Disables integration links for apps that are not present {kib-pull}37284[#37284] +* Removes several default common DatePicker values {kib-pull}37395[#37395] +* Supports KQL `OR` filters {kib-pull}37564[#37564] +* Updates documentation link for location column {kib-pull}37511[#37511] + +Visualize:: +* Fixes typo in top hit fields filter {kib-pull}38391[#38391] +* Resets FilterEditor on filter prop change {kib-pull}34494[#34494] +* Adds table with conflicting indices in field editor {kib-pull}35783[#35783] +* Fixes sorting of index pattern table in Chrome and Firefox {kib-pull}37613[#37613] +* Fixes Tableview in Time Series Visual Builder to show correct data {kib-pull}34343[#34343] +* Fixes Aggregation by "Static value" in Time Series Visual Builder so that it works properly {kib-pull}34624[#34624] +* Fixes problem in Time Series Visual Builder with shift in historic data after daylight savings time {kib-pull}34283[#34283] +* Triggers request for api/metrics/fields after all UI changes in Time Series Visual Builder {kib-pull}34436[#34436] +* Fixes problem with query bar showing randomly in editor page in Time Series Visual Builder {kib-pull}35081[#35081] +* Makes Time Series Visual Builder signal render-complete equals true on rendering {kib-pull}35215[#35215] +* Filters annotations by the last series timestamp in Time Series Visual Builder {kib-pull}35230[#35230] +* Allows negative values for custom ranges in metric and gauge visualizations {kib-pull}33814[#33814] +* Fixes broken filtering on metric visualizations {kib-pull}38029[#38029] +* Restores line rendering in point series vis using percentile agg {kib-pull}35649[#35649] +* Fixes range filtering in XY charts when field is a scripted date field {kib-pull}25379[#25379] +* Fixes clipping of wide Vega tooltip tables {kib-pull}33465[#33465] +* Migrates serialization of include/exclude options to strings instead of objects in significant terms bucket aggregation {kib-pull}34392[#34392] +* Initializes correct value of time picker's refresh interval {kib-pull}35839[#35839] +* Updates tab counters on filter change {kib-pull}34246[#34246] +* Resolves issue that occurs when migrations are partially complete and a new Kibana instance starts up {kib-pull}37674[#37674] +* Adds yml switch for using interpreter in expressions {kib-pull}33832[#33832] + + + +[[release-notes-7.1.1]] +== {kib} 7.1.1 + +There are no user-facing changes for this release. + +[[release-notes-7.1.0]] +== {kib} 7.1.0 + +[float] +[[enhancements-7.1.0]] +=== Enhancements +Security:: +* Updates {kib} to support changes to licensing of security features {kib-pull}35890[#35890] + +[float] +[[bug-7.1.0]] +=== Bug fixes +Geo:: +* Improves ES search decoding to deal with large geometries {kib-pull}36062[#36062] +Index Lifecycle Management:: +* Fixes surface shrink action in edit form if it's already been set on the policy {kib-pull}35987[#35987] +Machine Learning:: +* Fixes URL of link to detector function reference docs {kib-pull}35734[#35734] +Monitoring:: +* Fixes default timestamp sort and added tests {kib-pull}35640[#35640] + +[[release-notes-7.0.1]] +== {kib} 7.0.1 + + +See <> for the changes to be aware of when migrating your application +from one version of Kibana to another. + + +[float] +[[enhancement-7.0.1]] +=== Enhancements +Management:: +* Enhances design for Search Profiler, including dark mode {kib-pull}33445[#33445] +Visualize:: +* Sets a default timeout for all "waitFor" methods {kib-pull}34756[#34756] + +[float] +[[bug-7.0.1]] +=== Bug fixes +APM:: +* Updates APM migration reindex script {kib-pull}34801[#34801] +Canvas:: +* Recreates handlers and resets completed state on expression change {kib-pull}33900[#33900] +* Fixes bad context check {kib-pull}35621[#35621] +Design:: +* Updates README for KUI to note deprecation {kib-pull}34389[#34389] +* Resets heading and p tags to EUI font reset {kib-pull}33717[#33717] +Console:: +* Changes autocomplete suggest for `number_of_shards` to default (1) {kib-pull}35657[#35657] +Cross-Cluster Replication:: +* Updates the Delete Remote Cluster API to support multiple comma-delimited clusters {kib-pull}34595[#34595] +* Allows user to use CCR when security is not enabled {kib-pull}35333[#35333] +* Retrieves paused state of follower index from ES instead of depending upon the client to provide it {kib-pull}35342[#35342] +* Fixes filling x-axis values for date histogram {kib-pull}35247[#35247] +Geo:: +* Updates map name in breadcrumb when changed {kib-pull}34287[#34287] +* Filters fields properly for join right field select {kib-pull}35098[#35098] +* Clears data load error when layer gets correct data {kib-pull}34484[#34484] +Index Lifecycle Management:: +* Fixes crash when zero replicas configured in a phase for policy {kib-pull}34480[#34480] +Infrastructure:: +* Fixes metrics chart tooltip alignment {kib-pull}34749[#34749] +* Sets [System][auth] program name correctly {kib-pull}34212[#34212] +Kibana Home & Add Data:: +* Adds documentation link to Functionbeat to fix Getting Started Guide {kib-pull}35174[#35174] +Machine Learning:: +* Ensures cardinality warning is only shown on validity fail {kib-pull}34874[#34874] +* Adds data-test-subj to some job management elements {kib-pull}35284[#35284] +* Ensures `viewByFieldName` is retained on Anomaly Explorer initialize {kib-pull}35260[#35260] +Monitoring:: +* Monitors internal telemetry collection {kib-pull}34609[#34609] +* Addresses shard allocation color mismatch {kib-pull}34086[#34086] +* Protects against fields not existing in Logstash Nodes listing {kib-pull}34939[#34939] +* Fixes field name for "Events Ingested" in Logstash Node List page {kib-pull}35122[#35122] +* Swaps KUI base class with EUI equivalent {kib-pull}34644[#34644] +* Allows empty and null key types {kib-pull}35016[#35016] +* Adds sorting to all columns {kib-pull}35410[#35410] +* Shows node name instead of UID in breadcrumbs {kib-pull}35553[#35553] +Observability:: +* Removes crosshair synchronization to avoid display bug {kib-pull}33660[#33660] +* Switches GQL field from Int to String {kib-pull}33746[#33746] +Operations:: +* Links stylesheets with `type=text/css` {kib-pull}35546[#35546] +* Deletes empty stylesheet for status page {kib-pull}35540[#35540] +* Enables delete of `watch_optimizer_cache_state.json` when data folder is outside of {kib} folder {kib-pull}32446[#32446] +* Fixes missing flag checks {kib-pull}35187[#35187] +* Adds ability to register callback for clean up {kib-pull}35119[#35119] +Platform:: +* Fixes import UI to not fail silently when a record other than index-pattern and search is missing {kib-pull}33080[#33080] +* Avoids validating saved object migrationVersion in tests where not needed {kib-pull}35010[#35010] +* Exclude usage stats when `exclude_usage` flag is specified {kib-pull}35691[#35691] +Upgrade Assistant:: +* Specifies `allow_restricted_indices` for `_has_privileges` {kib-pull}35125[#35125] +* Shows different interstitial text when cluster is upgraded {kib-pull}34762[#34762] +Visualizations:: +* Prevents saving the current timezone in visualizations {kib-pull}34795[#34795] +* Fixes timepicker problem in Firefox {kib-pull}35279[#35279] +* Fixes timepicker quick select {kib-pull}34354[#34354] +* Applies timezone correctly to formatted dates and ticks {kib-pull}33831[#33831] + + + + + +[[release-notes-7.0.0]] +== {kib} 7.0.0 + +[float] +=== Known issues + +Monitoring:: +* If you have a version 7.0 monitoring cluster, a version 6.7 production +cluster and {kib} version 6.7.0 or 6.7.1, you cannot see the monitoring data in +{kib}. {kib-issue}34357[#34357] + +[float] +[[breaking-7.0.0]] +=== Breaking changes + +For more details about breaking changes in this release, see +<>. + +Discover:: +* Allows user to use advanced query DSL directly, and does not apply `query:queryString:options` to `query_string` filters automatically {kib-pull}15640[#15640] +* Removes `default_field` from `query:queryString:options` {kib-pull}18966[#18966] +* Makes KQL the default query language for new searches {kib-pull}27092[#27092] +Design:: +* Removes references to K6 EUI, using the default UI theme in its place {kib-pull}29152[#29152] +Geo:: +* Removes the deprecated `regionmap` and `tilemap` kibana.yml configurations. +Removes the backwards compatibility logic that checked for duplicative settings +`map.regionmap` and `map.tilemap`. {kib-pull}28609[#28609] +Monitoring:: +* Refactors index patterns from configurable to constants {kib-pull}29528[#29528] +* Removes `node_resolver` setting {kib-pull}21181[#21181] +Management:: +* Adds `configPrefix` to Index Management, License Management, Rollup Jobs, and +Upgrade Assistant {kib-pull}30149[#30149] +* Standardizes use of `index_pattern` in UI code and URLs, replacing `indices` +and `index` {kib-pull}29151[#29151] and {kib-pull}29481[#29481] +* Removes app-specific dark mode options and replaces with a global dark mode uiSetting {kib-pull}29017[#29017] +Operations:: +* Defers the optimize step in the plugin installer to server start {kib-pull}26983[#26983] +* Removes tribe node support {kib-pull}16397[#16397] +* Creates separate startup scripts for development and production {kib-pull}13806[#13806] +* Sets default port based on protocol {kib-pull}21564[#21564] +* Removes deprecated `/shorten` API {kib-pull}21861[#21861] +Platform:: +* Removes deprecated `i18n.defaultLocale` setting {kib-pull}29325[#29325] +* Removes previously deprecated `elasticsearch*` settings. {kib-pull}29496[#29496] +* Adds new "references" attribute to saved objects for relationships {kib-pull}28199[#28199] +Reporting:: +* Removes Phantom dependency {kib-pull}27142[#27142] +Security:: +* Removes deprecated SSL settings {kib-pull}28622[#28622] +* Removes legacy fallback {kib-pull}29107[#29107] +Visualizations:: +* Removes Timelion from the app switcher by default {kib-pull}30131[#30131] +* Removes nested table splits from table visualization {kib-pull}26057[#26057] + + +[float] +[[deprecation-7.0.0]] +=== Deprecations + +Geo:: +* Fixes legacy tilemap loading {kib-pull}22095[#22095] +Machine Learning:: +* Updates REST endpoint calls to remove _xpack {kib-pull}28069[#28069] +Visualizations:: +* Removes old visualize wizard URL {kib-pull}28982[#28982] +* Removes legacy response handler {kib-pull}28985[#28985] +* Removes `legacyIcon` from visualizations {kib-pull}28981[#28981] + + +[float] +[[enhancement-7.0.0]] +=== Enhancements +Canvas:: +* Removes WebSockets from Canvas expressions interpreter {kib-pull}29792[#29792] +* Optimizes Canvas REST calls via batching {kib-pull}29847[#29847] +* Implements a clipboard and stores the copied elements in `localStorage` {kib-pull}25890[#25890] +* Adds the ability to reuse assets without editing an element's expression {kib-pull}25764[#25764] +* Adds the `clear` function {kib-pull}26397[#26397] +* Adds workpad-level CSS {kib-pull}24143[#24143] +* Improvements to expression editor {kib-pull}32336[#32336] +* Adds `aria-label` attribute for Color: Auto Color to button inside chart style {kib-pull}32633[#32633] +* Adds `aria-label` attribute for Copy to clipboard {kib-pull}32880[#32880] +Dashboard:: +* Adds `href` option in addition to `onClick` for navigational links {kib-pull}25233[#25233] +Design:: +* Implements a new design for {kib} called K7 +* Updates logos for marketing {kib-pull}25489[#25489] +* Adds Kibana 7.0 breadcrumbs to home screen {kib-pull}26605[#26605] +* Moves elastic/eui typings to single file {kib-pull}23950[#23950] +Discover:: +* Renames the kuery setting to KQL {kib-pull}29587[#29587] +* Adds visual indication of selected language in query bar {kib-pull}30899[#30899] +Logstash:: +* Adopts {es} typeless API for Logstash central management {kib-pull}30546[#30546] +Management:: +* Adds `Request timestamp` to request inspector stats {kib-pull}25667[#25667] +* Adds "Reload indices" button to Index Management {kib-pull}27033[#27033] +Machine Learning:: +* Adds `created_by` field to Auditbeat and APM data recognizer jobs {kib-pull}33863[#33863] +* Adds the time of the anomaly to the `aria-label` of the actions button in each row of the anomalies table {kib-pull}32777[#32777] +* Adds `role="alert"` callouts on the Job Management page to ensure the information is read out by screen readers {kib-pull}32911[#32911] +* Adds EUI `ScreenReaderOnly` component to the "Analyzing data" modal {kib-pull}32472[#32472] +* Updates job type and APM module icon to new designs {kib-pull}25380[#25380] +* Allows model plot enablement via checkbox in MultiMetric/Population Job creation {kib-pull}24914[#24914] +* Adds support for the rare detector for charts in Anomaly Explorer and Singe Metric viewer {kib-pull}21524[#21524] +* Updates HTTP access modules for ECS {kib-pull}29383[#29383] +* Updates auditbeat modules for ECS {kib-pull}29934[#29934] +* Removes non ECS apache, nginx and auditbeat data recognizer modules {kib-pull}30537[#30537] +* Adds the configuration files for two new auditbeat data recognizer modules for +detecting unusual processes on hosts and Docker containers {kib-pull}25716[#25716] +* Adds support for saved searches created using Kuery to the job wizards {kib-pull}26094[#26094] +* Allows users to enter their own query in the Discover page; stops passing the query +from the job datafeed config in custom URLs {kib-pull}26957[#26957] +* Rewrites Calendar to React/EUI {kib-pull}26741[#26741] +* Converts Setting page to React/EUI {kib-pull}27144[#27144] +* Ensures loading indicator is present on initial jobs load {kib-pull}27151[#27151] +* Prevents a new calendar save if a calendar with that id already exists {kib-pull}27104[#27104] +* Edits data recognizer modules to use KQL in saved objects {kib-pull}32766[#32766] +Observability:: +* Converts monitor sparklines to histogram {kib-pull}28502[#28502] +* Adds crosshair sync for monitor page charts {kib-pull}28631[#28631] +* Adds a new plugin for Uptime Monitoring {kib-pull}25480[#25480] +Operations:: +* Adds support for reindexing APM indices {kib-pull}29845[#29845] +* Adds a reindex warning for mapping type changes {kib-pull}32081[#32081] +* Adds warning callout to update APM index pattern {kib-pull}33661[#33661] +Platform:: +* Adds help menu item to header {kib-pull}29664[#29664] +* Implements global dark theme {kib-pull}28445[#28445] +* Removes support for the K6 navigation style {kib-pull}29565[#29565] +* Adds `rest_total_hits_as_int` to all requests in platform code that eventually +look up `hits.total` {kib-pull}26432[#26432] +* Adds `dist` flag to the configuration context {kib-pull}26545[#26545] +* Prepares `@kbn/datemath` to be republished as `@elastic/datemath` {kib-pull}26559[#26559] +* Wraps `remote` methods in `browser` service {kib-pull}26394[#26394] +* Uses `stream.pipeline` to manage error handling {kib-pull}27246[#27246] +Querying & Filtering:: +* Moves the `buildESQuery` module (including filters and Kuery) into a separate package {kib-pull}23345[#23345] +* Adds comment explaining why `getComputedFields` adds a `docvalue` to `docvalue_fields` +for each date field in an index pattern. {kib-pull}25725[#25725] +* Moves filtering functions out of `vis.API.events` {kib-pull}25280[#25280] +Reporting:: +* Adds png output to reports {kib-pull}24759[#24759] +* Sorts ascending on sort order first then ascending on name. Any menu item +without a sort order gets set to zero. {kib-pull}25058[#25058] +* In the Visualization Editor, removes the "Optimize for printing" option when +exporting the visualization as PNG or PDF. The single visualization will automatically +be optimized for printing {kib-pull}30456[#30456] +* Adds browser type to the reporting side panel {kib-pull}26307[#26307] +* Adds better logging for `waitForSelector` failure {kib-pull}25762[#25762] +* Enhances error messaging and handling {kib-pull}26299[#26299] +* Adds "Info" button in the Reporting listing {kib-pull}25421[#25421] +* Adds new inspector for chromium-backed reports {kib-pull}32430[#32430] +Rollups:: +* Adds support for rolling up metrics of date fields {kib-pull}26450[#26450] +Security:: +* Introduces content security policy (CSP) {kib-pull}29545[#29545] +* Warns legacy browsers that do not support content security policy {kib-pull}29957[#29957] +* Adds content security policy strict mode {kib-pull}29856[#29856] +* Updates the GET `/api/security/role` endpoint to return the list of roles sorted +by name, rather than creation date {kib-pull}26491[#26491] +* Updates the Account Settings screen to show the change password form only when +a password change is possible for the authentication realm {kib-pull}26779[#26779] +* Makes space selector a `button` {kib-pull}26889[#26889] +Visualizations:: +* Replaces Angular timepicker with EuiSuperDatePicker {kib-pull}29204[#29204] +* Upgrades Kibana to Elasticsearch 7.0 {kib-pull}29184[#29184] +* Maps inspector requests by id so single requests can be reset at a time {kib-pull}26770[#26770] +* Adds ODBC to blurb for start trail {kib-pull}27223[#27223] +* Adds a `console.error` for visualize errors {kib-pull}24581[#24581] +* Adds a timeout so that Vega respects `elasticsearch.shardTimeout` setting {kib-pull}30482[#30482] +* Removes experimental flag from Visual Builder (TSVB) {kib-pull}25634[#25634] +* Implements new visualization type selection {kib-pull}23833[#23833] +* Removes `lab` stage for visualizations, making `experimental` the only non-production +stage available {kib-pull}25702[#25702] +* Makes markdown consistent across {kib} {kib-pull}31890[#31890] +* Adds option to open links in new tab in Time Series Visual Builder {kib-pull}31906[#31906] +* Adds max, min, placeholder to percentile in Time Series Visual Builder {kib-pull}32389[#32389] +* Displays interval information in Time Series Visual Builder when building {kib-pull}32117[#32117] +* Adds controls to toggle disable/enable individual series and annotations {kib-pull}33107[#33107] +* Updates Vega to version 4 {kib-pull}30628[#30628] + +[float] +[[bug-7.0.0]] +=== Bug fixes +APM:: +* Fixes missing Machine Learning data and NaN issue {kib-pull}34333[#34333] +* Fixes transaction sample on error page {kib-pull}34048[#34048] +* Uses form label for Transaction type selector {kib-pull}28322[#28322] +* Fixes icon for View trace button {kib-pull}28908[#28908] +* Shows metric-only services in service overview {kib-pull}30397[#30397] +* Adds span subtype and action to Span Flyout {kib-pull}30041[#30041] +* Updates head title and fixes breadcrumb string issues {kib-pull}29960[#29960] +* Adds fixes for `service.name` scripted field {kib-pull}28488[#28488] +* Updates APM index pattern {kib-pull}30837[#30837] +* Updates APM reindex script {kib-pull}30761[#30761] +* Sets Index Pattern version as string {kib-pull}30789[#30789] +* Overrides EUI chart default styles for gridlines {kib-pull}21723[#21723] +* Adds section titles to span detail modal {kib-pull}20717[#20717] +* Fixes upgrade assistant label and copy {kib-pull}31750[#31750] +* Changes `context.system.hostname` to `host.hostname` for APM link {kib-pull}30884[#30884] +* Updates APM reindex script {kib-pull}31965[#31965] +* Updates APM index pattern {kib-pull}33595[#33595] +Canvas:: +* Excludes assets from Canvas usage query {kib-pull}34516[#34516] +* Adds datetime as a date identifier {kib-pull}29537[#29537] +* Switches sample web logs fonts to 48px {kib-pull}30747[#30747] +* Fixes related to K7 design {kib-pull}30833[#30833] +* Fixes page preview size issue {kib-pull}26795[#26795] +* Fixes visual bug when opening the workpad loader {kib-pull}26647[#26647] +* Fixes page thumbnail sizes {kib-pull}26573[#26573] +* Decreases size of tray toggle {kib-pull}25470[#25470] +* Makes selection border 1px {kib-pull}26739[#26739] +* Fixes interpreter socket error {kib-pull}26870[#26870] +* Fixes duplicate `Value` options in math select value {kib-pull}25556[#25556] +* Gets correct plugins path {kib-pull}25448[#25448] +* Quotes the index pattern in SQL input {kib-pull}25488[#25488] +* Decreases the size of tray toggle {kib-pull}25470[#25470] +* Fixes the hours label container size {kib-pull}31838[#31838] +* Removes ID attribute {kib-pull}30736[#30736] +* Improves the plugin pre-build {kib-pull}25267[#25267] +Dashboard:: +* Removes `dashboardContext` function and makes Timelion, Vega, and Time Series +Visual Builder use `buildEsQuery` {kib-pull}23227[#23227] +* Shows the filter bar in dashboard embed mode {kib-pull}32222[#32222] +Design:: +* Updates dashboard design {kib-pull}29896[#29896] +* Adjusts side navigation interaction {kib-pull}29978[#29978] +* Converts Security UI from LESS to Sass {kib-pull}25079[#25079] +* Adds boilerplate Sass for Kibana core {kib-pull}21185[#21185] +* Makes dark mode overrides global {kib-pull}31628[#31628] +Discover:: +* Adds debug code to flaky field_data test {kib-pull}15535[#15535] +* Gets even more debug info for flaky field_data test {kib-pull}17627[#17627] +* Allows time ranges before the epoch in Discover {kib-pull}31807[#31807] +* Fixes Kibana Query Language handling of carriage return {kib-pull}32150[#32150] +* Improves warning messages when using Lucene-like syntax {kib-pull}31837[#31837] +* Update capitalization of KQL full name {kib-pull}31631[#31631] +* Adds placeholder text indicating the filters aggregation takes only Lucene and Query DSL {kib-pull}31296[#31296] +* Prevents sending request if it already failed during query parsing {kib-pull}31219[#31219] +* Fixes apps to always migrate legacy queries on state change {kib-pull}33276[#33276] +Geo:: +* Fixes panel cut off in K7 design {kib-pull}29209[#29209] +* Removes left-over geohash grid code {kib-pull}30312[#30312] +* Uses geo-tile aggregation instead of geohash precision {kib-pull}29776[#29776] +* Resolves URL dynamically when requesting EMS data {kib-pull}25685[#25685] +* Fixes EMS hotlink {kib-pull}26868[#26868] +* Fixes feature/align map config settings {kib-pull}19450[#19450] +* Removes `geotile_grid` aggregation from non-geospatial visualizations {kib-pull}31354[#31354] +* Coerces string doc-values to numbers if used in styling {kib-pull}33657[#33657] +Infrastructure:: +* Fixes server-side retrieval of the {kib} version {kib-pull}31440[#31440] +* Fixes react router import {kib-pull}33659[#33659] +* Adapts settings ui to saved object version type change {kib-pull}30082[#30082] +* Fixes potential color bugs {kib-pull}26292[#26292] +* Fixes auto refresh button on node detail page {kib-pull}26426[#26426] +* Changes the time range from the last hour to the last 5 minutes for the Waffle Map {kib-pull}26278[#26278] +* Passes flag in request to force BWC hit count {kib-pull}26517[#26517] +* Replaces redux source slice with constate container {kib-pull}26121[#26121] +* Changes node detail link to set time range to 1 hour {kib-pull}26977[#26977] +* Stops showing sidenav while loading. {kib-pull}27119[#27119] +* Fixes styling after breaking EUI changes {kib-pull}27021[#27021] +* Fixes graphql type generation after package upgrades {kib-pull}26991[#26991] +* Removes usage of `ts-optchain` in the browser {kib-pull}27148[#27148] +Machine Learning:: +* Fixes filter and icon for APM Data Recognizer module {kib-pull}31112[#31112] +* Ensures cardinality related messages in Advanced job wizard are formatted correctly {kib-pull}33599[#33599] +* Adds title elements which were missing from Calendars pages {kib-pull}33257[#33257] +* Changes job wizard query to use `match_all` {kib-pull}32008[#32008] +* Adds calendars list to job management {kib-pull}32566[#32566] +* Fixes Job Selector text to take group selection into account {kib-pull}31333[#31333] +* Ensures that Job Selector description text is accurate {kib-pull}32441[#32441] +* Reduces space between headings in the expanded row for Category examples in Anomalies Table {kib-pull}32417[#32417] +* Removes use of types in datafeeds {kib-pull}27572[#27572] +* Fixes metric select double caret {kib-pull}30357[#30357] +* Removes old angular based start datafeed modal {kib-pull}30392[#30392] +* Handles removal of backend ml.enabled node attribute {kib-pull}27604[#27604] +* Edits labels in the Apache and Nginx ECS data recognizer modules {kib-pull}29935[#29935] +* Fixes for K7 compatibility {kib-pull}30536[#30536] +* Fixes broken label style in advanced wizard {kib-pull}30847[#30847] +* Adds ml-ui team to .github/CODEOWNERS {kib-pull}29810[#29810] +* Allows user to add/edit/delete annotations in the Single Series Viewer {kib-pull}26034[#26034] +* Does not pass datafeed query to Discover in custom URL {kib-pull}26957[#26957] +* Fixes word break in Anomalies and Jobs tables {kib-pull}26978[#26978] +* Fixes alignment of filter icons in the Anomalies table {kib-pull}26253[#26253] +* Shows useful error on invalid query in JobList search bar {kib-pull}25153[#25153] +* Adds user privilege check to Jobs List group selector control {kib-pull}25225[#25225] +* Fixes file data viz file size check and formats as bytes {kib-pull}25295[#25295] +* Fixes the layout of the cards in the Data Visualizer on IE {kib-pull}25383[#25383] +* Adds better error reporting for reading and importing data {kib-pull}24269[#24269] +* Displays an ordinal y axis for low cardinality rare charts {kib-pull}24852[#24852] +* Fixes typo in job validation message {kib-pull}25130[#25130] +* Removes deprecated `angularjs` based jobs list and related code {kib-pull}25216[#25216] +* Skips invalid modules when data recognizer lists matches {kib-pull}33703[#33703] +Management:: +* Filters only on name in Index Management {kib-pull}34372[#34372] +* Removes grunt sterilize - its been replaced by `kbn clean` {kib-pull}27825[#27825] +* Makes Index management table more responsive {kib-pull}28882[#28882] +* Fixes index pattern wizard when there are remote clusters but no local indices {kib-pull}24339[#24339] +* Uses new `_graph` endpoints {kib-pull}26956[#26956] +* Adjusts spacing of Management navigation items {kib-pull}25666[#25666] +* Updates "Disenroll" text to be consistent with menu option "Unenroll" {kib-pull}26816[#26816] +* Fixes broken breadcrumb link for index management {kib-pull}27164[#27164] +* Fixes issue with multiple execution in Console {kib-pull}26933[#26933] +* Reloads full index list when reload hits missing index {kib-pull}27197[#27197] +* Adds boilerplate for remote clusters management app {kib-pull}25369[#25369] +* Adds `ignore_failure` to ingest common auto complete in console {kib-pull}24915[#24915] +* Removes support for expression-based scripted fields {kib-pull}14310[#14310] +* Adds WatchErrors to capture invalid watches {kib-pull}23887[#23887] +* Rewords the translation id for error with missing property in Watcher {kib-pull}24753[#24753] +* Triggers full load when encountering 403 for index list reload {kib-pull}28243[#28243] +* Updates X-Pack console specs {kib-pull}29506[#29506] +* Fixes API integration test for follower indices {kib-pull}30260[#30260] +* Fixes management footer logo spacing bug {kib-pull}30654[#30654] +Monitoring:: +* Updates to read from `.monitoring-*-7-*` indices {kib-pull}32654[#32654] +* Adds in explicit mappings {kib-pull}33004[#33004] +* Stops using the normalized derivative value {kib-pull}27416[#27416] +* Updates the title in the left nav to Stack Monitoring {kib-pull}28102[#28102] +* Prepares the Monitoring UI codebase for the incoming changes to `hits.total` {kib-pull}26442[#26442] +* Updates browser title to Stack Monitoring {kib-pull}29638[#29638] +* Fixes Monitoring design {kib-pull}29479[#29479] +* Removes old index patterns that are not expected in 7.0.0 onwards {kib-pull}27915[#27915] +* Removes deprecated `xpack.monitoring.report_stats` setting {kib-pull}30017[#30017] +* Fixes monitoring tests to work with mapping changes {kib-pull}29188[#29188] +* Removes type filter helper {kib-pull}30887[#30887] +* Fixes error handling for local stats collection/permissions {kib-pull}26560[#26560] +* Removes initial delay to check and send Telemetry data {kib-pull}26575[#26575] +* Pulls local Kibana usage stats {kib-pull}26496[#26496] +* Converts the Elasticsearch monitoring UIs to using EUI tables and page layout {kib-pull}26217[#26217] +* Renames Monitoring `FormattedMessage` to `FormattedAlert` {kib-pull}24197[#24197] +* Uses the cluster name from metadata if it exists {kib-pull}24495[#24495] +Observability:: +* Fixes 7.x references to tcp.port {kib-pull}29132[#29132] +* Ports functional tests to 7.x {kib-pull}29398[#29398] +* Ports unit tests to master {kib-pull}29876[#29876] +* Adds missing loading states for filter bar and snapshot components {kib-pull}30122[#30122] +* Removes double-format for duration value {kib-pull}30664[#30664] +* Switches Uptime localization from i18n provider to context {kib-pull}31601[#31601] +* Improves monitor charts query {kib-pull}30561[#30561] +* Adds global help support to Uptime {kib-pull}31493[#31493] +* Updates targeted index pattern for 7.0.0 {kib-pull}30998[#30998] +Operations:: +* Removes the usage of types from Esqueue used for the `.reporting index` {kib-pull}32146[#32146] +* Fixes IPv6 addresses used with Angular connector {kib-pull}29891[#29891] +* Fixes `makelogs` dependency {kib-pull}31428[#31428] +* Runs the {kib} server in production mode for functional testing {kib-pull}31346[#31346] +* Uses `fs.copyFile` to avoid race condition {kib-pull}32220[#32220] +* Removes `hash -r` {kib-pull}32616[#32616] +* Fixes JUnit reporter {kib-pull}32686[#32686] +* Adds options to `run()` that can modify help and show help on errors {kib-pull}33466[#33466] +* Captures values from boolean flags {kib-pull}33528[#33528] +* Fixes incorrect environment name for V8 options {kib-pull}31052[#31052] +* Removes svg from url-loader, as it conflicts with other loaders {kib-pull}30888[#30888] +* Uses apiVersion from es plugin in x-pack {kib-pull}30853[#30853] +* Clones saved object document before migrating to prevent accidental mutations {kib-pull}30475[#30475] +* Removes node fallback from kibana-keystore {kib-pull}15066[#15066] +* Adds debug script to set inspect flags {kib-pull}15967[#15967] +* Uses snake case for scripts/kibana-keystore.js and scripts/kibana-plugin.js {kib-pull}15331[#15331] +* Updates license info in package.json {kib-pull}20353[#20353] +* Fixes error log formatting {kib-pull}24788[#24788] +* Matches chalk dependency version on Kibana with the one used on X-Pack {kib-pull}20621[#20621] +* Fixes non-conforming licenses on devDependencies and adds the ability to whitelist devOnly licenses {kib-pull}23859[#23859] +* Adds jsxa11y into eslint rules {kib-pull}23932[#23932] +* Reverts Bump react-grid-layout to 0.16.0 {kib-pull}14912[#14912] +* Reverts breaking change for Status API {kib-pull}21927[#21927] +* Converts `utils/collection` to TypeScript {kib-pull}23992[#23992] +* Removes usage of update_all_types {kib-pull}16406[#16406] +* Improves the `yarn kbn bootstrap` speed by using yarn workspaces for packages inside `packages/*` and `x-pack` {kib-pull}24095[#24095] +* Runs jenkins:unit task with dev flag in order to run license check {kib-pull}19832[#19832] +* Does not break on startup in debug mode {kib-pull}19219[#19219] +Platform:: +* Removes types from `saved_objects` repository {kib-pull}32286[#32286] +* Fixes custom icon image paths in `NavDrawer` {kib-pull}33573[#33573] +* Fixes back button navigation {kib-pull}32372[#32372] +* Improves types for ftr and expect.js and cleans up `tsconfig` files {kib-pull}31948[#31948] +* Strips # from hash before updating ``$location` {kib-pull}32732[#32732] +* Removes `disableAutoAngularUrlEncodingFix()`` {kib-pull}33136[#33136] +* Removes unused system-loader implementation {kib-pull}33747[#33747] +* Moves the table vis migration to {kib} plugin {kib-pull}29478[#29478] +* Allows passing a default operator to use on saved object client find operations {kib-pull}29339[#29339] +* Fixes saved object repository `bulkCreate` to return migrated references and attributes {kib-pull}29754[#29754] +* Adds missing saved object reference handling for searchSourceJSON filter attribute {kib-pull}29840[#29840] +* Excludes `migrationVersion` and references from `getRootPropertiesObjects` result {kib-pull}30081[#30081] +* Removes dependency on doc versions {kib-pull}29906[#29906] +* Adds typings for saved object client {kib-pull}29951[#29951] +* Uses `lastSubUrl` when appropriate {kib-pull}28735[#28735] +* Removes es _xpack endpoint usage {kib-pull}29465[#29465] +* Adds typings for the `saved_object_finder` react component {kib-pull}30067[#30067] +* Fixes the confirm overwrite modal of saved objects to handle large titles {kib-pull}28590[#28590] +* Decreases start limit and interval {kib-pull}25474[#25474] +* Adds `--download` flag to snapshot command to warm the cache {kib-pull}25830[#25830] +* Implements `--prefer-offline` flag {kib-pull}25840[#25840] +* Fixes watcher routes broken by Hapi upgrade {kib-pull}26713[#26713] +* Fixes non-conforming licenses on devDependencies and adds the ability to whitelist devOnly licenses {kib-pull}23859[#23859] +* Watches optimizer cache invalidation {kib-pull}24172[#24172] +* Adds `normalizePath` in order to fix watch optimizer when running on Windows {kib-pull}26486[#26486] +* Creates vendor dll for the client modules {kib-pull}22618[#22618] +* Upgrades to NodeJS 10 {kib-pull}25157[#25157] +* Improves plugin version mismatch error message {kib-pull}25774[#25774] +* Improves build/packaging {kib-pull}26096[#26096] +* Swaps `jstimezonedetect` with `moment.tz.guess` {kib-pull}21800[#21800] +* Upgrades resize-observer-polyfill version {kib-pull}26990[#26990] +* Fixes saved objects client `_processBatchQueue` function to handle errors {kib-pull}26763[#26763] +* Changes kbn pm webpack config to generate dist files in mode=none {kib-pull}26847[#26847] +* Hides logs from deleteAll on task: clean client modules into dll {kib-pull}26884[#26884] +* Upgrades `resize-observer-polyfill` version {kib-pull}26990[#26990] +* Uses `single-node` discovery type for the test ES node/cluster {kib-pull}27125[#27125] +* Moves moment to peerDependency in elastic-datemath {kib-pull}27264[#27264] +* Transforms plugin deprecations before checking for unused settings {kib-pull}21294[#21294] +* Expands list of restricted globals in `eslint-config-kibana` {kib-pull}15798[#15798] +* Makes logs easier to read on Windows with chalk colors {kib-pull}15557[#15557] +* Fixes `includeFields` function to return root saved object properties {kib-pull}33847[#33847] +Reporting:: +* Refactors routes files and helpers {kib-pull}30111[#30111] +* Deletes `sortOrder` once items have been sorted and does not pass to `EuiContextMenuItem` +in the share context menu {kib-pull}26890[#26890] +* Fixes a regression bug in detection of Error and Warning toast notifications {kib-pull}25482[#25482] +* Stops passing an empty `formatConfig` to the fieldFormats helper {kib-pull}27168[#27168] +* Returns promise in Reporting jobs API {kib-pull}24769[#24769] +* Uses `content-disposition` package for non-US font titles in reporting {kib-pull}30895[#30895] +* Uses lowercased server host settings {kib-pull}33020[#33020] +Rollups:: +* Shows loading state in Rollup Job detail panel. {kib-pull}25752[#25752] +* Specifies Rollup Jobs breadcrumbs in header. {kib-pull}26590[#26590] +* Requires histogram interval in Rollup Job wizard to be a whole number. {kib-pull}26596[#26596] +* Removes duplicate rendered sections {kib-pull}[#28566] +Security:: +* Adds tests for interpreter `createSocket` {kib-pull}29459[#29459] +* Moves the server-side `SavedObjectClient` types from the `spaces` plugin to the +same location as the corresponding JavaScript source files {kib-pull}26448[#26448] +* Respects the `basePath` for the link to the user profile in the k7 header {kib-pull}26417[#26417] +* Fixes `prettier` throw rule error {kib-pull}26071[#26071] +* Fixes authentication logic to fail out of auth flow on first provider failure {kib-pull}26648[#26648] +* Fixes issues with the `url.search` being null in Node 10 {kib-pull}26992[#26992] +* Fixes DLS query toggle on the role management page {kib-pull}27213[#27213] +* Implements the K7 login screen {kib-pull}23512[#23512] +Visualizations:: +* Fixes missing column totals in data table {kib-pull}34169[#34169] +* Hides gauge labels when value is hidden {kib-pull}34171[#34171] +* Changes sample data sets to use `auto_expand_replicas` of `0-1` for added data +resiliency and ease of administration {kib-pull}33736[#33736] +* Fixes broken CSV export from data table {kib-pull}34131[#34131] +* Hides gauge labels when value is hidden {kib-pull}34171[#34171] +* Removes dangerously set inner HTML {kib-pull}33976[#33976] +* Fixes gauge filters {kib-pull}30057[#30057] +* Fixes fieldformatter calls in pipeline helper {kib-pull}29842[#29842] +* Adds pipeline field formatting {kib-pull}28746[#28746] +* Removes `kibana_table` pipeline type {kib-pull}28979[#28979] +* Moves renderers registry to OSS {kib-pull}28986[#28986] +* Prepares for cut over to the visualize data loader from the current expression +pipeline data loader {kib-pull}29873[#29873] +* Toggles between Expression Pipeline & Visualize Data loader {kib-pull}29874[#29874] +* Fixes every app that was wrapping `query` in an array unnecessarily {kib-pull}27636[#27636] +* Fixes build issue and reintroduces new filter bar {kib-pull}29752[#29752] +* Adds index pattern URL change notes {kib-pull}30779[#30779] +* Fixes visualization filters to ignore invalid entries {kib-pull}30633[#30633] +* Expands the size of add panels flyout and increases default rows per page {kib-pull}30508[#30508] +* Fixes support for React 16.4+ by only resetting state if adaptors are updated {kib-pull}26138[#26138] +* Fixes scrolling list on Firefox {kib-pull}26246[#26246] +* Guards against empty and undefined index pattern arrays passed to QueryBar {kib-pull}24607[#24607] +* Removes unused indexPattern from vega/tsvb/timelion request handler {kib-pull}26007[#26007] +* Passes global filters from editor down to visualize {kib-pull}26009[#26009] +* Stops using schemas in aggconfigs to output DSL {kib-pull}26010[#26010] +* Fixes `kbn-interpreter` package to not import from UI {kib-pull}26161[#26161] +* Fixes OSS dynamic plugin loading by reverting to Canvas way of loading plugins {kib-pull}26463[#26463] +* Fixes other bucket option to correctly apply without having to change other settings {kib-pull}26874[#26874] +* Adds `en` as a valid numeral locale setting {kib-pull}25948[#25948] +* Adds `rest_total_hits_as_int` into Kibana App {kib-pull}26404[#26404] +* Uses Canvas pipeline to fetch data inside Visualize {kib-pull}25996[#25996] +* Adds warning to the `documentation_links` file about link validation gotcha {kib-pull}24786[#24786] +* Adds workaround for `getDerivedStateFromProps` change in react 16.4 {kib-pull}25142[#25142] +* Fixes "Set up index patterns" link on home page {kib-pull}16128[#16128] +* Fixes Time Series Visual Builder so that auto apply changes on every click {kib-pull}33710[#33710] +* Removes the `geo_centroid` and `geo_bounds` aggregations from nested metrics {kib-pull}34042[#34042] +* Replaces deprecated `moving_avg` by `moving_fn` aggregation {kib-pull}34155[#34155] +* Adds autocomplete to Time Series Visual Builder {kib-pull}30158[#30158] +* Fixes missing Markdown variables {kib-pull}28173[#28173] +* Removes filter bar for Markdown visualizations {kib-pull}30354[#30354] +* Corrects label for OS visualization in logs sample data {kib-pull}30249[#30249] +* Fixes filter function on pie chart segment {kib-pull}26321[#26321] +* Rewrites URL when closing vis type selection modal {kib-pull}26327[#26327] +* Changes unbind calls from `.on` to `.off` {kib-pull}24575[#24575] +* Fixes date field in controls visualization by generating labels with the field +formatter {kib-pull}25654[#25654] +* Replaces LESS files with Sass in `ui/public/vis`, `visLib`, and `visualize` {kib-pull}25333[#25333] +* Replaces LESS files with Sass for the visualization types in `core_plugin/metrics` {kib-pull}24250[#24250] +* Moves `timeout` to `_msearch` body to fix time series visual builder requests {kib-pull}26510[#26510] +* Adds description for all visualization types {kib-pull}26243[#26243] +* Defaults the scroll wheel zoom to false on Vega maps {kib-pull}21169[#21169] +* Fixes problem within the input_vis_control plugin that prevents it from updating correctly +if the field is switched, and then switched back to the previous field {kib-pull}25164[#25164] +* Uses `vega-nocanvas` instead of Vega lib {kib-pull}16137[#16137] +* Migrates visualization from Angular to React {kib-pull}16425[#16425] +* Fixes maps for reporting (#15272) {kib-pull}15358[#15358] +* Stops creation of nested search source per postflightrequest {kib-pull}20373[#20373] +* Moves inspector code from Vis to embeddable visualize handler {kib-pull}24112[#24112] +* Removes inspector from Vis {kib-pull}24112[#24112] +* Fixes issue with debounce function running after component was unmounted {kib-pull}15045[#15045] +* Fixes for dark mode fixes for Visualize charts, Time Series Visual Builder, and Timelion {kib-pull}30478[#30478] +* Fixes geohash checkbox group spacing {kib-pull}32664[#32664] +* Removes deep clone from courier request handler {kib-pull}32806[#32806] +* Ensures saved filters from `searchSource` are always passed to response handlers {kib-pull}33074[#33074] +* Adds new visualization search selection {kib-pull}30196[#30196] +* Changes visualization save dialog when adding to dashboard {kib-pull}32883[#32883] +* Fixes missing variables preview in Time Series Visual Builder markdown {kib-pull}30830[#30830] +* Fixes incorrect behavior when filling the 'interval' field with values: s,m,d,M,y {kib-pull}32542[#32542] +* Fixes multi-metric gauge with vertical sizing {kib-pull}33245[#33245] +* Fixes Time Series Visual Builder display on small screen resolution {kib-pull}33299[#33299] +* Fixes Time Series Visual Builder metric and gauge panels when splitting data by numbers {kib-pull}33304[#33304] +* Fixes Time Series Visual Builder percentile ranks with integer values that return no results {kib-pull}33397[#33397] +* Fixes Time Series Visual Builder issue with table view {kib-pull}33645[#33645] +* Fixes Time Series Visual Builder issue with wrong color rules on multiple metrics {kib-pull}31455[#31455] +* Fixes Time Series Visual Builder issue with percentiles for table {kib-pull}32084[#32084] +* Switches all Time Series Visual Builder comboboxes to plain text single selection {kib-pull}31879[#31879] +* Fixes table visualization to format date string when grouping by date field {kib-pull}31783[#31783] +* Adds flex wrap to metric visualization container {kib-pull}31891[#31891] +* Fixes missing axis labels when moving position {kib-pull}32628[#32628] +* Fixes vislib legend entry width {kib-pull}33303[#33303] +* Fixes legend / color picker overflow {kib-pull}30960[#30960] +* Fixes total Metric Count inside donut pie charts {kib-pull}29086[#29086] +* Adds labels for sort order and request preference setting {kib-pull}31236[#31236] +* Fixes time picker quick ranges description {kib-pull}32455[#32455] +* Adds check for `extraMetric` in point server tooltip hovers {kib-pull}32641[#32641] +* Switches sample data objects to KQL {kib-pull}32718[#32718] +* Migrate visualization controls to use references {kib-pull}30880[#30880] +* Dedupes by index pattern ID rather than object identity {kib-pull}32350[#32350] +* Ensures extra columns are not shown in table visualization when `showPartialRows:true` {kib-pull}27154[#27154] +* Uses default index pattern when one is not present in Visualize {kib-pull}30574[#30574] +* Surfaces visualization loader errors in the UI {kib-pull}30594[#30594] + + + + + + +[[release-notes-7.0.0-rc2]] +== {kib} 7.0.0-rc2 + +[float] +=== Known issues + +Monitoring:: +* If you have a version 7.0 monitoring cluster, a version 6.7 production +cluster and {kib} version 6.7.0 or 6.7.1, you cannot see the monitoring data in +{kib}. {kib-issue}34357[#34357] + +[float] +[[breaking-7.0.0-rc2]] +=== Breaking changes + +For more details about breaking changes in this release, see +<>. + +Discover:: +* Allows user to use advanced query DSL directly, and does not apply `query:queryString:options` to `query_string` filters automatically {kib-pull}15640[#15640] +* Removes `default_field` from `query:queryString:options` {kib-pull}18966[#18966] +* Makes KQL the default query language for new searches {kib-pull}27092[#27092] +Design:: +* Removes references to K6 EUI, using the default UI theme in its place {kib-pull}29152[#29152] +Geo:: +* Removes the deprecated `regionmap` and `tilemap` kibana.yml configurations. +Removes the backwards compatibility logic that checked for duplicative settings +`map.regionmap` and `map.tilemap`. {kib-pull}28609[#28609] +Monitoring:: +* Refactors index patterns from configurable to constants {kib-pull}29528[#29528] +* Removes `node_resolver` setting {kib-pull}21181[#21181] +Management:: +* Adds `configPrefix` to Index Management, License Management, Rollup Jobs, and +Upgrade Assistant {kib-pull}30149[#30149] +* Removes nested table splits from table visualization {kib-pull}26057[#26057] +* Standardizes use of `index_pattern` in UI code and URLs, replacing `indices` +and `index` {kib-pull}29151[#29151] and {kib-pull}29481[#29481] +* Removes app-specific dark mode options and replaces with a global dark mode uiSetting {kib-pull}29017[#29017] +Operations:: +* Defers the optimize step in the plugin installer to server start {kib-pull}26983[#26983] +* Removes tribe node support {kib-pull}16397[#16397] +* Creates separate startup scripts for development and production {kib-pull}13806[#13806] +* Sets default port based on protocol {kib-pull}21564[#21564] +* Removes deprecated `/shorten` API {kib-pull}21861[#21861] +Platform:: +* Removes deprecated `i18n.defaultLocale` setting {kib-pull}29325[#29325] +* Removes previously deprecated `elasticsearch*` settings. {kib-pull}29496[#29496] +* Adds new "references" attribute to saved objects for relationships {kib-pull}28199[#28199] +Reporting:: +* Removes Phantom dependency {kib-pull}27142[#27142] +Security:: +* Removes deprecated SSL settings {kib-pull}28622[#28622] +* Removes legacy fallback {kib-pull}29107[#29107] +Visualizations:: +* Removes Timelion from the app switcher by default {kib-pull}30131[#30131] + + +[float] +[[deprecation-7.0.0-rc2]] +=== Deprecations + +Geo:: +* Fixes legacy tilemap loading {kib-pull}22095[#22095] +Machine Learning:: +* Updates REST endpoint calls to remove _xpack {kib-pull}28069[#28069] +Visualizations:: +* Removes old visualize wizard URL {kib-pull}28982[#28982] +* Removes legacy response handler {kib-pull}28985[#28985] +* Removes `legacyIcon` from visualizations {kib-pull}28981[#28981] + + +[float] +[[enhancement-7.0.0-rc2]] +=== Enhancements +Canvas:: +* Removes WebSockets from Canvas expressions interpreter {kib-pull}29792[#29792] +* Optimizes Canvas REST calls via batching {kib-pull}29847[#29847] +* Implements a clipboard and stores the copied elements in `localStorage` {kib-pull}25890[#25890] +* Adds the ability to reuse assets without editing an element's expression {kib-pull}25764[#25764] +* Adds the `clear` function {kib-pull}26397[#26397] +* Adds workpad-level CSS {kib-pull}24143[#24143] +* Improvements to expression editor {kib-pull}32336[#32336] +* Adds `aria-label` attribute for Color: Auto Color to button inside chart style {kib-pull}32633[#32633] +* Adds `aria-label` attribute for Copy to clipboard {kib-pull}32880[#32880] +Dashboard:: +* Adds `href` option in addition to `onClick` for navigational links {kib-pull}25233[#25233] +Design:: +* Implements a new design for {kib} called K7 +* Updates logos for marketing {kib-pull}25489[#25489] +* Adds Kibana 7.0 breadcrumbs to home screen {kib-pull}26605[#26605] +* Moves elastic/eui typings to single file {kib-pull}23950[#23950] +Discover:: +* Renames the kuery setting to KQL {kib-pull}29587[#29587] +* Adds visual indication of selected language in query bar {kib-pull}30899[#30899] +Logstash:: +* Adopts {es} typeless API for Logstash central management {kib-pull}30546[#30546] +Management:: +* Adds `Request timestamp` to request inspector stats {kib-pull}25667[#25667] +* Adds "Reload indices" button to Index Management {kib-pull}27033[#27033] +Machine Learning:: +* Adds `created_by` field to Auditbeat and APM data recognizer jobs {kib-pull}33863[#33863] +* Adds the time of the anomaly to the `aria-label` of the actions button in each row of the anomalies table {kib-pull}32777[#32777] +* Adds `role="alert"` callouts on the Job Management page to ensure the information is read out by screen readers {kib-pull}32911[#32911] +* Adds EUI `ScreenReaderOnly` component to the "Analyzing data" modal {kib-pull}32472[#32472] +* Updates job type and APM module icon to new designs {kib-pull}25380[#25380] +* Allows model plot enablement via checkbox in MultiMetric/Population Job creation {kib-pull}24914[#24914] +* Adds support for the rare detector for charts in Anomaly Explorer and Singe Metric viewer {kib-pull}21524[#21524] +* Updates HTTP access modules for ECS {kib-pull}29383[#29383] +* Updates auditbeat modules for ECS {kib-pull}29934[#29934] +* Removes non ECS apache, nginx and auditbeat data recognizer modules {kib-pull}30537[#30537] +* Adds the configuration files for two new auditbeat data recognizer modules for +detecting unusual processes on hosts and Docker containers {kib-pull}25716[#25716] +* Adds support for saved searches created using Kuery to the job wizards {kib-pull}26094[#26094] +* Allows users to enter their own query in the Discover page; stops passing the query +from the job datafeed config in custom URLs {kib-pull}26957[#26957] +* Rewrites Calendar to React/EUI {kib-pull}26741[#26741] +* Converts Setting page to React/EUI {kib-pull}27144[#27144] +* Ensures loading indicator is present on initial jobs load {kib-pull}27151[#27151] +* Prevents a new calendar save if a calendar with that id already exists {kib-pull}27104[#27104] +* Edits data recognizer modules to use KQL in saved objects {kib-pull}32766[#32766] +Observability:: +* Converts monitor sparklines to histogram {kib-pull}28502[#28502] +* Adds crosshair sync for monitor page charts {kib-pull}28631[#28631] +* Adds a new plugin for Uptime Monitoring {kib-pull}25480[#25480] +Operations:: +* Adds support for reindexing APM indices {kib-pull}29845[#29845] +* Adds a reindex warning for mapping type changes {kib-pull}32081[#32081] +* Adds warning callout to update APM index pattern {kib-pull}33661[#33661] +Platform:: +* Adds help menu item to header {kib-pull}29664[#29664] +* Implements global dark theme {kib-pull}28445[#28445] +* Removes support for the K6 navigation style {kib-pull}29565[#29565] +* Adds `rest_total_hits_as_int` to all requests in platform code that eventually +look up `hits.total` {kib-pull}26432[#26432] +* Adds `dist` flag to the configuration context {kib-pull}26545[#26545] +* Prepares `@kbn/datemath` to be republished as `@elastic/datemath` {kib-pull}26559[#26559] +* Wraps `remote` methods in `browser` service {kib-pull}26394[#26394] +* Uses `stream.pipeline` to manage error handling {kib-pull}27246[#27246] +Querying & Filtering:: +* Moves the `buildESQuery` module (including filters and Kuery) into a separate package {kib-pull}23345[#23345] +* Adds comment explaining why `getComputedFields` adds a `docvalue` to `docvalue_fields` +for each date field in an index pattern. {kib-pull}25725[#25725] +* Moves filtering functions out of `vis.API.events` {kib-pull}25280[#25280] +Reporting:: +* Adds png output to reports {kib-pull}24759[#24759] +* Sorts ascending on sort order first then ascending on name. Any menu item +without a sort order gets set to zero. {kib-pull}25058[#25058] +* In the Visualization Editor, removes the "Optimize for printing" option when +exporting the visualization as PNG or PDF. The single visualization will automatically +be optimized for printing {kib-pull}30456[#30456] +* Adds browser type to the reporting side panel {kib-pull}26307[#26307] +* Adds better logging for `waitForSelector` failure {kib-pull}25762[#25762] +* Enhances error messaging and handling {kib-pull}26299[#26299] +* Adds "Info" button in the Reporting listing {kib-pull}25421[#25421] +* Adds new inspector for chromium-backed reports {kib-pull}32430[#32430] +Rollups:: +* Adds support for rolling up metrics of date fields {kib-pull}26450[#26450] +Security:: +* Introduces content security policy (CSP) {kib-pull}29545[#29545] +* Warns legacy browsers that do not support content security policy {kib-pull}29957[#29957] +* Adds content security policy strict mode {kib-pull}29856[#29856] +* Updates the GET `/api/security/role` endpoint to return the list of roles sorted +by name, rather than creation date {kib-pull}26491[#26491] +* Updates the Account Settings screen to show the change password form only when +a password change is possible for the authentication realm {kib-pull}26779[#26779] +* Makes space selector a `button` {kib-pull}26889[#26889] +Visualizations:: +* Replaces Angular timepicker with EuiSuperDatePicker {kib-pull}29204[#29204] +* Upgrades Kibana to Elasticsearch 7.0 {kib-pull}29184[#29184] +* Maps inspector requests by id so single requests can be reset at a time {kib-pull}26770[#26770] +* Adds ODBC to blurb for start trail {kib-pull}27223[#27223] +* Adds a `console.error` for visualize errors {kib-pull}24581[#24581] +* Adds a timeout so that Vega respects `elasticsearch.shardTimeout` setting {kib-pull}30482[#30482] +* Removes experimental flag from Visual Builder (TSVB) {kib-pull}25634[#25634] +* Implements new visualization type selection {kib-pull}23833[#23833] +* Removes `lab` stage for visualizations, making `experimental` the only non-production +stage available {kib-pull}25702[#25702] +* Makes markdown consistent across {kib} {kib-pull}31890[#31890] +* Adds option to open links in new tab in Time Series Visual Builder {kib-pull}31906[#31906] +* Adds max, min, placeholder to percentile in Time Series Visual Builder {kib-pull}32389[#32389] +* Displays interval information in Time Series Visual Builder when building {kib-pull}32117[#32117] +* Adds controls to toggle disable/enable individual series and annotations {kib-pull}33107[#33107] +* Updates Vega to version 4 {kib-pull}30628[#30628] + +[float] +[[bug-7.0.0-rc2]] +=== Bug fixes +APM:: +* Fixes transaction sample on error page {kib-pull}34048[#34048] +* Uses form label for Transaction type selector {kib-pull}28322[#28322] +* Fixes icon for View trace button {kib-pull}28908[#28908] +* Shows metric-only services in service overview {kib-pull}30397[#30397] +* Adds span subtype and action to Span Flyout {kib-pull}30041[#30041] +* Updates head title and fixes breadcrumb string issues {kib-pull}29960[#29960] +* Adds fixes for `service.name` scripted field {kib-pull}28488[#28488] +* Updates APM index pattern {kib-pull}30837[#30837] +* Updates APM reindex script {kib-pull}30761[#30761] +* Sets Index Pattern version as string {kib-pull}30789[#30789] +* Overrides EUI chart default styles for gridlines {kib-pull}21723[#21723] +* Adds section titles to span detail modal {kib-pull}20717[#20717] +* Fixes upgrade assistant label and copy {kib-pull}31750[#31750] +* Changes `context.system.hostname` to `host.hostname` for APM link {kib-pull}30884[#30884] +* Updates APM reindex script {kib-pull}31965[#31965] +* Updates APM index pattern {kib-pull}33595[#33595] +Canvas:: +* Adds datetime as a date identifier {kib-pull}29537[#29537] +* Switches sample web logs fonts to 48px {kib-pull}30747[#30747] +* Fixes related to K7 design {kib-pull}30833[#30833] +* Fixes page preview size issue {kib-pull}26795[#26795] +* Fixes visual bug when opening the workpad loader {kib-pull}26647[#26647] +* Fixes page thumbnail sizes {kib-pull}26573[#26573] +* Decreases size of tray toggle {kib-pull}25470[#25470] +* Makes selection border 1px {kib-pull}26739[#26739] +* Fixes interpreter socket error {kib-pull}26870[#26870] +* Fixes duplicate `Value` options in math select value {kib-pull}25556[#25556] +* Gets correct plugins path {kib-pull}25448[#25448] +* Quotes the index pattern in SQL input {kib-pull}25488[#25488] +* Decreases the size of tray toggle {kib-pull}25470[#25470] +* Fixes the hours label container size {kib-pull}31838[#31838] +* Removes ID attribute {kib-pull}30736[#30736] +* Improves the plugin pre-build {kib-pull}25267[#25267] +Dashboard:: +* Removes `dashboardContext` function and makes Timelion, Vega, and Time Series +Visual Builder use `buildEsQuery` {kib-pull}23227[#23227] +* Shows the filter bar in dashboard embed mode {kib-pull}32222[#32222] +Design:: +* Updates dashboard design {kib-pull}29896[#29896] +* Adjusts side navigation interaction {kib-pull}29978[#29978] +* Converts Security UI from LESS to Sass {kib-pull}25079[#25079] +* Adds boilerplate Sass for Kibana core {kib-pull}21185[#21185] +* Makes dark mode overrides global {kib-pull}31628[#31628] +Discover:: +* Adds debug code to flaky field_data test {kib-pull}15535[#15535] +* Gets even more debug info for flaky field_data test {kib-pull}17627[#17627] +* Allows time ranges before the epoch in Discover {kib-pull}31807[#31807] +* Fixes Kibana Query Language handling of carriage return {kib-pull}32150[#32150] +* Improves warning messages when using Lucene-like syntax {kib-pull}31837[#31837] +* Update capitalization of KQL full name {kib-pull}31631[#31631] +* Adds placeholder text indicating the filters aggregation takes only Lucene and Query DSL {kib-pull}31296[#31296] +* Prevents sending request if it already failed during query parsing {kib-pull}31219[#31219] +* Fixes apps to always migrate legacy queries on state change {kib-pull}33276[#33276] +Geo:: +* Fixes panel cut off in K7 design {kib-pull}29209[#29209] +* Removes left-over geohash grid code {kib-pull}30312[#30312] +* Uses geo-tile aggregation instead of geohash precision {kib-pull}29776[#29776] +* Resolves URL dynamically when requesting EMS data {kib-pull}25685[#25685] +* Fixes EMS hotlink {kib-pull}26868[#26868] +* Fixes feature/align map config settings {kib-pull}19450[#19450] +* Removes `geotile_grid` aggregation from non-geospatial visualizations {kib-pull}31354[#31354] +* Coerces string doc-values to numbers if used in styling {kib-pull}33657[#33657] +Infrastructure:: +* Fixes server-side retrieval of the {kib} version {kib-pull}31440[#31440] +* Fixes react router import {kib-pull}33659[#33659] +* Adapts settings ui to saved object version type change {kib-pull}30082[#30082] +* Fixes potential color bugs {kib-pull}26292[#26292] +* Fixes auto refresh button on node detail page {kib-pull}26426[#26426] +* Changes the time range from the last hour to the last 5 minutes for the Waffle Map {kib-pull}26278[#26278] +* Passes flag in request to force BWC hit count {kib-pull}26517[#26517] +* Replaces redux source slice with constate container {kib-pull}26121[#26121] +* Changes node detail link to set time range to 1 hour {kib-pull}26977[#26977] +* Stops showing sidenav while loading. {kib-pull}27119[#27119] +* Fixes styling after breaking EUI changes {kib-pull}27021[#27021] +* Fixes graphql type generation after package upgrades {kib-pull}26991[#26991] +* Removes usage of `ts-optchain` in the browser {kib-pull}27148[#27148] +Machine Learning:: +* Fixes filter and icon for APM Data Recognizer module {kib-pull}31112[#31112] +* Ensures cardinality related messages in Advanced job wizard are formatted correctly {kib-pull}33599[#33599] +* Adds title elements which were missing from Calendars pages {kib-pull}33257[#33257] +* Changes job wizard query to use `match_all` {kib-pull}32008[#32008] +* Adds calendars list to job management {kib-pull}32566[#32566] +* Fixes Job Selector text to take group selection into account {kib-pull}31333[#31333] +* Ensures that Job Selector description text is accurate {kib-pull}32441[#32441] +* Reduces space between headings in the expanded row for Category examples in Anomalies Table {kib-pull}32417[#32417] +* Removes use of types in datafeeds {kib-pull}27572[#27572] +* Fixes metric select double caret {kib-pull}30357[#30357] +* Removes old angular based start datafeed modal {kib-pull}30392[#30392] +* Handles removal of backend ml.enabled node attribute {kib-pull}27604[#27604] +* Edits labels in the Apache and Nginx ECS data recognizer modules {kib-pull}29935[#29935] +* Fixes for K7 compatibility {kib-pull}30536[#30536] +* Fixes broken label style in advanced wizard {kib-pull}30847[#30847] +* Adds ml-ui team to .github/CODEOWNERS {kib-pull}29810[#29810] +* Allows user to add/edit/delete annotations in the Single Series Viewer {kib-pull}26034[#26034] +* Does not pass datafeed query to Discover in custom URL {kib-pull}26957[#26957] +* Fixes word break in Anomalies and Jobs tables {kib-pull}26978[#26978] +* Fixes alignment of filter icons in the Anomalies table {kib-pull}26253[#26253] +* Shows useful error on invalid query in JobList search bar {kib-pull}25153[#25153] +* Adds user privilege check to Jobs List group selector control {kib-pull}25225[#25225] +* Fixes file data viz file size check and formats as bytes {kib-pull}25295[#25295] +* Fixes the layout of the cards in the Data Visualizer on IE {kib-pull}25383[#25383] +* Adds better error reporting for reading and importing data {kib-pull}24269[#24269] +* Displays an ordinal y axis for low cardinality rare charts {kib-pull}24852[#24852] +* Fixes typo in job validation message {kib-pull}25130[#25130] +* Removes deprecated `angularjs` based jobs list and related code {kib-pull}25216[#25216] +* Skips invalid modules when data recognizer lists matches {kib-pull}33703[#33703] +Management:: +* Removes grunt sterilize - its been replaced by `kbn clean` {kib-pull}27825[#27825] +* Makes Index management table more responsive {kib-pull}28882[#28882] +* Fixes index pattern wizard when there are remote clusters but no local indices {kib-pull}24339[#24339] +* Uses new `_graph` endpoints {kib-pull}26956[#26956] +* Adjusts spacing of Management navigation items {kib-pull}25666[#25666] +* Updates "Disenroll" text to be consistent with menu option "Unenroll" {kib-pull}26816[#26816] +* Fixes broken breadcrumb link for index management {kib-pull}27164[#27164] +* Fixes issue with multiple execution in Console {kib-pull}26933[#26933] +* Reloads full index list when reload hits missing index {kib-pull}27197[#27197] +* Adds boilerplate for remote clusters management app {kib-pull}25369[#25369] +* Adds `ignore_failure` to ingest common auto complete in console {kib-pull}24915[#24915] +* Removes support for expression-based scripted fields {kib-pull}14310[#14310] +* Adds WatchErrors to capture invalid watches {kib-pull}23887[#23887] +* Rewords the translation id for error with missing property in Watcher {kib-pull}24753[#24753] +* Triggers full load when encountering 403 for index list reload {kib-pull}28243[#28243] +* Updates X-Pack console specs {kib-pull}29506[#29506] +* Fixes API integration test for follower indices {kib-pull}30260[#30260] +* Fixes management footer logo spacing bug {kib-pull}30654[#30654] +Monitoring:: +* Updates to read from `.monitoring-*-7-*` indices {kib-pull}32654[#32654] +* Adds in explicit mappings {kib-pull}33004[#33004] +* Stops using the normalized derivative value {kib-pull}27416[#27416] +* Updates the title in the left nav to Stack Monitoring {kib-pull}28102[#28102] +* Prepares the Monitoring UI codebase for the incoming changes to `hits.total` {kib-pull}26442[#26442] +* Updates browser title to Stack Monitoring {kib-pull}29638[#29638] +* Fixes Monitoring design {kib-pull}29479[#29479] +* Removes old index patterns that are not expected in 7.0.0 onwards {kib-pull}27915[#27915] +* Removes deprecated `xpack.monitoring.report_stats` setting {kib-pull}30017[#30017] +* Fixes monitoring tests to work with mapping changes {kib-pull}29188[#29188] +* Removes type filter helper {kib-pull}30887[#30887] +* Fixes error handling for local stats collection/permissions {kib-pull}26560[#26560] +* Removes initial delay to check and send Telemetry data {kib-pull}26575[#26575] +* Pulls local Kibana usage stats {kib-pull}26496[#26496] +* Converts the Elasticsearch monitoring UIs to using EUI tables and page layout {kib-pull}26217[#26217] +* Renames Monitoring `FormattedMessage` to `FormattedAlert` {kib-pull}24197[#24197] +* Uses the cluster name from metadata if it exists {kib-pull}24495[#24495] +Observability:: +* Fixes 7.x references to tcp.port {kib-pull}29132[#29132] +* Ports functional tests to 7.x {kib-pull}29398[#29398] +* Ports unit tests to master {kib-pull}29876[#29876] +* Adds missing loading states for filter bar and snapshot components {kib-pull}30122[#30122] +* Removes double-format for duration value {kib-pull}30664[#30664] +* Switches Uptime localization from i18n provider to context {kib-pull}31601[#31601] +* Improves monitor charts query {kib-pull}30561[#30561] +* Adds global help support to Uptime {kib-pull}31493[#31493] +* Updates targeted index pattern for 7.0.0 {kib-pull}30998[#30998] +Operations:: +* Removes the usage of types from Esqueue used for the `.reporting index` {kib-pull}32146[#32146] +* Fixes IPv6 addresses used with Angular connector {kib-pull}29891[#29891] +* Fixes `makelogs` dependency {kib-pull}31428[#31428] +* Runs the {kib} server in production mode for functional testing {kib-pull}31346[#31346] +* Uses `fs.copyFile` to avoid race condition {kib-pull}32220[#32220] +* Removes `hash -r` {kib-pull}32616[#32616] +* Fixes JUnit reporter {kib-pull}32686[#32686] +* Adds options to `run()` that can modify help and show help on errors {kib-pull}33466[#33466] +* Captures values from boolean flags {kib-pull}33528[#33528] +* Fixes incorrect environment name for V8 options {kib-pull}31052[#31052] +* Removes svg from url-loader, as it conflicts with other loaders {kib-pull}30888[#30888] +* Uses apiVersion from es plugin in x-pack {kib-pull}30853[#30853] +* Clones saved object document before migrating to prevent accidental mutations {kib-pull}30475[#30475] +* Removes node fallback from kibana-keystore {kib-pull}15066[#15066] +* Adds debug script to set inspect flags {kib-pull}15967[#15967] +* Uses snake case for scripts/kibana-keystore.js and scripts/kibana-plugin.js {kib-pull}15331[#15331] +* Updates license info in package.json {kib-pull}20353[#20353] +* Fixes error log formatting {kib-pull}24788[#24788] +* Matches chalk dependency version on Kibana with the one used on X-Pack {kib-pull}20621[#20621] +* Fixes non-conforming licenses on devDependencies and adds the ability to whitelist devOnly licenses {kib-pull}23859[#23859] +* Adds jsxa11y into eslint rules {kib-pull}23932[#23932] +* Reverts Bump react-grid-layout to 0.16.0 {kib-pull}14912[#14912] +* Reverts breaking change for Status API {kib-pull}21927[#21927] +* Converts `utils/collection` to TypeScript {kib-pull}23992[#23992] +* Removes usage of update_all_types {kib-pull}16406[#16406] +* Improves the `yarn kbn bootstrap` speed by using yarn workspaces for packages inside `packages/*` and `x-pack` {kib-pull}24095[#24095] +* Runs jenkins:unit task with dev flag in order to run license check {kib-pull}19832[#19832] +* Does not break on startup in debug mode {kib-pull}19219[#19219] +Platform:: +* Removes types from `saved_objects` repository {kib-pull}32286[#32286] +* Fixes custom icon image paths in `NavDrawer` {kib-pull}33573[#33573] +* Fixes back button navigation {kib-pull}32372[#32372] +* Improves types for ftr and expect.js and cleans up `tsconfig` files {kib-pull}31948[#31948] +* Strips # from hash before updating ``$location` {kib-pull}32732[#32732] +* Removes `disableAutoAngularUrlEncodingFix()`` {kib-pull}33136[#33136] +* Removes unused system-loader implementation {kib-pull}33747[#33747] +* Moves the table vis migration to {kib} plugin {kib-pull}29478[#29478] +* Allows passing a default operator to use on saved object client find operations {kib-pull}29339[#29339] +* Fixes saved object repository `bulkCreate` to return migrated references and attributes {kib-pull}29754[#29754] +* Adds missing saved object reference handling for searchSourceJSON filter attribute {kib-pull}29840[#29840] +* Excludes `migrationVersion` and references from `getRootPropertiesObjects` result {kib-pull}30081[#30081] +* Removes dependency on doc versions {kib-pull}29906[#29906] +* Adds typings for saved object client {kib-pull}29951[#29951] +* Uses `lastSubUrl` when appropriate {kib-pull}28735[#28735] +* Removes es _xpack endpoint usage {kib-pull}29465[#29465] +* Adds typings for the `saved_object_finder` react component {kib-pull}30067[#30067] +* Fixes the confirm overwrite modal of saved objects to handle large titles {kib-pull}28590[#28590] +* Decreases start limit and interval {kib-pull}25474[#25474] +* Adds `--download` flag to snapshot command to warm the cache {kib-pull}25830[#25830] +* Implements `--prefer-offline` flag {kib-pull}25840[#25840] +* Fixes watcher routes broken by Hapi upgrade {kib-pull}26713[#26713] +* Fixes non-conforming licenses on devDependencies and adds the ability to whitelist devOnly licenses {kib-pull}23859[#23859] +* Watches optimizer cache invalidation {kib-pull}24172[#24172] +* Adds `normalizePath` in order to fix watch optimizer when running on Windows {kib-pull}26486[#26486] +* Creates vendor dll for the client modules {kib-pull}22618[#22618] +* Upgrades to NodeJS 10 {kib-pull}25157[#25157] +* Improves plugin version mismatch error message {kib-pull}25774[#25774] +* Improves build/packaging {kib-pull}26096[#26096] +* Swaps `jstimezonedetect` with `moment.tz.guess` {kib-pull}21800[#21800] +* Upgrades resize-observer-polyfill version {kib-pull}26990[#26990] +* Fixes saved objects client `_processBatchQueue` function to handle errors {kib-pull}26763[#26763] +* Changes kbn pm webpack config to generate dist files in mode=none {kib-pull}26847[#26847] +* Hides logs from deleteAll on task: clean client modules into dll {kib-pull}26884[#26884] +* Upgrades `resize-observer-polyfill` version {kib-pull}26990[#26990] +* Uses `single-node` discovery type for the test ES node/cluster {kib-pull}27125[#27125] +* Moves moment to peerDependency in elastic-datemath {kib-pull}27264[#27264] +* Transforms plugin deprecations before checking for unused settings {kib-pull}21294[#21294] +* Expands list of restricted globals in `eslint-config-kibana` {kib-pull}15798[#15798] +* Makes logs easier to read on Windows with chalk colors {kib-pull}15557[#15557] +* Fixes `includeFields` function to return root saved object properties {kib-pull}33847[#33847] +Reporting:: +* Refactors routes files and helpers {kib-pull}30111[#30111] +* Deletes `sortOrder` once items have been sorted and does not pass to `EuiContextMenuItem` +in the share context menu {kib-pull}26890[#26890] +* Fixes a regression bug in detection of Error and Warning toast notifications {kib-pull}25482[#25482] +* Stops passing an empty `formatConfig` to the fieldFormats helper {kib-pull}27168[#27168] +* Returns promise in Reporting jobs API {kib-pull}24769[#24769] +* Uses `content-disposition` package for non-US font titles in reporting {kib-pull}30895[#30895] +* Uses lowercased server host settings {kib-pull}33020[#33020] +Rollups:: +* Shows loading state in Rollup Job detail panel. {kib-pull}25752[#25752] +* Specifies Rollup Jobs breadcrumbs in header. {kib-pull}26590[#26590] +* Requires histogram interval in Rollup Job wizard to be a whole number. {kib-pull}26596[#26596] +* Removes duplicate rendered sections {kib-pull}[#28566] +Security:: +* Adds tests for interpreter `createSocket` {kib-pull}29459[#29459] +* Moves the server-side `SavedObjectClient` types from the `spaces` plugin to the +same location as the corresponding JavaScript source files {kib-pull}26448[#26448] +* Respects the `basePath` for the link to the user profile in the k7 header {kib-pull}26417[#26417] +* Fixes `prettier` throw rule error {kib-pull}26071[#26071] +* Fixes authentication logic to fail out of auth flow on first provider failure {kib-pull}26648[#26648] +* Fixes issues with the `url.search` being null in Node 10 {kib-pull}26992[#26992] +* Fixes DLS query toggle on the role management page {kib-pull}27213[#27213] +* Implements the K7 login screen {kib-pull}23512[#23512] +Visualizations:: +* Hides gauge labels when value is hidden {kib-pull}34171[#34171] +* Removes dangerously set inner HTML {kib-pull}33976[#33976] +* Fixes gauge filters {kib-pull}30057[#30057] +* Fixes fieldformatter calls in pipeline helper {kib-pull}29842[#29842] +* Adds pipeline field formatting {kib-pull}28746[#28746] +* Removes `kibana_table` pipeline type {kib-pull}28979[#28979] +* Moves renderers registry to OSS {kib-pull}28986[#28986] +* Prepares for cut over to the visualize data loader from the current expression +pipeline data loader {kib-pull}29873[#29873] +* Toggles between Expression Pipeline & Visualize Data loader {kib-pull}29874[#29874] +* Fixes every app that was wrapping `query` in an array unnecessarily {kib-pull}27636[#27636] +* Fixes build issue and reintroduces new filter bar {kib-pull}29752[#29752] +* Adds index pattern URL change notes {kib-pull}30779[#30779] +* Fixes visualization filters to ignore invalid entries {kib-pull}30633[#30633] +* Expands the size of add panels flyout and increases default rows per page {kib-pull}30508[#30508] +* Fixes support for React 16.4+ by only resetting state if adaptors are updated {kib-pull}26138[#26138] +* Fixes scrolling list on Firefox {kib-pull}26246[#26246] +* Guards against empty and undefined index pattern arrays passed to QueryBar {kib-pull}24607[#24607] +* Removes unused indexPattern from vega/tsvb/timelion request handler {kib-pull}26007[#26007] +* Passes global filters from editor down to visualize {kib-pull}26009[#26009] +* Stops using schemas in aggconfigs to output DSL {kib-pull}26010[#26010] +* Fixes `kbn-interpreter` package to not import from UI {kib-pull}26161[#26161] +* Fixes OSS dynamic plugin loading by reverting to Canvas way of loading plugins {kib-pull}26463[#26463] +* Fixes other bucket option to correctly apply without having to change other settings {kib-pull}26874[#26874] +* Adds `en` as a valid numeral locale setting {kib-pull}25948[#25948] +* Adds `rest_total_hits_as_int` into Kibana App {kib-pull}26404[#26404] +* Uses Canvas pipeline to fetch data inside Visualize {kib-pull}25996[#25996] +* Adds warning to the `documentation_links` file about link validation gotcha {kib-pull}24786[#24786] +* Adds workaround for `getDerivedStateFromProps` change in react 16.4 {kib-pull}25142[#25142] +* Fixes "Set up index patterns" link on home page {kib-pull}16128[#16128] +* Fixes Time Series Visual Builder so that auto apply changes on every click {kib-pull}33710[#33710] +* Removes the `geo_centroid` and `geo_bounds` aggregations from nested metrics {kib-pull}34042[#34042] +* Replaces deprecated `moving_avg` by `moving_fn` aggregation {kib-pull}34155[#34155] +* Adds autocomplete to Time Series Visual Builder {kib-pull}30158[#30158] +* Fixes missing Markdown variables {kib-pull}28173[#28173] +* Removes filter bar for Markdown visualizations {kib-pull}30354[#30354] +* Corrects label for OS visualization in logs sample data {kib-pull}30249[#30249] +* Fixes filter function on pie chart segment {kib-pull}26321[#26321] +* Rewrites URL when closing vis type selection modal {kib-pull}26327[#26327] +* Changes unbind calls from `.on` to `.off` {kib-pull}24575[#24575] +* Fixes date field in controls visualization by generating labels with the field +formatter {kib-pull}25654[#25654] +* Replaces LESS files with Sass in `ui/public/vis`, `visLib`, and `visualize` {kib-pull}25333[#25333] +* Replaces LESS files with Sass for the visualization types in `core_plugin/metrics` {kib-pull}24250[#24250] +* Moves `timeout` to `_msearch` body to fix time series visual builder requests {kib-pull}26510[#26510] +* Adds description for all visualization types {kib-pull}26243[#26243] +* Defaults the scroll wheel zoom to false on Vega maps {kib-pull}21169[#21169] +* Fixes problem within the input_vis_control plugin that prevents it from updating correctly +if the field is switched, and then switched back to the previous field {kib-pull}25164[#25164] +* Uses `vega-nocanvas` instead of Vega lib {kib-pull}16137[#16137] +* Migrates visualization from Angular to React {kib-pull}16425[#16425] +* Fixes maps for reporting (#15272) {kib-pull}15358[#15358] +* Stops creation of nested search source per postflightrequest {kib-pull}20373[#20373] +* Moves inspector code from Vis to embeddable visualize handler {kib-pull}24112[#24112] +* Removes inspector from Vis {kib-pull}24112[#24112] +* Fixes issue with debounce function running after component was unmounted {kib-pull}15045[#15045] +* Fixes for dark mode fixes for Visualize charts, Time Series Visual Builder, and Timelion {kib-pull}30478[#30478] +* Fixes geohash checkbox group spacing {kib-pull}32664[#32664] +* Removes deep clone from courier request handler {kib-pull}32806[#32806] +* Ensures saved filters from `searchSource` are always passed to response handlers {kib-pull}33074[#33074] +* Adds new visualization search selection {kib-pull}30196[#30196] +* Changes visualization save dialog when adding to dashboard {kib-pull}32883[#32883] +* Fixes missing variables preview in Time Series Visual Builder markdown {kib-pull}30830[#30830] +* Fixes incorrect behavior when filling the 'interval' field with values: s,m,d,M,y {kib-pull}32542[#32542] +* Fixes multi-metric gauge with vertical sizing {kib-pull}33245[#33245] +* Fixes Time Series Visual Builder display on small screen resolution {kib-pull}33299[#33299] +* Fixes Time Series Visual Builder metric and gauge panels when splitting data by numbers {kib-pull}33304[#33304] +* Fixes Time Series Visual Builder percentile ranks with integer values that return no results {kib-pull}33397[#33397] +* Fixes Time Series Visual Builder issue with table view {kib-pull}33645[#33645] +* Fixes Time Series Visual Builder issue with wrong color rules on multiple metrics {kib-pull}31455[#31455] +* Fixes Time Series Visual Builder issue with percentiles for table {kib-pull}32084[#32084] +* Switches all Time Series Visual Builder comboboxes to plain text single selection {kib-pull}31879[#31879] +* Fixes table visualization to format date string when grouping by date field {kib-pull}31783[#31783] +* Adds flex wrap to metric visualization container {kib-pull}31891[#31891] +* Fixes missing axis labels when moving position {kib-pull}32628[#32628] +* Fixes vislib legend entry width {kib-pull}33303[#33303] +* Fixes legend / color picker overflow {kib-pull}30960[#30960] +* Fixes total Metric Count inside donut pie charts {kib-pull}29086[#29086] +* Adds labels for sort order and request preference setting {kib-pull}31236[#31236] +* Fixes time picker quick ranges description {kib-pull}32455[#32455] +* Adds check for `extraMetric` in point server tooltip hovers {kib-pull}32641[#32641] +* Switches sample data objects to KQL {kib-pull}32718[#32718] +* Migrate visualization controls to use references {kib-pull}30880[#30880] +* Dedupes by index pattern ID rather than object identity {kib-pull}32350[#32350] +* Ensures extra columns are not shown in table visualization when `showPartialRows:true` {kib-pull}27154[#27154] +* Uses default index pattern when one is not present in Visualize {kib-pull}30574[#30574] +* Surfaces visualization loader errors in the UI {kib-pull}30594[#30594] + + + + + +[[release-notes-7.0.0-rc1]] +== {kib} 7.0.0-rc1 + +[float] +[[breaking-7.0.0-rc1]] +=== Breaking changes + +For more details about breaking changes in this release, see +<>. + +Discover:: +* Allows user to use advanced query DSL directly, and does not apply `query:queryString:options` to `query_string` filters automatically {kib-pull}15640[#15640] +* Removes `default_field` from `query:queryString:options` {kib-pull}18966[#18966] +* Makes KQL the default query language for new searches {kib-pull}27092[#27092] +Design:: +* Removes references to K6 EUI, using the default UI theme in its place {kib-pull}29152[#29152] +Geo:: +* Removes the deprecated `regionmap` and `tilemap` kibana.yml configurations. +Removes the backwards compatibility logic that checked for duplicative settings +`map.regionmap` and `map.tilemap`. {kib-pull}28609[#28609] +Monitoring:: +* Refactors index patterns from configurable to constants {kib-pull}29528[#29528] +* Removes `node_resolver` setting {kib-pull}21181[#21181] +Management:: +* Adds `configPrefix` to Index Management, License Management, Rollup Jobs, and +Upgrade Assistant {kib-pull}30149[#30149] +* Removes nested table splits from table visualization {kib-pull}26057[#26057] +* Standardizes use of `index_pattern` in UI code and URLs, replacing `indices` +and `index` {kib-pull}29151[#29151] and {kib-pull}29481[#29481] +* Removes app-specific dark mode options and replaces with a global dark mode uiSetting {kib-pull}29017[#29017] +Operations:: +* Defers the optimize step in the plugin installer to server start {kib-pull}26983[#26983] +* Removes tribe node support {kib-pull}16397[#16397] +* Creates separate startup scripts for development and production {kib-pull}13806[#13806] +* Sets default port based on protocol {kib-pull}21564[#21564] +* Removes deprecated `/shorten` API {kib-pull}21861[#21861] +Platform:: +* Removes deprecated `i18n.defaultLocale` setting {kib-pull}29325[#29325] +* Removes previously deprecated `elasticsearch*` settings. {kib-pull}29496[#29496] +* Adds new "references" attribute to saved objects for relationships {kib-pull}28199[#28199] +Reporting:: +* Removes Phantom dependency {kib-pull}27142[#27142] +Security:: +* Removes deprecated SSL settings {kib-pull}28622[#28622] +* Removes legacy fallback {kib-pull}29107[#29107] +Visualizations:: +* Removes Timelion from the app switcher by default {kib-pull}30131[#30131] + + +[float] +[[deprecation-7.0.0-rc1]] +=== Deprecations + +Geo:: +* Fixes legacy tilemap loading {kib-pull}22095[#22095] +Machine Learning:: +* Updates REST endpoint calls to remove _xpack {kib-pull}28069[#28069] +Visualizations:: +* Removes old visualize wizard URL {kib-pull}28982[#28982] +* Removes legacy response handler {kib-pull}28985[#28985] +* Removes `legacyIcon` from visualizations {kib-pull}28981[#28981] + + +[float] +[[enhancement-7.0.0-rc1]] +=== Enhancements +Canvas:: +* Removes WebSockets from Canvas expressions interpreter {kib-pull}29792[#29792] +* Optimizes Canvas REST calls via batching {kib-pull}29847[#29847] +* Implements a clipboard and stores the copied elements in `localStorage` {kib-pull}25890[#25890] +* Adds the ability to reuse assets without editing an element's expression {kib-pull}25764[#25764] +* Adds the `clear` function {kib-pull}26397[#26397] +* Adds workpad-level CSS {kib-pull}24143[#24143] +* Improvements to expression editor {kib-pull}32336[#32336] +* Adds `aria-label` attribute for Color: Auto Color to button inside chart style {kib-pull}32633[#32633] +* Adds `aria-label` attribute for Copy to clipboard {kib-pull}32880[#32880] +Dashboard:: +* Adds `href` option in addition to `onClick` for navigational links {kib-pull}25233[#25233] +Design:: +* Implements a new design for {kib} called K7 +* Updates logos for marketing {kib-pull}25489[#25489] +* Adds Kibana 7.0 breadcrumbs to home screen {kib-pull}26605[#26605] +* Moves elastic/eui typings to single file {kib-pull}23950[#23950] +Discover:: +* Renames the kuery setting to KQL {kib-pull}29587[#29587] +* Adds visual indication of selected language in query bar {kib-pull}30899[#30899] +Kibana App:: +* Replaces Angular timepicker with EuiSuperDatePicker {kib-pull}29204[#29204] +* Upgrades Kibana to Elasticsearch 7.0 {kib-pull}29184[#29184] +* Maps inspector requests by id so single requests can be reset at a time {kib-pull}26770[#26770] +* Adds ODBC to blurb for start trail {kib-pull}27223[#27223] +Logstash:: +* Adopts {es} typeless API for Logstash central management {kib-pull}30546[#30546] +Management:: +* Adds `Request timestamp` to request inspector stats {kib-pull}25667[#25667] +* Adds "Reload indices" button to Index Management {kib-pull}27033[#27033] +Machine Learning:: +* Adds the time of the anomaly to the `aria-label` of the actions button in each row of the anomalies table {kib-pull}32777[#32777] +* Adds `role="alert"` callouts on the Job Management page to ensure the information is read out by screen readers {kib-pull}32911[#32911] +* Adds EUI `ScreenReaderOnly` component to the "Analyzing data" modal {kib-pull}32472[#32472] +* Updates job type and APM module icon to new designs {kib-pull}25380[#25380] +* Allows model plot enablement via checkbox in MultiMetric/Population Job creation {kib-pull}24914[#24914] +* Adds support for the rare detector for charts in Anomaly Explorer and Singe Metric viewer {kib-pull}21524[#21524] +* Updates HTTP access modules for ECS {kib-pull}29383[#29383] +* Updates auditbeat modules for ECS {kib-pull}29934[#29934] +* Removes non ECS apache, nginx and auditbeat data recognizer modules {kib-pull}30537[#30537] +* Adds the configuration files for two new auditbeat data recognizer modules for +detecting unusual processes on hosts and Docker containers {kib-pull}25716[#25716] +* Adds support for saved searches created using Kuery to the job wizards {kib-pull}26094[#26094] +* Allows users to enter their own query in the Discover page; stops passing the query +from the job datafeed config in custom URLs {kib-pull}26957[#26957] +* Rewrites Calendar to React/EUI {kib-pull}26741[#26741] +* Converts Setting page to React/EUI {kib-pull}27144[#27144] +* Ensures loading indicator is present on initial jobs load {kib-pull}27151[#27151] +* Prevents a new calendar save if a calendar with that id already exists {kib-pull}27104[#27104] +* Edits data recognizer modules to use KQL in saved objects {kib-pull}32766[#32766] +Observability:: +* Converts monitor sparklines to histogram {kib-pull}28502[#28502] +* Adds crosshair sync for monitor page charts {kib-pull}28631[#28631] +* Adds a new plugin for Uptime Monitoring {kib-pull}25480[#25480] +Operations:: +* Adds support for reindexing APM indices {kib-pull}29845[#29845] +* Adds a reindex warning for mapping type changes {kib-pull}32081[#32081] +* Adds warning callout to update APM index pattern {kib-pull}33661[#33661] +Platform:: +* Adds help menu item to header {kib-pull}29664[#29664] +* Implements global dark theme {kib-pull}28445[#28445] +* Removes support for the K6 navigation style {kib-pull}29565[#29565] +* Adds `rest_total_hits_as_int` to all requests in platform code that eventually +look up `hits.total` {kib-pull}26432[#26432] +* Adds `dist` flag to the configuration context {kib-pull}26545[#26545] +* Prepares `@kbn/datemath` to be republished as `@elastic/datemath` {kib-pull}26559[#26559] +* Wraps `remote` methods in `browser` service {kib-pull}26394[#26394] +* Uses `stream.pipeline` to manage error handling {kib-pull}27246[#27246] +Querying & Filtering:: +* Moves the `buildESQuery` module (including filters and Kuery) into a separate package {kib-pull}23345[#23345] +* Adds comment explaining why `getComputedFields` adds a `docvalue` to `docvalue_fields` +for each date field in an index pattern. {kib-pull}25725[#25725] +* Moves filtering functions out of `vis.API.events` {kib-pull}25280[#25280] +Reporting:: +* Adds png output to reports {kib-pull}24759[#24759] +* Sorts ascending on sort order first then ascending on name. Any menu item +without a sort order gets set to zero. {kib-pull}25058[#25058] +* In the Visualization Editor, removes the "Optimize for printing" option when +exporting the visualization as PNG or PDF. The single visualization will automatically +be optimized for printing {kib-pull}30456[#30456] +* Adds browser type to the reporting side panel {kib-pull}26307[#26307] +* Adds better logging for `waitForSelector` failure {kib-pull}25762[#25762] +* Enhances error messaging and handling {kib-pull}26299[#26299] +* Adds "Info" button in the Reporting listing {kib-pull}25421[#25421] +* Adds new inspector for chromium-backed reports {kib-pull}32430[#32430] +Rollups:: +* Adds support for rolling up metrics of date fields {kib-pull}26450[#26450] +Security:: +* Introduces content security policy (CSP) {kib-pull}29545[#29545] +* Warns legacy browsers that do not support content security policy {kib-pull}29957[#29957] +* Adds content security policy strict mode {kib-pull}29856[#29856] +* Updates the GET `/api/security/role` endpoint to return the list of roles sorted +by name, rather than creation date {kib-pull}26491[#26491] +* Updates the Account Settings screen to show the change password form only when +a password change is possible for the authentication realm {kib-pull}26779[#26779] +* Makes space selector a `button` {kib-pull}26889[#26889] +Visualizations:: +* Adds a `console.error` for visualize errors {kib-pull}24581[#24581] +* Adds a timeout so that Vega respects `elasticsearch.shardTimeout` setting {kib-pull}30482[#30482] +* Removes experimental flag from Visual Builder (TSVB) {kib-pull}25634[#25634] +* Implements new visualization type selection {kib-pull}23833[#23833] +* Removes `lab` stage for visualizations, making `experimental` the only non-production +stage available {kib-pull}25702[#25702] +* Makes markdown consistent across {kib} {kib-pull}31890[#31890] +* Adds option to open links in new tab in Time Series Visual Builder {kib-pull}31906[#31906] +* Adds max, min, placeholder to percentile in Time Series Visual Builder {kib-pull}32389[#32389] +* Displays interval information in Time Series Visual Builder when building {kib-pull}32117[#32117] +* Adds controls to toggle disable/enable individual series and annotations {kib-pull}33107[#33107] +* Updates Vega to version 4 {kib-pull}30628[#30628] + +[float] +[[bug-7.0.0-rc1]] +=== Bug fixes +APM:: +* Uses form label for Transaction type selector {kib-pull}28322[#28322] +* Fixes icon for View trace button {kib-pull}28908[#28908] +* Shows metric-only services in service overview {kib-pull}30397[#30397] +* Adds span subtype and action to Span Flyout {kib-pull}30041[#30041] +* Updates head title and fixes breadcrumb string issues {kib-pull}29960[#29960] +* Adds fixes for `service.name` scripted field {kib-pull}28488[#28488] +* Updates APM index pattern {kib-pull}30837[#30837] +* Updates APM reindex script {kib-pull}30761[#30761] +* Sets Index Pattern version as string {kib-pull}30789[#30789] +* Overrides EUI chart default styles for gridlines {kib-pull}21723[#21723] +* Adds section titles to span detail modal {kib-pull}20717[#20717] +* Fixes upgrade assistant label and copy {kib-pull}31750[#31750] +* Changes `context.system.hostname` to `host.hostname` for APM link {kib-pull}30884[#30884] +* Updates APM reindex script {kib-pull}31965[#31965] +* Updates APM index pattern {kib-pull}33595[#33595] +Canvas:: +* Adds datetime as a date identifier {kib-pull}29537[#29537] +* Switches sample web logs fonts to 48px {kib-pull}30747[#30747] +* Fixes related to K7 design {kib-pull}30833[#30833] +* Fixes page preview size issue {kib-pull}26795[#26795] +* Fixes visual bug when opening the workpad loader {kib-pull}26647[#26647] +* Fixes page thumbnail sizes {kib-pull}26573[#26573] +* Decreases size of tray toggle {kib-pull}25470[#25470] +* Makes selection border 1px {kib-pull}26739[#26739] +* Fixes interpreter socket error {kib-pull}26870[#26870] +* Fixes duplicate `Value` options in math select value {kib-pull}25556[#25556] +* Gets correct plugins path {kib-pull}25448[#25448] +* Quotes the index pattern in SQL input {kib-pull}25488[#25488] +* Decreases the size of tray toggle {kib-pull}25470[#25470] +* Fixes the hours label container size {kib-pull}31838[#31838] +* Removes ID attribute {kib-pull}30736[#30736] +* Improves the plugin pre-build {kib-pull}25267[#25267] +Dashboard:: +* Removes `dashboardContext` function and makes Timelion, Vega, and Time Series +Visual Builder use `buildEsQuery` {kib-pull}23227[#23227] +* Shows the filter bar in dashboard embed mode {kib-pull}32222[#32222] +Design:: +* Updates dashboard design {kib-pull}29896[#29896] +* Adjusts side navigation interaction {kib-pull}29978[#29978] +* Converts Security UI from LESS to Sass {kib-pull}25079[#25079] +* Adds boilerplate Sass for Kibana core {kib-pull}21185[#21185] +* Makes dark mode overrides global {kib-pull}31628[#31628] +Discover:: +* Adds debug code to flaky field_data test {kib-pull}15535[#15535] +* Gets even more debug info for flaky field_data test {kib-pull}17627[#17627] +* Allows time ranges before the epoch in Discover {kib-pull}31807[#31807] +* Fixes Kibana Query Language handling of carriage return {kib-pull}32150[#32150] +* Improves warning messages when using Lucene-like syntax {kib-pull}31837[#31837] +* Update capitalization of KQL full name {kib-pull}31631[#31631] +* Adds placeholder text indicating the filters aggregation takes only Lucene and Query DSL {kib-pull}31296[#31296] +* Prevents sending request if it already failed during query parsing {kib-pull}31219[#31219] +* Fixes apps to always migrate legacy queries on state change {kib-pull}33276[#33276] +Geo:: +* Fixes panel cut off in K7 design {kib-pull}29209[#29209] +* Removes left-over geohash grid code {kib-pull}30312[#30312] +* Uses geo-tile aggregation instead of geohash precision {kib-pull}29776[#29776] +* Resolves URL dynamically when requesting EMS data {kib-pull}25685[#25685] +* Fixes EMS hotlink {kib-pull}26868[#26868] +* Fixes feature/align map config settings {kib-pull}19450[#19450] +* Removes `geotile_grid` aggregation from non-geospatial visualizations {kib-pull}31354[#31354] +* Coerces string doc-values to numbers if used in styling {kib-pull}33657[#33657] +Infrastructure:: +* Fixes server-side retrieval of the {kib} version {kib-pull}31440[#31440] +* Fixes react router import {kib-pull}33659[#33659] +* Adapts settings ui to saved object version type change {kib-pull}30082[#30082] +* Fixes potential color bugs {kib-pull}26292[#26292] +* Fixes auto refresh button on node detail page {kib-pull}26426[#26426] +* Changes the time range from the last hour to the last 5 minutes for the Waffle Map {kib-pull}26278[#26278] +* Passes flag in request to force BWC hit count {kib-pull}26517[#26517] +* Replaces redux source slice with constate container {kib-pull}26121[#26121] +* Changes node detail link to set time range to 1 hour {kib-pull}26977[#26977] +* Stops showing sidenav while loading. {kib-pull}27119[#27119] +* Fixes styling after breaking EUI changes {kib-pull}27021[#27021] +* Fixes graphql type generation after package upgrades {kib-pull}26991[#26991] +* Removes usage of `ts-optchain` in the browser {kib-pull}27148[#27148] +Kibana App:: +* Fixes gauge filters {kib-pull}30057[#30057] +* Fixes fieldformatter calls in pipeline helper {kib-pull}29842[#29842] +* Adds pipeline field formatting {kib-pull}28746[#28746] +* Removes `kibana_table` pipeline type {kib-pull}28979[#28979] +* Moves renderers registry to OSS {kib-pull}28986[#28986] +* Prepares for cut over to the visualize data loader from the current expression +pipeline data loader {kib-pull}29873[#29873] +* Toggles between Expression Pipeline & Visualize Data loader {kib-pull}29874[#29874] +* Fixes every app that was wrapping `query` in an array unnecessarily {kib-pull}27636[#27636] +* Fixes build issue and reintroduces new filter bar {kib-pull}29752[#29752] +* Adds index pattern URL change notes {kib-pull}30779[#30779] +* Fixes visualization filters to ignore invalid entries {kib-pull}30633[#30633] +* Expands the size of add panels flyout and increases default rows per page {kib-pull}30508[#30508] +* Fixes support for React 16.4+ by only resetting state if adaptors are updated {kib-pull}26138[#26138] +* Fixes scrolling list on Firefox {kib-pull}26246[#26246] +* Guards against empty and undefined index pattern arrays passed to QueryBar {kib-pull}24607[#24607] +* Removes unused indexPattern from vega/tsvb/timelion request handler {kib-pull}26007[#26007] +* Passes global filters from editor down to visualize {kib-pull}26009[#26009] +* Stops using schemas in aggconfigs to output DSL {kib-pull}26010[#26010] +* Fixes `kbn-interpreter` package to not import from UI {kib-pull}26161[#26161] +* Fixes OSS dynamic plugin loading by reverting to Canvas way of loading plugins {kib-pull}26463[#26463] +* Fixes other bucket option to correctly apply without having to change other settings {kib-pull}26874[#26874] +* Adds `en` as a valid numeral locale setting {kib-pull}25948[#25948] +* Adds `rest_total_hits_as_int` into Kibana App {kib-pull}26404[#26404] +* Uses Canvas pipeline to fetch data inside Visualize {kib-pull}25996[#25996] +* Adds warning to the `documentation_links` file about link validation gotcha {kib-pull}24786[#24786] +* Adds workaround for `getDerivedStateFromProps` change in react 16.4 {kib-pull}25142[#25142] +* Fixes "Set up index patterns" link on home page {kib-pull}16128[#16128] +Machine Learning:: +* Fixes filter and icon for APM Data Recognizer module {kib-pull}31112[#31112] +* Ensures cardinality related messages in Advanced job wizard are formatted correctly {kib-pull}33599[#33599] +* Adds title elements which were missing from Calendars pages {kib-pull}33257[#33257] +* Changes job wizard query to use `match_all` {kib-pull}32008[#32008] +* Adds calendars list to job management {kib-pull}32566[#32566] +* Fixes Job Selector text to take group selection into account {kib-pull}31333[#31333] +* Ensures that Job Selector description text is accurate {kib-pull}32441[#32441] +* Reduces space between headings in the expanded row for Category examples in Anomalies Table {kib-pull}32417[#32417] +* Removes use of types in datafeeds {kib-pull}27572[#27572] +* Fixes metric select double caret {kib-pull}30357[#30357] +* Removes old angular based start datafeed modal {kib-pull}30392[#30392] +* Handles removal of backend ml.enabled node attribute {kib-pull}27604[#27604] +* Edits labels in the Apache and Nginx ECS data recognizer modules {kib-pull}29935[#29935] +* Fixes for K7 compatibility {kib-pull}30536[#30536] +* Fixes broken label style in advanced wizard {kib-pull}30847[#30847] +* Adds ml-ui team to .github/CODEOWNERS {kib-pull}29810[#29810] +* Allows user to add/edit/delete annotations in the Single Series Viewer {kib-pull}26034[#26034] +* Does not pass datafeed query to Discover in custom URL {kib-pull}26957[#26957] +* Fixes word break in Anomalies and Jobs tables {kib-pull}26978[#26978] +* Fixes alignment of filter icons in the Anomalies table {kib-pull}26253[#26253] +* Shows useful error on invalid query in JobList search bar {kib-pull}25153[#25153] +* Adds user privilege check to Jobs List group selector control {kib-pull}25225[#25225] +* Fixes file data viz file size check and formats as bytes {kib-pull}25295[#25295] +* Fixes the layout of the cards in the Data Visualizer on IE {kib-pull}25383[#25383] +* Adds better error reporting for reading and importing data {kib-pull}24269[#24269] +* Displays an ordinal y axis for low cardinality rare charts {kib-pull}24852[#24852] +* Fixes typo in job validation message {kib-pull}25130[#25130] +* Removes deprecated `angularjs` based jobs list and related code {kib-pull}25216[#25216] +* Skips invalid modules when data recognizer lists matches {kib-pull}33703[#33703] +Management:: +* Removes grunt sterilize - its been replaced by `kbn clean` {kib-pull}27825[#27825] +* Makes Index management table more responsive {kib-pull}28882[#28882] +* Fixes index pattern wizard when there are remote clusters but no local indices {kib-pull}24339[#24339] +* Uses new `_graph` endpoints {kib-pull}26956[#26956] +* Adjusts spacing of Management navigation items {kib-pull}25666[#25666] +* Updates "Disenroll" text to be consistent with menu option "Unenroll" {kib-pull}26816[#26816] +* Fixes broken breadcrumb link for index management {kib-pull}27164[#27164] +* Fixes issue with multiple execution in Console {kib-pull}26933[#26933] +* Reloads full index list when reload hits missing index {kib-pull}27197[#27197] +* Adds boilerplate for remote clusters management app {kib-pull}25369[#25369] +* Adds `ignore_failure` to ingest common auto complete in console {kib-pull}24915[#24915] +* Removes support for expression-based scripted fields {kib-pull}14310[#14310] +* Adds WatchErrors to capture invalid watches {kib-pull}23887[#23887] +* Rewords the translation id for error with missing property in Watcher {kib-pull}24753[#24753] +* Triggers full load when encountering 403 for index list reload {kib-pull}28243[#28243] +* Updates X-Pack console specs {kib-pull}29506[#29506] +* Fixes API integration test for follower indices {kib-pull}30260[#30260] +* Fixes management footer logo spacing bug {kib-pull}30654[#30654] +Monitoring:: +* Updates to read from `.monitoring-*-7-*` indices {kib-pull}32654[#32654] +* Adds in explicit mappings {kib-pull}33004[#33004] +* Stops using the normalized derivative value {kib-pull}27416[#27416] +* Updates the title in the left nav to Stack Monitoring {kib-pull}28102[#28102] +* Prepares the Monitoring UI codebase for the incoming changes to `hits.total` {kib-pull}26442[#26442] +* Updates browser title to Stack Monitoring {kib-pull}29638[#29638] +* Fixes Monitoring design {kib-pull}29479[#29479] +* Removes old index patterns that are not expected in 7.0.0 onwards {kib-pull}27915[#27915] +* Removes deprecated `xpack.monitoring.report_stats` setting {kib-pull}30017[#30017] +* Fixes monitoring tests to work with mapping changes {kib-pull}29188[#29188] +* Removes type filter helper {kib-pull}30887[#30887] +* Fixes error handling for local stats collection/permissions {kib-pull}26560[#26560] +* Removes initial delay to check and send Telemetry data {kib-pull}26575[#26575] +* Pulls local Kibana usage stats {kib-pull}26496[#26496] +* Converts the Elasticsearch monitoring UIs to using EUI tables and page layout {kib-pull}26217[#26217] +* Renames Monitoring `FormattedMessage` to `FormattedAlert` {kib-pull}24197[#24197] +* Uses the cluster name from metadata if it exists {kib-pull}24495[#24495] +Observability:: +* Fixes 7.x references to tcp.port {kib-pull}29132[#29132] +* Ports functional tests to 7.x {kib-pull}29398[#29398] +* Ports unit tests to master {kib-pull}29876[#29876] +* Adds missing loading states for filter bar and snapshot components {kib-pull}30122[#30122] +* Removes double-format for duration value {kib-pull}30664[#30664] +* Switches Uptime localization from i18n provider to context {kib-pull}31601[#31601] +* Improves monitor charts query {kib-pull}30561[#30561] +* Adds global help support to Uptime {kib-pull}31493[#31493] +* Updates targeted index pattern for 7.0.0 {kib-pull}30998[#30998] +Operations:: +* Removes the usage of types from Esqueue used for the `.reporting index` {kib-pull}32146[#32146] +* Fixes IPv6 addresses used with Angular connector {kib-pull}29891[#29891] +* Fixes `makelogs` dependency {kib-pull}31428[#31428] +* Runs the {kib} server in production mode for functional testing {kib-pull}31346[#31346] +* Uses `fs.copyFile` to avoid race condition {kib-pull}32220[#32220] +* Removes `hash -r` {kib-pull}32616[#32616] +* Fixes JUnit reporter {kib-pull}32686[#32686] +* Adds options to `run()` that can modify help and show help on errors {kib-pull}33466[#33466] +* Captures values from boolean flags {kib-pull}33528[#33528] +* Fixes incorrect environment name for V8 options {kib-pull}31052[#31052] +* Removes svg from url-loader, as it conflicts with other loaders {kib-pull}30888[#30888] +* Uses apiVersion from es plugin in x-pack {kib-pull}30853[#30853] +* Clones saved object document before migrating to prevent accidental mutations {kib-pull}30475[#30475] +* Removes node fallback from kibana-keystore {kib-pull}15066[#15066] +* Adds debug script to set inspect flags {kib-pull}15967[#15967] +* Uses snake case for scripts/kibana-keystore.js and scripts/kibana-plugin.js {kib-pull}15331[#15331] +* Updates license info in package.json {kib-pull}20353[#20353] +* Fixes error log formatting {kib-pull}24788[#24788] +* Matches chalk dependency version on Kibana with the one used on X-Pack {kib-pull}20621[#20621] +* Fixes non-conforming licenses on devDependencies and adds the ability to whitelist devOnly licenses {kib-pull}23859[#23859] +* Adds jsxa11y into eslint rules {kib-pull}23932[#23932] +* Reverts Bump react-grid-layout to 0.16.0 {kib-pull}14912[#14912] +* Reverts breaking change for Status API {kib-pull}21927[#21927] +* Converts `utils/collection` to TypeScript {kib-pull}23992[#23992] +* Removes usage of update_all_types {kib-pull}16406[#16406] +* Improves the `yarn kbn bootstrap` speed by using yarn workspaces for packages inside `packages/*` and `x-pack` {kib-pull}24095[#24095] +* Runs jenkins:unit task with dev flag in order to run license check {kib-pull}19832[#19832] +* Does not break on startup in debug mode {kib-pull}19219[#19219] +Platform:: +* Removes types from `saved_objects` repository {kib-pull}32286[#32286] +* Fixes custom icon image paths in `NavDrawer` {kib-pull}33573[#33573] +* Fixes back button navigation {kib-pull}32372[#32372] +* Improves types for ftr and expect.js and cleans up `tsconfig` files {kib-pull}31948[#31948] +* Strips # from hash before updating ``$location` {kib-pull}32732[#32732] +* Removes `disableAutoAngularUrlEncodingFix()`` {kib-pull}33136[#33136] +* Removes unused system-loader implementation {kib-pull}33747[#33747] +* Moves the table vis migration to {kib} plugin {kib-pull}29478[#29478] +* Allows passing a default operator to use on saved object client find operations {kib-pull}29339[#29339] +* Fixes saved object repository `bulkCreate` to return migrated references and attributes {kib-pull}29754[#29754] +* Adds missing saved object reference handling for searchSourceJSON filter attribute {kib-pull}29840[#29840] +* Excludes `migrationVersion` and references from `getRootPropertiesObjects` result {kib-pull}30081[#30081] +* Removes dependency on doc versions {kib-pull}29906[#29906] +* Adds typings for saved object client {kib-pull}29951[#29951] +* Uses `lastSubUrl` when appropriate {kib-pull}28735[#28735] +* Removes es _xpack endpoint usage {kib-pull}29465[#29465] +* Adds typings for the `saved_object_finder` react component {kib-pull}30067[#30067] +* Fixes the confirm overwrite modal of saved objects to handle large titles {kib-pull}28590[#28590] +* Decreases start limit and interval {kib-pull}25474[#25474] +* Adds `--download` flag to snapshot command to warm the cache {kib-pull}25830[#25830] +* Implements `--prefer-offline` flag {kib-pull}25840[#25840] +* Fixes watcher routes broken by Hapi upgrade {kib-pull}26713[#26713] +* Fixes non-conforming licenses on devDependencies and adds the ability to whitelist devOnly licenses {kib-pull}23859[#23859] +* Watches optimizer cache invalidation {kib-pull}24172[#24172] +* Adds `normalizePath` in order to fix watch optimizer when running on Windows {kib-pull}26486[#26486] +* Creates vendor dll for the client modules {kib-pull}22618[#22618] +* Upgrades to NodeJS 10 {kib-pull}25157[#25157] +* Improves plugin version mismatch error message {kib-pull}25774[#25774] +* Improves build/packaging {kib-pull}26096[#26096] +* Swaps `jstimezonedetect` with `moment.tz.guess` {kib-pull}21800[#21800] +* Upgrades resize-observer-polyfill version {kib-pull}26990[#26990] +* Fixes saved objects client `_processBatchQueue` function to handle errors {kib-pull}26763[#26763] +* Changes kbn pm webpack config to generate dist files in mode=none {kib-pull}26847[#26847] +* Hides logs from deleteAll on task: clean client modules into dll {kib-pull}26884[#26884] +* Upgrades `resize-observer-polyfill` version {kib-pull}26990[#26990] +* Uses `single-node` discovery type for the test ES node/cluster {kib-pull}27125[#27125] +* Moves moment to peerDependency in elastic-datemath {kib-pull}27264[#27264] +* Transforms plugin deprecations before checking for unused settings {kib-pull}21294[#21294] +* Expands list of restricted globals in `eslint-config-kibana` {kib-pull}15798[#15798] +* Makes logs easier to read on Windows with chalk colors {kib-pull}15557[#15557] +Reporting:: +* Refactors routes files and helpers {kib-pull}30111[#30111] +* Deletes `sortOrder` once items have been sorted and does not pass to `EuiContextMenuItem` +in the share context menu {kib-pull}26890[#26890] +* Fixes a regression bug in detection of Error and Warning toast notifications {kib-pull}25482[#25482] +* Stops passing an empty `formatConfig` to the fieldFormats helper {kib-pull}27168[#27168] +* Returns promise in Reporting jobs API {kib-pull}24769[#24769] +* Uses `content-disposition` package for non-US font titles in reporting {kib-pull}30895[#30895] +* Uses lowercased server host settings {kib-pull}33020[#33020] +Rollups:: +* Shows loading state in Rollup Job detail panel. {kib-pull}25752[#25752] +* Specifies Rollup Jobs breadcrumbs in header. {kib-pull}26590[#26590] +* Requires histogram interval in Rollup Job wizard to be a whole number. {kib-pull}26596[#26596] +* Removes duplicate rendered sections {kib-pull}[#28566] +Security:: +* Adds tests for interpreter `createSocket` {kib-pull}29459[#29459] +* Moves the server-side `SavedObjectClient` types from the `spaces` plugin to the +same location as the corresponding JavaScript source files {kib-pull}26448[#26448] +* Respects the `basePath` for the link to the user profile in the k7 header {kib-pull}26417[#26417] +* Fixes `prettier` throw rule error {kib-pull}26071[#26071] +* Fixes authentication logic to fail out of auth flow on first provider failure {kib-pull}26648[#26648] +* Fixes issues with the `url.search` being null in Node 10 {kib-pull}26992[#26992] +* Fixes DLS query toggle on the role management page {kib-pull}27213[#27213] +* Implements the K7 login screen {kib-pull}23512[#23512] +Visualizations:: +* Adds autocomplete to Time Series Visual Builder {kib-pull}30158[#30158] +* Fixes missing Markdown variables {kib-pull}28173[#28173] +* Removes filter bar for Markdown visualizations {kib-pull}30354[#30354] +* Corrects label for OS visualization in logs sample data {kib-pull}30249[#30249] +* Fixes filter function on pie chart segment {kib-pull}26321[#26321] +* Rewrites URL when closing vis type selection modal {kib-pull}26327[#26327] +* Changes unbind calls from `.on` to `.off` {kib-pull}24575[#24575] +* Fixes date field in controls visualization by generating labels with the field +formatter {kib-pull}25654[#25654] +* Replaces LESS files with Sass in `ui/public/vis`, `visLib`, and `visualize` {kib-pull}25333[#25333] +* Replaces LESS files with Sass for the visualization types in `core_plugin/metrics` {kib-pull}24250[#24250] +* Moves `timeout` to `_msearch` body to fix time series visual builder requests {kib-pull}26510[#26510] +* Adds description for all visualization types {kib-pull}26243[#26243] +* Defaults the scroll wheel zoom to false on Vega maps {kib-pull}21169[#21169] +* Fixes problem within the input_vis_control plugin that prevents it from updating correctly +if the field is switched, and then switched back to the previous field {kib-pull}25164[#25164] +* Uses `vega-nocanvas` instead of Vega lib {kib-pull}16137[#16137] +* Migrates visualization from Angular to React {kib-pull}16425[#16425] +* Fixes maps for reporting (#15272) {kib-pull}15358[#15358] +* Stops creation of nested search source per postflightrequest {kib-pull}20373[#20373] +* Moves inspector code from Vis to embeddable visualize handler {kib-pull}24112[#24112] +* Removes inspector from Vis {kib-pull}24112[#24112] +* Fixes issue with debounce function running after component was unmounted {kib-pull}15045[#15045] +* Fixes for dark mode fixes for Visualize charts, Time Series Visual Builder, and Timelion {kib-pull}30478[#30478] +* Fixes geohash checkbox group spacing {kib-pull}32664[#32664] +* Removes deep clone from courier request handler {kib-pull}32806[#32806] +* Ensures saved filters from `searchSource` are always passed to response handlers {kib-pull}33074[#33074] +* Adds new visualization search selection {kib-pull}30196[#30196] +* Changes visualization save dialog when adding to dashboard {kib-pull}32883[#32883] +* Fixes missing variables preview in Time Series Visual Builder markdown {kib-pull}30830[#30830] +* Fixes incorrect behavior when filling the 'interval' field with values: s,m,d,M,y {kib-pull}32542[#32542] +* Fixes multi-metric gauge with vertical sizing {kib-pull}33245[#33245] +* Fixes Time Series Visual Builder display on small screen resolution {kib-pull}33299[#33299] +* Fixes Time Series Visual Builder metric and gauge panels when splitting data by numbers {kib-pull}33304[#33304] +* Fixes Time Series Visual Builder percentile ranks with integer values that return no results {kib-pull}33397[#33397] +* Fixes Time Series Visual Builder issue with table view {kib-pull}33645[#33645] +* Fixes Time Series Visual Builder issue with wrong color rules on multiple metrics {kib-pull}31455[#31455] +* Fixes Time Series Visual Builder issue with percentiles for table {kib-pull}32084[#32084] +* Switches all Time Series Visual Builder comboboxes to plain text single selection {kib-pull}31879[#31879] +* Fixes table visualization to format date string when grouping by date field {kib-pull}31783[#31783] +* Adds flex wrap to metric visualization container {kib-pull}31891[#31891] +* Fixes missing axis labels when moving position {kib-pull}32628[#32628] +* Fixes vislib legend entry width {kib-pull}33303[#33303] +* Fixes legend / color picker overflow {kib-pull}30960[#30960] +* Fixes total Metric Count inside donut pie charts {kib-pull}29086[#29086] +* Adds labels for sort order and request preference setting {kib-pull}31236[#31236] +* Fixes time picker quick ranges description {kib-pull}32455[#32455] +* Adds check for `extraMetric` in point server tooltip hovers {kib-pull}32641[#32641] +* Switches sample data objects to KQL {kib-pull}32718[#32718] +* Migrate visualization controls to use references {kib-pull}30880[#30880] +* Dedupes by index pattern ID rather than object identity {kib-pull}32350[#32350] +* Ensures extra columns are not shown in table visualization when `showPartialRows:true` {kib-pull}27154[#27154] +* Uses default index pattern when one is not present in Visualize {kib-pull}30574[#30574] +* Surfaces visualization loader errors in the UI {kib-pull}30594[#30594] + + + + + + +[[release-notes-7.0.0-beta1]] +== {kib} 7.0.0-beta1 + + +[float] +[[breaking-7.0.0-beta1]] +=== Breaking changes + +For more details about breaking changes in this release, see +<>. + +Design:: +* Removes references to K6 EUI, using the default UI theme in its place {kib-pull}29152[#29152] +Geo:: +* Removes the deprecated `regionmap` and `tilemap` kibana.yml configurations. +Removes the backwards compatibility logic that checked for duplicative settings +`map.regionmap` and `map.tilemap`. {kib-pull}28609[#28609] +Monitoring:: +* Refactors index patterns from configurable to constants {kib-pull}29528[#29528] +Management:: +* Adds `configPrefix` to Index Management, License Management, Rollup Jobs, and +Upgrade Assistant {kib-pull}30149[#30149] +* Removes nested table splits from table visualization {kib-pull}26057[#26057] +* Standardizes use of `index_pattern` in UI code and URLs, replacing `indices` +and `index` {kib-pull}29151[#29151] and {kib-pull}29481[#29481] +* Removes app-specific dark mode options and replaces with a global dark mode uiSetting {kib-pull}29017[#29017] +Operations:: +* Defers the optimize step in the plugin installer to server start {kib-pull}26983[#26983] +Platform:: +* Removes deprecated `i18n.defaultLocale` setting {kib-pull}29325[#29325] +* Removes previously deprecated `elasticsearch*` settings. {kib-pull}29496[#29496] +* Adds new "references" attribute to saved objects for relationships {kib-pull}28199[#28199] +Querying & Filtering:: +* Makes KQL the default query language for new searches {kib-pull}27092[#27092] +Reporting:: +* Removes Phantom dependency {kib-pull}27142[#27142] +Security:: +* Removes deprecated SSL settings {kib-pull}28622[#28622] +* Removes legacy fallback {kib-pull}29107[#29107] +Visualizations:: +* Removes Timelion from the app switcher by default {kib-pull}30131[#30131] + + +[float] +[[deprecation-7.0.0-beta1]] +=== Deprecations +Machine Learning:: +* Updates REST endpoint calls to remove _xpack {kib-pull}28069[#28069] +Visualizations:: +* Removes old visualize wizard URL {kib-pull}28982[#28982] +* Removes legacy response handler {kib-pull}28985[#28985] +* Removes `legacyIcon` from visualizations {kib-pull}28981[#28981] + + +[float] +[[enhancement-7.0.0-beta1]] +=== Enhancements +Canvas:: +* Removes WebSockets from Canvas expressions interpreter {kib-pull}29792[#29792] +* Optimizes Canvas REST calls via batching {kib-pull}29847[#29847] +Kibana App:: +* Replaces Angular timepicker with EuiSuperDatePicker {kib-pull}29204[#29204] +* Upgrades Kibana to Elasticsearch 7.0 {kib-pull}29184[#29184] +Machine Learning:: +* Updates HTTP access modules for ECS {kib-pull}29383[#29383] +* Updates auditbeat modules for ECS {kib-pull}29934[#29934] +* Removes non ECS apache, nginx and auditbeat data recognizer modules {kib-pull}30537[#30537] +Observability:: +* Converts monitor sparklines to histogram {kib-pull}28502[#28502] +* Adds crosshair sync for monitor page charts {kib-pull}28631[#28631] +Operations:: +* Adds support for reindexing APM indices {kib-pull}29845[#29845] +Platform:: +* Adds help menu item to header {kib-pull}29664[#29664] +* Implements global dark theme {kib-pull}28445[#28445] +* Removes support for the K6 navigation style {kib-pull}29565[#29565] +Reporting:: +* In the Visualization Editor, removes the "Optimize for printing" option when +exporting the visualization as PNG or PDF. The single visualization will automatically +be optimized for printing {kib-pull}30456[#30456] +Security:: +* Introduces content security policy (CSP) {kib-pull}29545[#29545] +* Warns legacy browsers that do not support content security policy {kib-pull}29957[#29957] +* Adds content security policy strict mode {kib-pull}29856[#29856] +Visualizations:: +* Adds a timeout so that Vega respects `elasticsearch.shardTimeout` setting {kib-pull}30482[#30482] + + +[float] +[[bug-7.0.0-beta1]] +=== Bug fixes +APM:: +* Uses form label for Transaction type selector {kib-pull}28322[#28322] +* Fixes icon for View trace button {kib-pull}28908[#28908] +* Shows metric-only services in service overview {kib-pull}30397[#30397] +* Adds span subtype and action to Span Flyout {kib-pull}30041[#30041] +* Updates head title and fixes breadcrumb string issues {kib-pull}29960[#29960] +* Adds fixes for `service.name` scripted field {kib-pull}28488[#28488] +* Updates APM index pattern {kib-pull}30837[#30837] +* Updates APM reindex script {kib-pull}30761[#30761] +* Sets Index Pattern version as string {kib-pull}30789[#30789] +Canvas:: +* Adds datetime as a date identifier {kib-pull}29537[#29537] +* Switches sample web logs fonts to 48px {kib-pull}30747[#30747] +* Fixes related to K7 design {kib-pull}30833[#30833] +Design:: +* Updates dashboard design {kib-pull}29896[#29896] +* Adjusts side navigation interaction {kib-pull}29978[#29978] +Elasticsearch UI:: +* Triggers full load when encountering 403 for index list reload {kib-pull}28243[#28243] +* Updates xpack console specs {kib-pull}29506[#29506] +* Fixes API integration test for follower indices {kib-pull}30260[#30260] +Geo:: +* Fixes panel cut off in K7 design {kib-pull}29209[#29209] +* Removes left-over geohash grid code {kib-pull}30312[#30312] +* Uses geo-tile aggregation instead of geohash precision {kib-pull}29776[#29776] +Infrastructure UI:: +* Adapts settings ui to saved object version type change {kib-pull}30082[#30082] +Kibana App:: +* Fixes gauge filters {kib-pull}30057[#30057] +* Fixes fieldformatter calls in pipeline helper {kib-pull}29842[#29842] +* Adds pipeline field formatting {kib-pull}28746[#28746] +* Removes `kibana_table` pipeline type {kib-pull}28979[#28979] +* Moves renderers registry to OSS {kib-pull}28986[#28986] +* Prepares for cut over to the visualize data loader from the current expression +pipeline data loader {kib-pull}29873[#29873] +* Toggles between Expression Pipeline & Visualize Data loader {kib-pull}29874[#29874] +* Fixes every app that was wrapping `query` in an array unnecessarily {kib-pull}27636[#27636] +* Fixes build issue and reintroduces new filter bar {kib-pull}29752[#29752] +* Adds index pattern URL change notes {kib-pull}30779[#30779] +* Fixes visualization filters to ignore invalid entries {kib-pull}30633[#30633] +* Expands the size of add panels flyout and increases default rows per page {kib-pull}30508[#30508] +Machine Learning:: +* Removes use of types in datafeeds {kib-pull}27572[#27572] +* Fixes metric select double caret {kib-pull}30357[#30357] +* Removes old angular based start datafeed modal {kib-pull}30392[#30392] +* Handles removal of backend ml.enabled node attribute {kib-pull}27604[#27604] +* Edits labels in the Apache and Nginx ECS data recognizer modules {kib-pull}29935[#29935] +* Fixes for K7 compatibility {kib-pull}30536[#30536] +* Fixes broken label style in advanced wizard {kib-pull}30847[#30847] +* Adds ml-ui team to .github/CODEOWNERS {kib-pull}29810[#29810] +Management:: +* Removes grunt sterilize - its been replaced by `kbn clean` {kib-pull}27825[#27825] +* Makes Index management table more responsive {kib-pull}28882[#28882] +Monitoring:: +* Stops using the normalized derivative value {kib-pull}27416[#27416] +* Updates the title in the left nav to Stack Monitoring {kib-pull}28102[#28102] +* Prepares the Monitoring UI codebase for the incoming changes to `hits.total` {kib-pull}26442[#26442] +* Updates browser title to Stack Monitoring {kib-pull}29638[#29638] +* Fixes Monitoring design {kib-pull}29479[#29479] +* Removes old index patterns that are not expected in 7.0.0 onwards {kib-pull}27915[#27915] +* Removes deprecated `xpack.monitoring.report_stats` setting {kib-pull}30017[#30017] +* Fixes monitoring tests to work with mapping changes {kib-pull}29188[#29188] +* Removes type filter helper {kib-pull}30887[#30887] +Operations:: +* Removes svg from url-loader, as it conflicts with other loaders {kib-pull}30888[#30888] +* Uses apiVersion from es plugin in x-pack {kib-pull}30853[#30853] +* Clones saved object document before migrating to prevent accidental mutations {kib-pull}30475[#30475] +Observability:: +* Fixes 7.x references to tcp.port {kib-pull}29132[#29132] +* Ports functional tests to 7.x {kib-pull}29398[#29398] +* Ports unit tests to master {kib-pull}29876[#29876] +* Adds missing loading states for filter bar and snapshot components {kib-pull}30122[#30122] +* Removes double-format for duration value {kib-pull}30664[#30664] +Platform:: +* Moves the table vis migration to {kib} plugin {kib-pull}29478[#29478] +* Allows passing a default operator to use on saved object client find operations {kib-pull}29339[#29339] +* Fixes saved object repository `bulkCreate` to return migrated references and attributes {kib-pull}29754[#29754] +* Adds missing saved object reference handling for searchSourceJSON filter attribute {kib-pull}29840[#29840] +* Excludes `migrationVersion` and references from `getRootPropertiesObjects` result {kib-pull}30081[#30081] +* Removes dependency on doc versions {kib-pull}29906[#29906] +* Adds typings for saved object client {kib-pull}29951[#29951] +* Uses `lastSubUrl` when appropriate {kib-pull}28735[#28735] +* Removes es _xpack endpoint usage {kib-pull}29465[#29465] +* Adds typings for the `saved_object_finder` react component {kib-pull}30067[#30067] +* Fixes the confirm overwrite modal of saved objects to handle large titles {kib-pull}28590[#28590] +Reporting:: +* Refactors routes files and helpers {kib-pull}30111[#30111] +Rollups:: +* Removes duplicate rendered sections {kib-pull}28566[#28566] +Security:: +* Adds tests for interpreter `createSocket` {kib-pull}29459[#29459] +Visualizations:: +* Adds autocomplete to Time Series Visual Builder {kib-pull}30158[#30158] +* Fixes missing Markdown variables {kib-pull}28173[#28173] +* Removes filter bar for Markdown visualizations {kib-pull}30354[#30354] +* Corrects label for OS visualization in logs sample data {kib-pull}30249[#30249] + + + + + + + + + + + +[[release-notes-7.0.0-alpha2]] +== {kib} 7.0.0-alpha2 + + +[float] +[[breaking-7.0.0-alpha2]] +=== Breaking changes + +For more details about breaking changes in this release, see +<>. + +[float] +[[highlight-7.0.0-alpha2]] +=== Highlights +Canvas:: +* Canvas now has a template tab in the workpad manager where users can find workpad templates, +demos, and tutorials to help them get started. See {kib-pull}23966[#23966] for more information. +Kibana App:: +* Visualizations in Kibana will use a new data pipeline introduced as part of Canvas. +The change does not yet apply to Vega, Timelion, or Time Series Visual Builder (TSVB). +See {kib-pull}25711[#25711] for more information. +Index Lifecyle Management:: +* Implements a user interface to create, update, edit, or delete index lifecyle policies. +See {kib-pull}25553[#25553] for more information. + +[float] +[[enhancement-7.0.0-alpha2]] +=== Enhancements +Canvas:: +* Implements a clipboard and stores the copied elements in `localStorage` {kib-pull}25890[#25890] +* Adds the ability to reuse assets without editing an element's expression {kib-pull}25764[#25764] +* Adds the `clear` function {kib-pull}26397[#26397] +* Adds workpad-level CSS {kib-pull}24143[#24143] +Dashboard:: +* Adds `href` option in addition to `onClick` for navigational links {kib-pull}25233[#25233] +Design:: +* Updates logos for marketing {kib-pull}25489[#25489] +* Adds Kibana 7.0 breadcrumbs to home screen {kib-pull}26605[#26605] +* Moves elastic/eui typings to single file {kib-pull}23950[#23950] +Kibana App:: +* Maps inspector requests by id so single requests can be reset at a time {kib-pull}26770[#26770] +* Adds ODBC to blurb for start trail {kib-pull}27223[#27223] +Management:: +* Adds `Request timestamp` to request inspector stats {kib-pull}25667[#25667] +* Adds "Reload indices" button to Index Management {kib-pull}27033[#27033] +Machine Learning:: +* Adds the configuration files for two new auditbeat data recognizer modules for +detecting unusual processes on hosts and Docker containers {kib-pull}25716[#25716] +* Adds support for saved searches created using Kuery to the job wizards {kib-pull}26094[#26094] +* Allows users to enter their own query in the Discover page; stops passing the query +from the job datafeed config in custom URLs {kib-pull}26957[#26957] +* Rewrites Calendar to React/EUI {kib-pull}26741[#26741] +* Converts Setting page to React/EUI {kib-pull}27144[#27144] +* Ensures loading indicator is present on initial jobs load {kib-pull}27151[#27151] +* Prevents a new calendar save if a calendar with that id already exists {kib-pull}27104[#27104] +Observability:: +* Adds a new plugin for Uptime Monitoring {kib-pull}25480[#25480] +Platform:: +* Adds `rest_total_hits_as_int` to all requests in platform code that eventually +look up `hits.total` {kib-pull}26432[#26432] +* Adds `dist` flag to the configuration context {kib-pull}26545[#26545] +* Prepares `@kbn/datemath` to be republished as `@elastic/datemath` {kib-pull}26559[#26559] +* Wraps `remote` methods in `browser` service {kib-pull}26394[#26394] +* Uses `stream.pipeline` to manage error handling {kib-pull}27246[#27246] +Querying & Filtering:: +* Moves the `buildESQuery` module (including filters and Kuery) into a separate package {kib-pull}23345[#23345] +* Adds comment explaining why `getComputedFields` adds a `docvalue` to `docvalue_fields` +for each date field in an index pattern. {kib-pull}25725[#25725] +* Moves filtering functions out of `vis.API.events` {kib-pull}25280[#25280] +Reporting:: +* Adds browser type to the reporting side panel {kib-pull}26307[#26307] +* Adds better logging for `waitForSelector` failure {kib-pull}25762[#25762] +* Enhances error messaging and handling {kib-pull}26299[#26299] +* Adds "Info" button in the Reporting listing {kib-pull}25421[#25421] +Rollups:: +* Adds support for rolling up metrics of date fields {kib-pull}26450[#26450] +Security:: +* Updates the GET `/api/security/role` endpoint to return the list of roles sorted +by name, rather than creation date {kib-pull}26491[#26491] +* Updates the Account Settings screen to show the change password form only when +a password change is possible for the authentication realm {kib-pull}26779[#26779] +* Makes space selector a `button` {kib-pull}26889[#26889] +Visualizations:: +* Removes experimental flag from Visual Builder (TSVB) {kib-pull}25634[#25634] +* Implements new visualization type selection {kib-pull}23833[#23833] +* Removes `lab` stage for visualizations, making `experimental` the only non-production +stage available {kib-pull}25702[#25702] + +[float] +[[bug-7.0.0-alpha2]] +=== Bug fixes +Canvas:: +* Fixes page preview size issue {kib-pull}26795[#26795] +* Fixes visual bug when opening the workpad loader {kib-pull}26647[#26647] +* Fixes page thumbnail sizes {kib-pull}26573[#26573] +* Decreases size of tray toggle {kib-pull}25470[#25470] +* Makes selection border 1px {kib-pull}26739[#26739] +* Fixes interpreter socket error {kib-pull}26870[#26870] +Geo:: +* Resolves URL dynamically when requesting EMS data {kib-pull}25685[#25685] +* Fixes EMS hotlink {kib-pull}26868[#26868] +Infrastructure UI:: +* Fixes potential color bugs {kib-pull}26292[#26292] +* Fixes auto refresh button on node detail page {kib-pull}26426[#26426] +* Changes the time range from the last hour to the last 5 minutes for the Waffle Map {kib-pull}26278[#26278] +* Passes flag in request to force BWC hit count {kib-pull}26517[#26517] +* Replaces redux source slice with constate container {kib-pull}26121[#26121] +* Changes node detail link to set time range to 1 hour {kib-pull}26977[#26977] +* Stops showing sidenav while loading. {kib-pull}27119[#27119] +* Fixes styling after breaking EUI changes {kib-pull}27021[#27021] +* Fixes graphql type generation after package upgrades {kib-pull}26991[#26991] +* Removes usage of `ts-optchain` in the browser {kib-pull}27148[#27148] +Kibana App:: +* Fixes support for React 16.4+ by only resetting state if adaptors are updated {kib-pull}26138[#26138] +* Fixes scrolling list on Firefox {kib-pull}26246[#26246] +* Guards against empty and undefined index pattern arrays passed to QueryBar {kib-pull}24607[#24607] +* Removes unused indexPattern from vega/tsvb/timelion request handler {kib-pull}26007[#26007] +* Passes global filters from editor down to visualize {kib-pull}26009[#26009] +* Stops using schemas in aggconfigs to output DSL {kib-pull}26010[#26010] +* Fixes `kbn-interpreter` package to not import from UI {kib-pull}26161[#26161] +* Fixes OSS dynamic plugin loading by reverting to Canvas way of loading plugins {kib-pull}26463[#26463] +* Fixes other bucket option to correctly apply without having to change other settings {kib-pull}26874[#26874] +* Adds `en` as a valid numeral locale setting {kib-pull}25948[#25948] +* Adds `rest_total_hits_as_int` into Kibana App {kib-pull}26404[#26404] +* Uses Canvas pipeline to fetch data inside Visualize {kib-pull}25996[#25996] +Management:: +* Fixes index pattern wizard when there are remote clusters but no local indices {kib-pull}24339[#24339] +* Uses new `_graph` endpoints {kib-pull}26956[#26956] +* Adjusts spacing of Management navigation items {kib-pull}25666[#25666] +* Updates "Disenroll" text to be consistent with menu option "Unenroll" {kib-pull}26816[#26816] +* Fixes broken breadcrumb link for index management {kib-pull}27164[#27164] +* Fixes issue with multiple execution in Console {kib-pull}26933[#26933] +* Reloads full index list when reload hits missing index {kib-pull}27197[#27197] +Machine Learning:: +* Allows user to add/edit/delete annotations in the Single Series Viewer {kib-pull}26034[#26034] +* Does not pass datafeed query to Discover in custom URL {kib-pull}26957[#26957] +* Fixes word break in Anomalies and Jobs tables {kib-pull}26978[#26978] +* Fixes alignment of filter icons in the Anomalies table {kib-pull}26253[#26253] +Monitoring:: +* Fixes error handling for local stats collection/permissions {kib-pull}26560[#26560] +* Removes initial delay to check and send Telemetry data {kib-pull}26575[#26575] +* Pulls local Kibana usage stats {kib-pull}26496[#26496] +* Converts the Elasticsearch monitoring UIs to using EUI tables and page layout {kib-pull}26217[#26217] +Platform & Operations:: +* Decreases start limit and interval {kib-pull}25474[#25474] +* Adds `--download` flag to snapshot command to warm the cache {kib-pull}25830[#25830] +* Implements `--prefer-offline` flag {kib-pull}25840[#25840] +* Fixes watcher routes broken by Hapi upgrade {kib-pull}26713[#26713] +* Fixes non-conforming licenses on devDependencies and adds the ability to whitelist devOnly licenses {kib-pull}23859[#23859] +* Watches optimizer cache invalidation {kib-pull}24172[#24172] +* Adds `normalizePath` in order to fix watch optimizer when running on Windows {kib-pull}26486[#26486] +* Creates vendor dll for the client modules {kib-pull}22618[#22618] +* Upgrades to NodeJS 10 {kib-pull}25157[#25157] +* Improves plugin version mismatch error message {kib-pull}25774[#25774] +* Improves build/packaging {kib-pull}26096[#26096] +* Swaps `jstimezonedetect` with `moment.tz.guess` {kib-pull}21800[#21800] +* Upgrades resize-observer-polyfill version {kib-pull}26990[#26990] +* Fixes saved objects client `_processBatchQueue` function to handle errors {kib-pull}26763[#26763] +* Changes kbn pm webpack config to generate dist files in mode=none {kib-pull}26847[#26847] +* Hides logs from deleteAll on task: clean client modules into dll {kib-pull}26884[#26884] +* Upgrades `resize-observer-polyfill` version {kib-pull}26990[#26990] +* Uses `single-node` discovery type for the test ES node/cluster {kib-pull}27125[#27125] +* Moves moment to peerDependency in elastic-datemath {kib-pull}27264[#27264] +Reporting:: +* Deletes `sortOrder` once items have been sorted and does not pass to `EuiContextMenuItem` +in the share context menu {kib-pull}26890[#26890] +* Fixes a regression bug in detection of Error and Warning toast notifications {kib-pull}25482[#25482] +* Stops passing an empty `formatConfig` to the fieldFormats helper {kib-pull}27168[#27168] +Rollups:: +* Shows loading state in Rollup Job detail panel. {kib-pull}25752[#25752] +* Specifies Rollup Jobs breadcrumbs in header. {kib-pull}26590[#26590] +* Requires histogram interval in Rollup Job wizard to be a whole number. {kib-pull}26596[#26596] +Security:: +* Moves the server-side `SavedObjectClient` types from the `spaces` plugin to the +same location as the corresponding JavaScript source files {kib-pull}26448[#26448] +* Respects the `basePath` for the link to the user profile in the k7 header {kib-pull}26417[#26417] +* Fixes `prettier` throw rule error {kib-pull}26071[#26071] +* Fixes authentication logic to fail out of auth flow on first provider failure {kib-pull}26648[#26648] +* Fixes issues with the `url.search` being null in Node 10 {kib-pull}26992[#26992] +* Fixes DLS query toggle on the role management page {kib-pull}27213[#27213] +Visualizations:: +* Fixes filter function on pie chart segment {kib-pull}26321[#26321] +* Rewrites URL when closing vis type selection modal {kib-pull}26327[#26327] +* Changes unbind calls from `.on` to `.off` {kib-pull}24575[#24575] +* Fixes date field in controls visualization by generating labels with the field +formatter {kib-pull}25654[#25654] +* Replaces LESS files with Sass in `ui/public/vis`, `visLib`, and `visualize` {kib-pull}25333[#25333] +* Replaces LESS files with Sass for the visualization types in `core_plugin/metrics` {kib-pull}24250[#24250] +* Moves `timeout` to `_msearch` body to fix time series visual builder requests {kib-pull}26510[#26510] +* Adds description for all visualization types {kib-pull}26243[#26243] + + + + + + +[[release-notes-7.0.0-alpha1]] +== {kib} 7.0.0-alpha1 + +[float] +[[breaking-7.0.0-alpha1]] +=== Breaking changes + +For more details about breaking changes in this release, see +<>. + +Discover:: +* Does not apply `query:queryString:options` to `query_string` filters {kib-pull}15640[#15640] +* Removes `default_field` from `query:queryString:options` {kib-pull}18966[#18966] + +Monitoring:: +* Removes `node_resolver` setting {kib-pull}21181[#21181] + +Operations:: +* Removes tribe node support {kib-pull}16397[#16397] +* Creates separate startup scripts for development and production {kib-pull}13806[#13806] +* Sets default port based on protocol {kib-pull}21564[#21564] +* Removes deprecated `/shorten` API {kib-pull}21861[#21861] +* Plugin installer defers optimization step until server start {kib-pull}26983[#26983] + +[float] +[[deprecation-7.0.0-alpha1]] +=== Deprecations + +Geo:: +* Fixes legacy tilemap loading {kib-pull}22095[#22095] + +[float] +[[K7-design-7.0.0-alpha1]] +=== K7 UI Design + +{kib} 7.0.0-alpha1 includes a new design for {kib} called K7. In this early stage, +K7 is still a little rough around the edges. If you'd like to switch back to the +existing K6 design, go to *Management > Advanced Settings* and turn +off the *k7design* setting. The option to switch to the old design +will be removed before 7.0.0 GA. + +[float] +[[enhancement-7.0.0-alpha1]] +=== Enhancements + +Machine Learning:: +* Updates job type and APM module icon to new designs {kib-pull}25380[#25380] +* Allows model plot enablement via checkbox in MultiMetric/Population Job creation {kib-pull}24914[#24914] +* Adds support for the rare detector for charts in Anomaly Explorer and Singe Metric viewer {kib-pull}21524[#21524] + +Reporting:: +* Adds png output to reports {kib-pull}24759[#24759] +* Sorts ascending on sort order first then ascending on name. Any menu item +without a sort order gets set to zero. {kib-pull}25058[#25058] + +Visualizations:: +* Adds a console.error for visualize errors {kib-pull}24581[#24581] + +[float] +[[bug-7.0.0-alpha1]] +=== Bug fixes + +APM:: +* Overrides EUI chart default styles for gridlines {kib-pull}21723[#21723] +* Adds section titles to span detail modal {kib-pull}20717[#20717] + +Canvas:: +* Fixes duplicate `Value` options in math select value {kib-pull}25556[#25556] +* Gets correct plugins path {kib-pull}25448[#25448] +* Quotes the index pattern in SQL input {kib-pull}25488[#25488] +* Decreases the size of tray toggle {kib-pull}25470[#25470] +* Improves the plugin pre-build {kib-pull}25267[#25267] + +Dashboard:: +* Removes `dashboardContext` function and makes Timelion, Vega, and Time Series +Visual Builder use `buildEsQuery` {kib-pull}23227[#23227] + +Design:: +* Converts Security UI from LESS to Sass {kib-pull}25079[#25079] +* Adds boilerplate Sass for Kibana core {kib-pull}21185[#21185] + +Discover:: +* Adds debug code to flaky field_data test {kib-pull}15535[#15535] +* Gets even more debug info for flaky field_data test {kib-pull}17627[#17627] + +Geo:: +* Fixes feature/align map config settings {kib-pull}19450[#19450] + +Kibana App:: + +* Adds warning to the `documentation_links` file about link validation gotcha {kib-pull}24786[#24786] +* Adds workaround for `getDerivedStateFromProps` change in react 16.4 {kib-pull}25142[#25142] + +Kibana Home & Add Data:: +* Fixes "Set up index patterns" link on home page {kib-pull}16128[#16128] + +Machine Learning:: +* Shows useful error on invalid query in JobList search bar {kib-pull}25153[#25153] +* Adds user privilege check to Jobs List group selector control {kib-pull}25225[#25225] +* Fixes file data viz file size check and formats as bytes {kib-pull}25295[#25295] +* Fixes the layout of the cards in the Data Visualizer on IE {kib-pull}25383[#25383] +* Adds better error reporting for reading and importing data {kib-pull}24269[#24269] +* Displays an ordinal y axis for low cardinality rare charts {kib-pull}24852[#24852] +* Fixes typo in job validation message {kib-pull}25130[#25130] +* Removes deprecated `angularjs` based jobs list and related code {kib-pull}25216[#25216] + +Management:: +* Adds boilerplate for remote clusters management app {kib-pull}25369[#25369] +* Adds `ignore_failure` to ingest common auto complete in console {kib-pull}24915[#24915] +* Removes support for expression-based scripted fields {kib-pull}14310[#14310] +* Adds WatchErrors to capture invalid watches {kib-pull}23887[#23887] +* Rewords the translation id for error with missing property in Watcher {kib-pull}24753[#24753] + +Monitoring:: +* Renames Monitoring `FormattedMessage` to `FormattedAlert` {kib-pull}24197[#24197] +* Uses the cluster name from metadata if it exists {kib-pull}24495[#24495] + +Operations:: +* Removes node fallback from kibana-keystore {kib-pull}15066[#15066] +* Adds debug script to set inspect flags {kib-pull}15967[#15967] +* Uses snake case for scripts/kibana-keystore.js and scripts/kibana-plugin.js {kib-pull}15331[#15331] +* Updates license info in package.json {kib-pull}20353[#20353] +* Fixes error log formatting {kib-pull}24788[#24788] +* Matches chalk dependency version on Kibana with the one used on X-Pack {kib-pull}20621[#20621] +* Fixes non-conforming licenses on devDependencies and adds the ability to whitelist devOnly licenses {kib-pull}23859[#23859] +* Adds jsxa11y into eslint rules {kib-pull}23932[#23932] +* Reverts Bump react-grid-layout to 0.16.0 {kib-pull}14912[#14912] +* Reverts breaking change for Status API {kib-pull}21927[#21927] +* Converts `utils/collection` to TypeScript {kib-pull}23992[#23992] +* Removes usage of update_all_types {kib-pull}16406[#16406] +* Improves the `yarn kbn bootstrap` speed by using yarn workspaces for packages inside `packages/*` and `x-pack` {kib-pull}24095[#24095] +* Runs jenkins:unit task with dev flag in order to run license check {kib-pull}19832[#19832] +* Does not break on startup in debug mode {kib-pull}19219[#19219] + + +Platform:: +* Transforms plugin deprecations before checking for unused settings {kib-pull}21294[#21294] +* Expands list of restricted globals in `eslint-config-kibana` {kib-pull}15798[#15798] +* Makes logs easier to read on Windows with chalk colors {kib-pull}15557[#15557] + +Querying & Filtering:: +* Fixes wildcard queries against the default field {kib-pull}24778[#24778] + +Reporting:: +* Returns promise in Reporting jobs API {kib-pull}24769[#24769] + +Security:: +* Implements the K7 login screen {kib-pull}23512[#23512] + +Sharing:: + +* Fixes issue with debounce function running after component was unmounted {kib-pull}15045[#15045] + +Visualizations:: +* Defaults the scroll wheel zoom to false on Vega maps {kib-pull}21169[#21169] +* Fixes problem within the input_vis_control plugin that prevents it from updating correctly +if the field is switched, and then switched back to the previous field {kib-pull}25164[#25164] +* Uses `vega-nocanvas` instead of vega lib {kib-pull}16137[#16137] +* Migrates visualization from Angular to React {kib-pull}16425[#16425] +* Fixes maps for reporting (#15272) {kib-pull}15358[#15358] +* Stops creation of nested search source per postflightrequest {kib-pull}20373[#20373] +* Moves inspector code from Vis to embeddable visualize handler {kib-pull}24112[#24112] +* Removes inspector from Vis {kib-pull}24112[#24112] + +//// \ No newline at end of file diff --git a/docs/index.asciidoc b/docs/index.asciidoc index 3e303afc9804..dbee584925a2 100644 --- a/docs/index.asciidoc +++ b/docs/index.asciidoc @@ -21,6 +21,8 @@ include::user/index.asciidoc[] include::accessibility.asciidoc[] +// include::migration.asciidoc[] + include::CHANGELOG.asciidoc[] include::developer/index.asciidoc[] From 1ab5366e8de1755ad7be4e4ab993b6e5514a4cad Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 8 Apr 2021 12:39:15 -0500 Subject: [PATCH 34/49] skip flaky a11y test --- x-pack/test/accessibility/apps/spaces.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/accessibility/apps/spaces.ts b/x-pack/test/accessibility/apps/spaces.ts index 41926628c237..dc0dfad2debf 100644 --- a/x-pack/test/accessibility/apps/spaces.ts +++ b/x-pack/test/accessibility/apps/spaces.ts @@ -34,7 +34,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await a11y.testAppSnapshot(); }); - it('a11y test for manage spaces page', async () => { + // flaky + it.skip('a11y test for manage spaces page', async () => { await PageObjects.spaceSelector.clickManageSpaces(); await PageObjects.header.waitUntilLoadingHasFinished(); await toasts.dismissAllToasts(); From a2ce7dcca93fd1b5aacec3b1114cf43e96620748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Thu, 8 Apr 2021 18:44:20 +0100 Subject: [PATCH 35/49] [ILM] Fix frozen phase min_age (de)serialization (#96544) (#96591) --- .../policy_serialization.test.ts | 91 ++++++++++++++++--- .../sections/edit_policy/form/deserializer.ts | 8 ++ .../edit_policy/form/serializer/serializer.ts | 7 ++ 3 files changed, 92 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts index 846e20b48ddc..aa176fe3b188 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts @@ -481,21 +481,84 @@ describe(' serialization', () => { }); }); - test('delete phase', async () => { - const { actions } = testBed; - await actions.delete.enable(true); - await actions.setWaitForSnapshotPolicy('test'); - await actions.savePolicy(); - const latestRequest = server.requests[server.requests.length - 1]; - const entirePolicy = JSON.parse(JSON.parse(latestRequest.requestBody).body); - expect(entirePolicy.phases.delete).toEqual({ - min_age: '365d', - actions: { - delete: {}, - wait_for_snapshot: { - policy: 'test', + describe('frozen phase', () => { + test('default value', async () => { + const { actions } = testBed; + await actions.frozen.enable(true); + await actions.frozen.setSearchableSnapshot('myRepo'); + + await actions.savePolicy(); + + const latestRequest = server.requests[server.requests.length - 1]; + const entirePolicy = JSON.parse(JSON.parse(latestRequest.requestBody).body); + expect(entirePolicy.phases.frozen).toEqual({ + min_age: '0d', + actions: { + searchable_snapshot: { snapshot_repository: 'myRepo' }, }, - }, + }); + }); + + describe('deserialization', () => { + beforeEach(async () => { + const policyToEdit = getDefaultHotPhasePolicy('my_policy'); + policyToEdit.policy.phases.frozen = { + min_age: '1234m', + actions: { searchable_snapshot: { snapshot_repository: 'myRepo' } }, + }; + + httpRequestsMockHelpers.setLoadPolicies([policyToEdit]); + httpRequestsMockHelpers.setLoadSnapshotPolicies([]); + httpRequestsMockHelpers.setListNodes({ + nodesByRoles: {}, + nodesByAttributes: { test: ['123'] }, + isUsingDeprecatedDataRoleConfig: false, + }); + + await act(async () => { + testBed = await setup(); + }); + + const { component } = testBed; + component.update(); + }); + + test('default value', async () => { + const { actions } = testBed; + + await actions.savePolicy(); + + const latestRequest = server.requests[server.requests.length - 1]; + const entirePolicy = JSON.parse(JSON.parse(latestRequest.requestBody).body); + expect(entirePolicy.phases.frozen).toEqual({ + min_age: '1234m', + actions: { + searchable_snapshot: { + snapshot_repository: 'myRepo', + }, + }, + }); + }); + }); + }); + + describe('delete phase', () => { + test('default value', async () => { + const { actions } = testBed; + await actions.delete.enable(true); + await actions.setWaitForSnapshotPolicy('test'); + await actions.savePolicy(); + const latestRequest = server.requests[server.requests.length - 1]; + const entirePolicy = JSON.parse(JSON.parse(latestRequest.requestBody).body); + expect(entirePolicy.phases.delete).toEqual({ + min_age: '365d', + actions: { + delete: {}, + wait_for_snapshot: { + policy: 'test', + }, + }, + }); }); }); }); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts index 73ecb0d73b7a..af571d16ca8c 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts @@ -114,6 +114,14 @@ export const createDeserializer = (isCloudEnabled: boolean) => ( } } + if (draft.phases.frozen) { + if (draft.phases.frozen.min_age) { + const minAge = splitSizeAndUnits(draft.phases.frozen.min_age); + draft.phases.frozen.min_age = minAge.size; + draft._meta.frozen.minAgeUnit = minAge.units; + } + } + if (draft.phases.delete) { if (draft.phases.delete.min_age) { const minAge = splitSizeAndUnits(draft.phases.delete.min_age); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts index 24dafa6cca23..0b1db784469a 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts @@ -267,6 +267,13 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => ( draft.phases.frozen!.actions = draft.phases.frozen?.actions ?? {}; const frozenPhase = draft.phases.frozen!; + /** + * FROZEN PHASE MIN AGE + */ + if (updatedPolicy.phases.frozen?.min_age) { + frozenPhase.min_age = `${updatedPolicy.phases.frozen!.min_age}${_meta.frozen.minAgeUnit}`; + } + /** * FROZEN PHASE SEARCHABLE SNAPSHOT */ From 17d4f2ccc14952ed6b763c7ba298bd9e61375eda Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 8 Apr 2021 13:50:34 -0400 Subject: [PATCH 36/49] [ML] Data Frame Analytics: Don't allow user to pick an index pattern or saved search based on CCS. (#96555) (#96595) Data Frame Analytics does not support cross-cluster search. This PR fixes the SourceSelection component to not allow a user to select a CCS index pattern or a saved search using a CCS index pattern. Co-authored-by: Walter Rafelsberger --- .../source_selection.test.tsx | 216 ++++++++++++++++++ .../source_selection/source_selection.tsx | 78 ++++++- 2 files changed, 291 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.test.tsx diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.test.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.test.tsx new file mode 100644 index 000000000000..858ab58b53f4 --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.test.tsx @@ -0,0 +1,216 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render, fireEvent, waitFor, screen } from '@testing-library/react'; + +import { IntlProvider } from 'react-intl'; + +import { + getIndexPatternAndSavedSearch, + IndexPatternAndSavedSearch, +} from '../../../../../util/index_utils'; + +import { SourceSelection } from './source_selection'; + +jest.mock('../../../../../../../../../../src/plugins/saved_objects/public', () => { + const SavedObjectFinderUi = ({ + onChoose, + }: { + onChoose: (id: string, type: string, fullName: string, savedObject: object) => void; + }) => { + return ( + <> + + + + + + ); + }; + + return { + SavedObjectFinderUi, + }; +}); + +const mockNavigateToPath = jest.fn(); +jest.mock('../../../../../contexts/kibana', () => ({ + useMlKibana: () => ({ + services: { + savedObjects: {}, + uiSettings: {}, + }, + }), + useNavigateToPath: () => mockNavigateToPath, +})); + +jest.mock('../../../../../util/index_utils', () => { + return { + getIndexPatternAndSavedSearch: jest.fn( + async (id: string): Promise => { + return { + indexPattern: { + fields: [], + title: + id === 'the-remote-saved-search-id' + ? 'my_remote_cluster:index-pattern-title' + : 'index-pattern-title', + }, + savedSearch: null, + }; + } + ), + }; +}); + +const mockOnClose = jest.fn(); +const mockGetIndexPatternAndSavedSearch = getIndexPatternAndSavedSearch as jest.Mock; + +describe('Data Frame Analytics: ', () => { + afterEach(() => { + mockNavigateToPath.mockClear(); + mockGetIndexPatternAndSavedSearch.mockClear(); + }); + + it('renders the title text', async () => { + // prepare + render( + + + + ); + + // assert + expect(screen.queryByText('New analytics job')).toBeInTheDocument(); + expect(mockNavigateToPath).toHaveBeenCalledTimes(0); + expect(mockGetIndexPatternAndSavedSearch).toHaveBeenCalledTimes(0); + }); + + it('shows the error callout when clicking a remote index pattern', async () => { + // prepare + render( + + + + ); + + // act + fireEvent.click(screen.getByText('RemoteIndexPattern', { selector: 'button' })); + await waitFor(() => screen.getByTestId('analyticsCreateSourceIndexModalCcsErrorCallOut')); + + // assert + expect( + screen.queryByText('Index patterns using cross-cluster search are not supported.') + ).toBeInTheDocument(); + expect(mockNavigateToPath).toHaveBeenCalledTimes(0); + expect(mockGetIndexPatternAndSavedSearch).toHaveBeenCalledTimes(0); + }); + + it('calls navigateToPath for a plain index pattern ', async () => { + // prepare + render( + + + + ); + + // act + fireEvent.click(screen.getByText('PlainIndexPattern', { selector: 'button' })); + + // assert + await waitFor(() => { + expect( + screen.queryByText('Index patterns using cross-cluster search are not supported.') + ).not.toBeInTheDocument(); + expect(mockNavigateToPath).toHaveBeenCalledWith( + '/data_frame_analytics/new_job?index=the-plain-index-pattern-id' + ); + expect(mockGetIndexPatternAndSavedSearch).toHaveBeenCalledTimes(0); + }); + }); + + it('shows the error callout when clicking a saved search using a remote index pattern', async () => { + // prepare + render( + + + + ); + + // act + fireEvent.click(screen.getByText('RemoteSavedSearch', { selector: 'button' })); + await waitFor(() => screen.getByTestId('analyticsCreateSourceIndexModalCcsErrorCallOut')); + + // assert + expect( + screen.queryByText('Index patterns using cross-cluster search are not supported.') + ).toBeInTheDocument(); + expect( + screen.queryByText( + `The saved search 'the-remote-saved-search-title' uses the index pattern 'my_remote_cluster:index-pattern-title'.` + ) + ).toBeInTheDocument(); + expect(mockNavigateToPath).toHaveBeenCalledTimes(0); + expect(mockGetIndexPatternAndSavedSearch).toHaveBeenCalledWith('the-remote-saved-search-id'); + }); + + it('calls navigateToPath for a saved search using a plain index pattern ', async () => { + // prepare + render( + + + + ); + + // act + fireEvent.click(screen.getByText('PlainSavedSearch', { selector: 'button' })); + + // assert + await waitFor(() => { + expect( + screen.queryByText('Index patterns using cross-cluster search are not supported.') + ).not.toBeInTheDocument(); + expect(mockNavigateToPath).toHaveBeenCalledWith( + '/data_frame_analytics/new_job?savedSearchId=the-plain-saved-search-id' + ); + expect(mockGetIndexPatternAndSavedSearch).toHaveBeenCalledWith('the-plain-saved-search-id'); + }); + }); +}); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx index 40f97690d779..cbc5a226eb31 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx @@ -5,15 +5,28 @@ * 2.0. */ -import React, { FC } from 'react'; +import React, { useState, FC } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiModal, EuiModalBody, EuiModalHeader, EuiModalHeaderTitle } from '@elastic/eui'; +import { + EuiCallOut, + EuiModal, + EuiModalBody, + EuiModalHeader, + EuiModalHeaderTitle, + EuiSpacer, +} from '@elastic/eui'; + +import type { SimpleSavedObject } from 'src/core/public'; import { SavedObjectFinderUi } from '../../../../../../../../../../src/plugins/saved_objects/public'; import { useMlKibana, useNavigateToPath } from '../../../../../contexts/kibana'; +import { getNestedProperty } from '../../../../../util/object_utils'; + +import { getIndexPatternAndSavedSearch } from '../../../../../util/index_utils'; + const fixedPageSize: number = 8; interface Props { @@ -26,7 +39,49 @@ export const SourceSelection: FC = ({ onClose }) => { } = useMlKibana(); const navigateToPath = useNavigateToPath(); - const onSearchSelected = async (id: string, type: string) => { + const [isCcsCallOut, setIsCcsCallOut] = useState(false); + const [ccsCallOutBodyText, setCcsCallOutBodyText] = useState(); + + const onSearchSelected = async ( + id: string, + type: string, + fullName: string, + savedObject: SimpleSavedObject + ) => { + // Kibana index patterns including `:` are cross-cluster search indices + // and are not supported by Data Frame Analytics yet. For saved searches + // and index patterns that use cross-cluster search we intercept + // the selection before redirecting and show an error callout instead. + let indexPatternTitle = ''; + + if (type === 'index-pattern') { + indexPatternTitle = getNestedProperty(savedObject, 'attributes.title'); + } else if (type === 'search') { + const indexPatternAndSavedSearch = await getIndexPatternAndSavedSearch(id); + indexPatternTitle = indexPatternAndSavedSearch.indexPattern?.title ?? ''; + } + + if (indexPatternTitle.includes(':')) { + setIsCcsCallOut(true); + if (type === 'search') { + setCcsCallOutBodyText( + i18n.translate( + 'xpack.ml.dataFrame.analytics.create.searchSelection.CcsErrorCallOutBody', + { + defaultMessage: `The saved search '{savedSearchTitle}' uses the index pattern '{indexPatternTitle}'.`, + values: { + savedSearchTitle: getNestedProperty(savedObject, 'attributes.title'), + indexPatternTitle, + }, + } + ) + ); + } else { + setCcsCallOutBodyText(undefined); + } + return; + } + await navigateToPath( `/data_frame_analytics/new_job?${ type === 'index-pattern' ? 'index' : 'savedSearchId' @@ -54,6 +109,23 @@ export const SourceSelection: FC = ({ onClose }) => { + {isCcsCallOut && ( + <> + + {typeof ccsCallOutBodyText === 'string' &&

{ccsCallOutBodyText}

} +
+ + + )} Date: Thu, 8 Apr 2021 14:24:05 -0400 Subject: [PATCH 37/49] [7.x] Docs: getting started with Kibana Security (#94158) (#96618) * Docs: getting started with Kibana Security (#94158) Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Gail Chappell # Conflicts: # docs/redirects.asciidoc * adjust reference --- .../quick-start-guide.asciidoc | 4 +- docs/redirects.asciidoc | 5 + .../security/images/role-index-privilege.png | Bin 80869 -> 0 bytes docs/user/security/images/role-management.png | Bin 161191 -> 0 bytes docs/user/security/images/role-new-user.png | Bin 69595 -> 0 bytes .../images/role-space-visualization.png | Bin 127770 -> 0 bytes .../tutorial-secure-access-example-1-role.png | Bin 0 -> 320953 bytes ...tutorial-secure-access-example-1-space.png | Bin 0 -> 328089 bytes .../tutorial-secure-access-example-1-test.png | Bin 0 -> 183305 bytes .../tutorial-secure-access-example-1-user.png | Bin 0 -> 219096 bytes docs/user/security/index.asciidoc | 1 - docs/user/security/rbac_tutorial.asciidoc | 105 -------------- .../how-to-secure-access-to-kibana.asciidoc | 136 ++++++++++++++++++ docs/user/setup.asciidoc | 2 + 14 files changed, 146 insertions(+), 107 deletions(-) delete mode 100644 docs/user/security/images/role-index-privilege.png delete mode 100644 docs/user/security/images/role-management.png delete mode 100644 docs/user/security/images/role-new-user.png delete mode 100644 docs/user/security/images/role-space-visualization.png create mode 100644 docs/user/security/images/tutorial-secure-access-example-1-role.png create mode 100644 docs/user/security/images/tutorial-secure-access-example-1-space.png create mode 100644 docs/user/security/images/tutorial-secure-access-example-1-test.png create mode 100644 docs/user/security/images/tutorial-secure-access-example-1-user.png delete mode 100644 docs/user/security/rbac_tutorial.asciidoc create mode 100644 docs/user/security/tutorials/how-to-secure-access-to-kibana.asciidoc diff --git a/docs/getting-started/quick-start-guide.asciidoc b/docs/getting-started/quick-start-guide.asciidoc index 1bdc9b9dea85..5e6a60f019be 100644 --- a/docs/getting-started/quick-start-guide.asciidoc +++ b/docs/getting-started/quick-start-guide.asciidoc @@ -12,7 +12,7 @@ When you've finished, you'll know how to: [float] === Required privileges When security is enabled, you must have `read`, `write`, and `manage` privileges on the `kibana_sample_data_*` indices. -For more information, refer to {ref}/security-privileges.html[Security privileges]. +Learn how to <>, or refer to {ref}/security-privileges.html[Security privileges] for more information. [float] [[set-up-on-cloud]] @@ -141,3 +141,5 @@ For more information, refer to <>. If you are you ready to add your own data, refer to <>. If you want to ingest your data, refer to {fleet-guide}/fleet-quick-start.html[Quick start: Get logs and metrics into the Elastic Stack]. + +If you want to secure access to your data, refer to our guide on <> diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc index 932139845191..12e66b0203f7 100644 --- a/docs/redirects.asciidoc +++ b/docs/redirects.asciidoc @@ -308,3 +308,8 @@ This content has moved. refer to <>. This content has moved. Refer to <>. + +[role="exclude",id="space-rbac-tutorial"] +== Tutorial: Use role-based access control to customize Kibana spaces + +This content has moved. refer to <>. diff --git a/docs/user/security/images/role-index-privilege.png b/docs/user/security/images/role-index-privilege.png deleted file mode 100644 index 1dc1ae640e3ba362816d3240e4f7ed074415ae7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80869 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≫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 diff --git a/docs/user/security/images/role-management.png b/docs/user/security/images/role-management.png deleted file mode 100644 index 29efdd85c4df39b6fd1b756878f0784df4c3b036..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 161191 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νaJO$w| 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
}ElG>s>)X2jC>}UeeDA*QE6M-oFv#yWcc@vq3Aq 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%0APH_{>yKl%`g+B4IXz9kt?`D~)28$Ro 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%0AL0)SmQWn^Xf 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
    ^E-&}I|}zZ=J-2g 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

    ~s+2Q#Xxt2eH{MTj+9HE7sDq(!f3xI`zi+ zTtwZ+wPw;_VgXM#X1nG_#AGG-#C{@GSTw0Vn^;HnnTH!Ev)of(i!lY5iFym4dul>K zp28xV6Rb&nZ7GP7+wgQFHa4v|s?SU(x7C*`l{c+0MX&%wo5jpL{`Ma-n-bdctk7lE1F>O_99(EGvip5jdi< zl(Z-uhs88un{$zxsOj5qkZ zY`%2O6lUwvOl6_Ghy?OQu;GZ;Z?@I)`ImbRSEsSjDF3e^uf68KuP}?I2|?WgJyK9{LuP z#ni9K4ts<@6J@1YxM|xqZ&I0&7qLw05txXyY=xQTBTUpc8MxDPOV65A-X^%!t&DVGTr5d>{GhsI#e?4QGKbW!f<*C z-V?j|{eX>u@KXwbfu!*TCrYNjF^glRH*ca9ovX~<1;Kt`&iaxS06-D*FCw#8PSp_` z2AlM$cpM)vK=sQ~uO=BjLrtf4k=g1yXL&p>x<_UT*+JMs*er}hBm}P=tdJkOf4gVz zIXn8hxTWOoL)tb&*cELx6Y{hbb^NE&ii1N|EBGu5F2qan(txcEQ6}YShBat&J9M)N z@U%0eecJeRaU2~nNX%4UtPku!Ez=9l7C%1QBEvv`ebH-@n6}I>*o}4K8XZlSWep34pOnv`t_@hyjXCzO$T+sjG`ud7L zQyJxZn0NQiDr5T|KkR}$^~y-w))k_ zdH6nJ_zmTTFoVOhj}cmzO*hv;^tK0>8$Z?ZRb)bLcyJnekQ#-g$B1GOQ$D?t2ptYF ztK018JzSwA!3~PxmM{4?M&$Z8% z8P5}jXcSp|IJ!w@saTsU&b*WEHi{NFl#*JjL1{nM9>>4a~ zXA!`DPWLVq;H5LI&WTn?=tt9`>AG`r?HZea%3{yzf_0F8-J69sV1iQII6&H_a~V#; zKP4o@HOS9a9suzFbP?P>y|b)3egqLBQ}aS3WrO2H)!Sp|_ZT&KuaO_2A2!P%gYMD? zZPce?fLMd)#@*he^f35O`hx27=Xb4mq0%Ya)CmhEUn}>9I~Ys`-F^GFi+%g!ph3wO z4{G&UONB^9!!yXadoxBCt2N$y!NfTBsr&q7C`qzvFjn_El1-Iw;6t?7Qh~gs>HE?O zGq1_egJ-YV)IptLx|V1iWo7}zZ_sV+p-A68t}KWyDb02wT96(7LeXTVAO4Af9vuL& z)y~3AhnzM2nCVn6fZ4<3&|KS^FB~q0gBBUyqmP+5s2NdHry?A8$o1tH1LNkLOrzXf z50fCjD|TwLIBm}(IGxv?ThHO-UN3>2wFWLAltGHpYj%z;g_|+d+u5YACKxj^?=ZU8 z=vtkdwQx2)wA7KdYdqzg@mCT7JhE>gLo>|>=>PBuH0kMWe=6wIL*dvGX)Os* zsi}eDMZl3u5VmuFlp=2ykqmFM1@%Z{rm9kNw6kw^!3$w%FhQ<7x%?>iS@7#pfTyQb z;%W+ClsDx{E!s3l-Dg^C}LJt1GOqWt1hjPg~x4AJty^wy#c}4jx#QcCtNH zQ(;=SBf-kR!?Aq6G282G>z_t@19U`PZ3_(ZSFCj#l&yz1SP##%-rp-TbPEipFo@I` z?lea`NMfR!PbVd(n{WLFhE3$MVc)O!5?w<-_m{qOjb)kp!amvo^u+n~C1tWLz}5xfQ@(<|7kVMEk6?rE-VMT| zsL6Gi2BeN4V)J^Je8II!b?fAlY{0{|-743zu~`~8o>$GuWYKxXr|Dz_j%A9CzxD?I*f1wOMqV`cukx=PsMg9YGH2X8}@X zkvH|T=d`g>ymw=iTFxbO!n7%s$y*BiZva(J^qiBq8xu$oMvW*wpV5ZwJ~Eeo)cT$f zEklw^S>C&(j!4J|alB*bD<{ll`?V=TAK|lSl$-eJm)_Nlp9H|Typq|fea`1Libs0h z=B9tl%4e81+OXh4PZJ29hgj!q@=QzWPc^BG8sMJK`mWb1wg$knduB+5Zeea~Cc)Oz4YO86H~M^p!IW(@=_f`4z$NQ4y`4Vu^(gL z=X;uL&y&mKZGfLm@qes!pMis#4D!K!tMfbIIyNa`v1#su(a%p%obRw~@hJqJaHn*h zKO%XBXmZa1gx#lW9tO;6MOG!_muf+Hp=JY#la*;DUbU{)BSzbV5u!}qm&XrhA*Jp1 z+k{B8YS?M2a6_;Nu6;a^yt;_C+|j=LH25Yx0o|ql;ozem0D5;yKWq)8N8mXPY_Eo(DvIEgXL87;|U?@7y=UXY+%%!?8opy4u zZT=BUYIm-7*yKIqmR+|F-fthmDt{$OS)c2RaJ3Z}l1tKN-2EN^fTK$FD7>g8i}Z6D&mn zU!TBRzoj-AaE~XmI@J_k+sG)#VVY-YOZQiUBaphM;R-o(cpcAEZtfe*c*gf^LT+>vj&n0~o;hdORKSBr31bP0REGwS{ZRK4)3MtiXU zc-4W)^2jdLaE;{$sIRSRh#6+FK60s!=m>d}YDKM(`l(Y#vqQtyz@esTx-`hbC?M|Z zMb_Mj+)_Y@NJZ}c^!^EbafK{Q1o{?(Z+?w3y0TWP7)w};hwK}d?e=S=9n0VP3@j3m zoG-bNf*peLh79Uy6`1-G&mTv}E-_gu(}P!eXK)`g4e(ymb7@@D8eW&d`cI7zg{lTZ z_UKI9g5pLArn%E3yf;|xFrqQ=`#XKcxrO&xU^h-$-3ct%g$hzQNXPmL zvq-ndUW^QwGhQ* zAzL$kZ2e^w|PbT4mlQdshb|`5(_Zfl|_FKy? z&$QUBjXD!~(sT{kfQEG!Z@FZqwVyYmP6hMT=tO?KV1z6wDwOoR<3uAFItO&Q-@08l z(Hvkt7)9sX9b0*DXAwZm!ENL|&RXk%S=G^G2Wq*57c;GNH`|rcpLuRiFmio1=yYzr zIzQ|iiy+qNIfuFnW_^J=08&1jr)*ISNrCZQ;#i-_g|8wf3N?E~0!|VqTEE%CY!AJ* zR_&@TP}QcWz%zCX*SVNJ!nasU!)t(>H3#(FeW!bZE~AXPyruC#Tg30Mbe}nM-K6t? zG}lvH^A~{2?NeQdQA`1QBpxTRbuF~9kAD}8Y_;Fl&m$U>XEs*_lu^fAMe3D-q0b1e zIwzIZ2Q~!dVozKKy@eZIl(&AP^qFRJ-4P|>mJH4t^#zI;;B8ntNn4*&kL5utwWVOT ze_+(ykEAiaTm@rRsW+7dnnz=L+MHPxtLFI$(HK&i-Xq0q&Pz%0db-ux<#MdlZx7QZB>$V@bz# z+DN|d+1uZ^-oTtz5#vr!qAgnQH*T1qGzUWfIpbQVN_o19^k<;$QQx9-4qSYL*K(95 zIGB)=Y^bG)rC~+DkZ$OtT3M=w$|+9 zftWS;hNR=+!e1xd#)p7*dDGQ$QGDEt^$TbB z*9J3`M>4l#5z#|JtF+dON@2i9jr#T+!?;>12E0ZME=mql6$B`P6+<#5{bhB8ptBFw z4|bn)2UCzN@x_J+wlat2ChMzQ96|VB;rvwxa=-J95wxLnHBT5MPaoNp`j9%&6i{AA z`==HKixKnF{kJ6UHqVJnM*|dEhuK$BgI^CiqX&yUHlgOVSY_@v$I&q?L_)TKn1W}q zS??keUtWLARD#Y*ZdA6MOno`ElIN77-Eg(Jyaq8Ew%zpIRbWUHg@r}&JDUMzEtLuG zK4s3(hDTwo-ynfaOt&KU z_tG(|J6vySu}<|zZ~KNdL?)#HR|telei0m7A?m>Nz15QXINbq*#>LQ^)2k~ltsf|^ zEB^eo^9$`f9Ef$bnzjl198o8p7wOCH_CP~W3I`Dg2F(>_@}8xd)kMJtsm0WmtOkqW zV;9tS^{?b42k;{Pv4%nC)OBF4I4jpe;&y(e=0fsm+zF{^=}sZaT+i(l!ylF1*nDC-%b;g0+%Yl6JDb*O&%`JAeBIv$Nl%c!rq_ zr>6NU@-KE7&_^5ZBh|zNRs8ZLS;Rumj};O)ulbYc0!PE zRbaxOG-YKoe9CH0=+4xuuMqQxCSEU4L}qOS({fOk*#qc8tgE3Ho&E4n(kHL8FL}Lw z`85hze0J3WBFbHs2YwsZgV|iHdf9J{s#$a!qz|E=R`@ANGAQsLejeGvc*^c&XveDd z+gX3l@RQXVkx=kf6c7+d-CM|!_W~%KnT9a))h=7(`MlCXDs<&RWnpuKw~9ZC|eN?=mc)f zc~5?Sw-BRGBIpwrah8>1t4FlkSH z=cHk$gvUAFU@u?JhHgJuU_?8|iEcQ0-UoBm&e)GYVAFH8_q`Hv38#`D7G5S$G^!xr zvb{Z{l;<m1sTIXy(iT~}&hwz0ARpv_)^KYe^cY!<#fu%`}# ztP0$ox`bAXVa>>S)4X%{f^Bak7IbHQFfHaew4t}b)ljxrz!5nwQX(5G%W2uJ1)B6I z_EO@RsaVrB*Cz(T1AV;Y(|0>A0;$iTO=*l|_cfZNQqq0xTMSx;9yH)wu}rvSqRtC9 z(*IV>{s_kp&^HgX`3L=0OVlowkKtR0e8*|h`zWNuLGiz9fo~0oO6Jx;zO!EWb9Z?Z zPTBh7eOmn?HCB!~GV=^#8LA;bI{U#BY#@2KJY zhy#w;s2zbsq4O9Py{hT)!J(AdfpONGjS19#hnq*)hmQc9X_z9Qzdt~7aE*nNeXiOj z_QKh0uqySdG?3Jf2f`*EH#hTMMo~v9I#Y(LbZh z0Vd~zkOcK(x$FLk4wZ1`3l0p#^f`)2-vS?)12BC>orLssV>7a+-Y|>6;MPTYXsJ}# zHm8+|UjKE>!_aT5sC-maNHc!OlcsTl6K_|n_%nFq8&kmQW;<6D68o0B7PbVqTcv!v zcZcb1l`vF9&R56ND;uzoC`?#14M#hoiDcXP6&>JY;4PS4mg`@EDqukkV61%}peG5c zv}6CuW%|}Br30}rjT#x=ye!m=F48WIQ!j)_r-`ulPub4x4h|KfwAYdKS%?IHBCe^R z-?~HA$-TLzc`M}{Iyn6Th~L?{0^odZzjpw#2dR}dmzZI^oZTlj^Q~Y(RgylG(w1ij z!T>cw&dl~*#U`hbvd@Scpl z{0}yLP+eiNDQ;D7JVGkrdfg-s0Ac^jjKoh2Rmw1w0aNZF5krk1&Hxb*D@K`5P z1gD=Uq`zAssi;lK9o#UV{}JS|zEx-Rvl7q;*ziqU%#G*u>$}I+@aCBqy#+*Qt<9IF znvRHZfQPi4S!Q%spC0fL#Q`Rd{vaA?y7Oo@9q%i|H$B6C&NCD<)UwRa&|`PBd#uIK z-aHyOi=6ICeZ9~dCB*V!%QXQ62hJmC1+6S(WY69=U3fdGUS9!Yy+sE`AX0a|Ph*(f zHMP>#`dsl^Kr8cg98ZsrJkBe+rmBb%4{{f61N=*LMWcDNmd50`dV`fjar&QpNb3ev zMWUtdn)ip^W?ou>YRLz9tVQqz;_WE;H2fI~wlmd@56-RAlKyHf@Rwiu^Xk4K5J2n~ zM>Xcb#%q6Y1Eu8bGX7YNjGa7}t-v@YQW>r()#{^-!8k9zg-w1%49)_W;hgG*!FLyf z3*f6ge%9wm0kehD6ESz;s{sQJrz;GNI?F%yWCLo3W`AQhkhMl}xc`VqyAY!s<-Q0%VppS*? zx<67%`;;W3XX2MS`)YcfVUkWBVl;=6Jt{O_-)t{xqV+z-6BIB=Mm(iEAHT8tc2ggt zwp?ae8U?MxtL#=%+FP5v*Mf6o`X6W60&=sAOC)^UP%45nFXRI;%0u6Vb77OJPXFp3 z+nG9QxC^+$$j;Q3(p3fZG<}8vP?ta_8T84T@hmRL_6M)L^_}Ad>WgtrD|9h1Fubc8w4G@Wc zP)&h`J1-(j6KFupH++bWNVflN7c$?%`%eUu)8y zK?tn+AKSv%{0%(c8(6^l0L3{9K=J$)2QyS%zA^!*5$Y1D>wi91i@0A6<`Hi7r?1P& zb99Sey&pPqdP}==zfzU^D!BMdX?`afDZ>iP;q>=dZU{y!eUu6-OVvZpktiB{RlGBj z@sar4p-sGn{>%2Up>ug^1ZvM|e^IPHC;g_i4)22P%&4Tvy0i4hZDIFkF?RgZ6oFpEs^s7V{l&uAFpc{G z`J!Stph$UFmlnbZ82Y%-LoU)6m@S+W3ItBtq8n0SWNZPyh4E@>d-%nn>#NR9nk}H|FRsj!(lW1Wm8L%1r5P z`h;y8A;wvCd!rSeBZW*U>Pm+On{Cb+4!c+LfkIj{r3a_dSn^m8pV0~gfx(-}y8@pn z3TS&=S#C@M9`bFVY$mOSEvs%)1e&Sb}FHZb`Z51hrP| zffb@&NL&%3;Cnt|9JXn;whKEz0ZwJyBr1$AH!#^)3aftyQb-e#*qQ+pWAr+E)xw)h z+B^A#TDJEWLJHXtHU=Qn{8Oh4HfR1QLSi6%BcWNn?m?AAa_vb z3^V0;cR@Xo$9j2zCv#0A2!CL(_Q~P1EY*9gsMkwq@xvmzrtnD+?Hcs zZ4f}@bBMy9TVrr$KYl)Mlxi>p^wH==WtEFvmg&N9K*;_d9q(2vLgTd&0YKLdfi}M; zi(@+e*@@riV0T0uWoTh;83a_|tCANEzf^&Rka?ve@&JL3N`>hF*@-j#By$wfT!Bmd zJKic*Txqiwt9GRsZjoZSD}~k+a&MvOay3(pSSB|#p=gl?)SvidM;e_WcyhxSUEhh< zvbC$m7N(mvM|PGiW(a4bOr{t%elg~JTPR`l61>^scVYh_@ZlC6=yZqrqH*doEpAb- zvB(NArNl?$MgypMnYc)v0o$i-n*VA>9Ip3~J0{&!4;x;J9Q=(i{-^Yu>hm9MYJ9M^ zL;02*|F4XkEBd7h|Nq18yKu zSxDf+-h4p^92Y<+%le_$O8aox0=t$s%4Vj5?h^|+!E16qp0v_fAZ^*_eh;iih z_!b5{U%BH((SKNrzdkw=9axoYG|s%gZtx$j{HE_eA|W7mANu#k^mp50qyoAoKcI5{ zQ_%Gv?hKgF|Mdq?kaXqzvlqZ$i}(N7OZ@)_|GNeLwHkk1{eOG^-dK zSvWoNJ!-G}XGjn@+oRs68#V7ll~?yBQFBl`afSa6``mWYn1#S-Oe|DC!8@=x?CJvTBAbqAuB*97F&br>zH$Asgfr8LUUh@|M9r{*UwyR zC#3q=8Q?x#Z~UK})So_!jRbf=wx7C#0sjGr_-~7HSOOe`;}X=lgyf%n-k-Por$_X| zkpg@d&bo$k#{abF|N1+3hqqFy*pF*rVU+Ja8VFdWI=Jp0meOphgHt~LrF9jOa= zo!42T)|fT4H#Vp8!}J_I;=T>lI!y}fpfa(9uX{0^-i?YAP?QR~Z}Yx6HfOO<)f+45 zS|Ok;6;-{c%*nA@1FtQB`gI33E({sHOKA>X`&@l>**(p4l`f|a$ad@y`0?!diT7=s zX?}hFPDMXP7APA&@;x0w9}3aAGhE!kui_%p3BM7eEY02 zrauOy8{2Q$VB?xk;5$0q3&B0p7j3L}1~n5R>Nof{>bNO!nhcsfC6_vV-)Fw%Js#bz z;M&Sbir56&m_~_-T8C)_$K-e7%GoK=K;At8WEP~tU^ZKGzud1X(j)l=zP(ux9`F+N#rh(+tS#L zw9>P_`!5Hd1ZpW(iiu)hFPD*~~e1vxA-~Qb1x=R(hzts2P$D5Y6kI>W%gFP#?B59u)m}=ISxe$l) zm7x~osFEmqbn$uEcKf{}l{k6I_Z24J{dZ+ryBPKDx}US;%BL~R`Re4}jb*+pAMox_ z=@9Fn9|=pUU5yf~u@&DM&pF*X6ef~l(Qb~rp03a@DK|b>QOg(KqAEp7JdxtaUKD}M ze*Zuq8_`U&c~S_8;Z=~en!F+}mW2gkV&pcHgoL^c-jyVIbpf_?xo$V*PvrXWR`f;a zeq3JM2vw-VnwKsW?~{OuYAda`90>VTUQOb$P?9kTXjgK#c6GR3%j-K=H|Z2ONPYJX#FpPoB=gNqg5mg2gF#N;(0rVQ^Y>FDxn-!+ zO4Won;GaT2(X^8$zjl=hd89GlH)pH+{XnsRSkl*H|`Fiph+0GhFqj0P? zqwRA(dpC8KKG!2Dt=3mW^-j$S`p?`Xwsl;!q&c2GBz^VctcNHM`y=MpZyeNBj>uy^ zd5cdaZ%7D2`3L}(>)(F;Xm=iC`~bx(6@RVJyN(CiV&Y|+Fg zYc|@kX%s0zAoa;#UAcQ-jf5bkes|VN3XZQp@}Z{#vQ|RUFX4Y@oD^#>(T}5@H0QH` z=8*ehme(g%aev@x-v9M9vn5PLSa;u`{o9`}QfTep(hm-GtnKg9oP}L7YnG0qF7X+| z9IPq1q+H@5$i*d^29F&)VV|qC`>q5@j~Qg8pP|$I+G@E;?PVj({hd1yU)m>xLsRvH z$Lh&It*LOr&Dub`3#yy7fmJ+~Rwh}wNZ8M`$leZlb&ez8cu1MZgCwq}#ZyozcH&Qn zAbCYC8U9RWy}AbIQwFqM&9oYDpRS0H&@450-}#N;EzG^KPW}k39p&*%L{zgBnx4dG zKTx|9t@X)q|Es@;BYWpT^P`@f{#SYpUg||iQaYu$nB~szrqBCxyahjWrht)Mt{!1g zbTabTk2@&CIV;!=fTudmdd7zse2p=`%=4LV7Zy_0ybw;kr+whP_byS;DYQI}W@2 z6)KDFdT7!771s*l;oic?_FhfIU4(8e;xX)|{K~lhy8Pq0Ht&XY8lvs}O73?Ncax+g z|Arly-%zS^97Z#%%f|VdHQX!NEA)4)2dz@vTcI85+2?_=9A6N&@L{h6R?(#0X5YP3 zW(`8j6Yb*gHVA%D_A;V;x*WBN{ON{xLy{3C{`}vXB4DNM&+pu)5#LPqpbj-!YAd4j z&FFZi^oYEys%a_a>tOgL ziFa<_QX+YNv_3Ha*y3TVH8%)OZCN#f<&`88%Sp;(tChC=z`r(beaKMU7r~#tCt#zR zEiDTbtc_YbddiXmlx+`Or8nz8T=_*I=tlm=M$h~sZBWF>;~;tMa!>zx+qsGtDMH?X zwmGxlGoe|v)F>;sL-{&r8z1a1Fo?7<)?;~*{aQu3&0tT`prFJ@W zd8y*Avq{v8)in4P^H1D7DmjdA{IaSX#|@8HEkA!qy#&zoA7>2(x`hS)Xhu6VEnCEn ztWH*AWzW}!64ckL@p-4%&ek*q9QJ={(AG9CSjCFws8F-W29;o}3L7y1%Qn)O7QdZI zVN1okI$5e3cJ=j@-Rg9HMV)-Uv09eZz2fi9uE@m6hx;}hHn0YQgL8i8(=Q@y=F^K) zi-qhj%}-eZ4_n=KhpL&5U+OlzUK>o&U*Jmop+O!WpsYYXMaNtoJ|zW(FMuL_t}M%S zRwL86?IKyY$T`jvI95w|_g{QW>~JF6R^mel-0+$TjqXwK5~w-SdQ;5%*#!Jl6MaSrCRI zo!paL9UkWQ%0sogo2wmgoymqzm-QyR21oykvbT<^a_zdtkBWpyY)Tpd3F!_gX%%Vd zlJ4#n>6VZV>5}e-O?Ni}o0jg5-^Fvz^NjC#zw@4N{KoJPB=+9-eP7pFbImp9x@==o zcW>qu?5Tlm0p%=cV7BP=Uul9hOmWM($ynb)oLYfq|*nuVPU6FF5MHGzlx#RL8@~MfE z?FEsJM^S~*(f2mOJ^q49FU6vncLW~yW7?9U&(^*#qOcm!{}?kI>|4j|Lbbb)8tZJu z`KRUn_N5)h7bY^F!C)#VBF7uTH*WI|Yi36D-xy8B4Q zC5d+6k0COAoPd&uF$Q*w^!NrL-W8KFo~e8$GNrJec028_bI$8oA>Zm^e!2QE>39tL zLd>|DT=$#2am5J|Ywfnj<(gg>eK(%-4OSf1nsYR*kC{7LR{2iqj^FpDUTC+03lll+ zI_%CO!Gk_Q_-Woox>j*m^l)G-)^W|?**UV{a6dP)KIW-v_4Zh;JL?BpUWB~&m|`Nq z_}|4)wzCv}JD-`b+O58-Ek-8)YSnb=WyV62y5z(Vnt0*O@b=kGZ9Duvqc7=V(zI^N z!AMl{0uSBr(f+*LeG_a$a_FrOWY>p@EF&1)-c+roB@fuL{*}e(#~k&zwW(8q9HFN+ z1SR=UM4ZE&8OLs!;ypc_W^2`Iqt6#a7;#L{C`0z4fyM9}KI7O6Zel){Pq*BEX!{Vo zj`sco@yq}A@9ieVAKD^_$pntRkXf6Ru5jALJxRvr;rBtDTvK;dD)-)e)p$JV;iThF zn%##ipOyz3OPRf;eYvnIO{N}{dbdGXdhn&q#7ZX|6TtgeXG4-5cr{k_`;%jqU-nL2 zRgxzbW@h2UeE7~R0`S)Xo93SI2N#l|tyddFK>U{p2+G0nUOkLEhXC4!Ew#Gq? zM;Lc#rf^E8k-#4#Ld@w<>@HB=Ff#{vcfLI0Tc~f*D+S!v-I;EUs!!Iv-ImC~r7F=- z=u`UAG+K%5@CpqZ%8(__%Gwl6f|oPhG32fWE~iJ>L|k?uXL|xa!`tx6yAYc=W=eX{ zxTJO@vt(L%quFiY@r3+*X>+7fzuV9HtKh@3t;&C*)1iZ`1CNmMQ+s7Avhm|8a;@2+&Ar;3MF+LD{!n2dsb0O8k zc>%}0bS&FaNGc|B+tu05%Qk$Y-Cx*ZaBFU+wln6tMG9Jcv7fZziUWsi@nDb*a?&5p zXE)sDGj&m6gvjXMtlft!%vX=SkCQHVYz|70>NW_@F63TnNgduuiPAk^G92;^R?<^5 zSeR>0K4EGnmKqGQg&I$W-;Xt$&Q+S^E>69Uq_RKodC3#U-*9+y^zsl*p z5f0C+O;+Z*RMiT0;||Au&tFQEeXz|dt~%E9;P_B-@HOiD#v=~0QvzPartcQ|-?%|3 zA_=OYGe&wSZa+4TuDOJwqXV)TkyUf7RN?P`TC#l`*w%IAu7I!m8Q-CpN^N~_RD zbPyO^z?+`nB`BGzx|x)*tj>5w9_LyuMIV6TX`))^MsGe_rh%hCeU4Om?Lt3;MBd-& zu8CGGA$e1EnB*LMLRQYST)il26s7PeO>(+qq1lnjyETp{9}IgQfFgd+;W-a6__9$t zmMJCZCM_0#?&YYzyj|tG5373=v&b(UPZqDZYgbSt$v0)-u+|rY1+(wP@08<%J8({9 zGWe3VFoWuPw6wCUM`5&NGx4S8dI!npDHfOoq(ur{uHLScdD{T5iA?3;XPidl)NILP(gnVw5mA>b|QbHUXXLG*d<--zDfW+je$A_Pquwx-CR?}6;7i-|W z{g}ie{z9>IIIuA#_x&w{VzGH;Xn8|*s@4`ORAX=FGV6ZH`Y1);E6j5P2mX+P1P$m! zq|w(G(G9dkjw!X?_;_-^YKM#&G7OKDY`!iFfU>QJjHqBMjC zEXCc&QqcPPdo{1wa1;8N{6MqNh9mf@f~zgnwEhF%|C2Com$epc1Blw>+ys4%5udb0 zUXyZN&I?&VEw#$6W1>{-w5dX58lN7p_fM56EOVXLJM70QfJ-&GSmmsmvGwOJm91?? zthC-=c%qW^jJ(0Ri0uh4+Jcsk^1IIv9YOoWyWOeERf6$#d)3{!WK#uP7@ZrmyHtJ? zz&4vrP$kHJgvqvjUkyrAXa9T@rz?Jf4L|-4wXGn{V%#-`&)5hid6BSe+LtsPH{&>r z>%6CY!D6BJMY(N$&_s)eQTsh^YkGv>Z5>yD>&3;MfYUp7gs=!PwPR*q@F9y+B=VWk zEeiA7wcqszHX>TTLzMD;whBojG3jk^**&snuhCNaZ7rloLjr2M49#2dEloH-loKj} z<~SE*X_WxXF13b<*$W+PkUh4@1LL&&KlQd_mM55HPa zyjVjaf`++DNT}JT6`=l!G~_2bi2*Y)2()-+g8zFd{r2S!DD457`wq~YZHVhG`k+RQ zh;CCNgJUpuk2JuKQI}C<>W`aYy@89_W)nN6@tmHyVrD!mO|{`w`yX*(+m|!S^-eP; z8o1hLF_3v^K=IbZw-kCdj@ij6!ky>Zge*eHo-L-@#dsaT*e}E4_uk9-LL~7g$sPDC zzR%k2kO$9<^?=Idgwg?uIPrO}KNxx#bw7MA?-{)k?+f9(dY&Ur*8cG`F(l@$E{wx` zfwD`+7qY;ml<;UF9;S)S`cyPT&#_2B8_u5|c0i%{Uf&Fr;`4+iEpk2+)NQcR+Noa3 z=U%1q%uyv%Q$Sc;itNm!HLn`6G|jg@;%TqH%kwAK4%trDE7X-|D!UDFqHt$?0b-t< zl4t~a9(Va0>8a=~uPV@6xCrKoEbdz~*lY)dREXk~LSVX-+c2Nb=ldD{ridV9{VPrR z{HiSUn94g3ywYgZp}|p@p*U?w@ZcF%6Yct){)%tp(`vk{WYscWOqOD zSCHLYVN0g7G}cDNhl@jz3V^$N2RJ;kV{l7A9@%1@-r*C`SnP{s%oCn+T(Ex`BJ=wt z+CR}#+TMToKuGOU=CQ@NSj!e_oD<GEAvMBrU4>%@Kc=&g7QgKB z4Tk)IK)z=shm2YagwYc1&Pr{(xcIX>xzGT9zFDN$4J3Ls2f&;*shD#_&LNS*qY^P{ z#2$Yp%vtEIN1EbuIbl3Shv9PNK?4kjQZR>ldKl)te`1l;pA*00D6s|WxALuvBTsJVEBkM!REOyG`ws(>58XG&>83O!TKqW9cO z7nM-zp_wSzS#-ta!%5@dsy+I->_C`LZn?LUgu-ULK|zN^p46y4guv?wW0@^AP31j9 zHOC(l|2@|2W`rYlu~nP-jC=>G+<-2&7iJkcA1@l0!a=5vMrF`V$IV^uS)+N{AX8vK zv22@30W$T1lgHtkofJrlO|$1cDZo7;593>*3-dp6q*F#%Vc&ai_;x!5{P;+6BL))gNj5JR!#VN1%{P^)H}62Cy?A z)+sq?lqmp(wC{N%+Nb!ldP_$QXFBn0Jq$eHl))j(^t-w(&R>m9&KAcWM%ZFby{&FZ z>+S%$R_p5Gx{6OX*`gUQzo---_)*}dsEGe$!p6{90e7U@&{Yi$OAuSkZinM-(a20? zQK7`KSlTo4>A62#iIy_!)Tgd;=WI88W4|9h(p3DU?ZY|v-QbJTRQBM2v(_{6-e?*r z_WT%5>DT89x<5d4oAF^ve?JVO6K9|A99Djsw^_nw$Lz(RQ0QjpqJdaw;)fRunh~y~ zFlH!2W5PwGIe=cvpQg64k=`!{e|n8XChl7HUa<50-0)x8<9n%#AQ3<2WfvGk!6 zJcW<*dG=F#vI-4)Ao&c%PYRS2US0b&qL!YMO1ZmKym&0&D*YjU1GnCkwxm|}ANSx( zbQ?gMBa)uAz7COD%w4U%qE&J;Y+)w3vxRw)mN7+&hY<#r1y(m|NdD{TG}{b_sWxi| zH({Y7M845yflZKch=vnOc79o``OWydGm+p@4mSkVSuH?)Cta+PB3-XIUKu|H7NKo8B(y0{60n`D zx>47~?UnuZu#RRhj6&wdsmOP9*yjyz_ojB^Ym;&6n3V!w6Ov>0yamUmXIZihMvoqN zp}JSXDaG1NG29Qcxd6FAaa@E*UZmbA)h6c7IEPTpBqT+{-*BmZB!Zj9kH&vlgXk{1 z!fGCfs&?wyLzjLaf(r}Xc)_UH$S@&;zvTtzd;Obr!x*$NT+XpxN6K}EkIFuVyrJ~F zAYR{JHWiBQe9S8af@cu{pZdI`?9csrPf^6oJu)ne9JV}pnOM{T{e^#RIhUTJ%9E~` zU7N5NXnkn;BA;pirp0q@9}z#af1tzB5#=AAY}!~BzUS_|dx6B*vMrBm@WP-j90ByQ z@SPMLjS)zd_D034$w=h9$yz9d!#}Ovd*k_n+Y%I%j`onq7w~WZJ0bc|d&CLbTknN2 zLFG|Vky)^7bP!qX)3&E9N1u`Ma@$?h{FGZ9X0K-7zy5&BY}tyTy~_78XM47kI}1n5 zvcN8SWkx!cs-S=Q$-v8gOZae-UyGA9O-?iTvkmtCgu-Bpuc!;+!sd1THKr%UB zRIjJ1-1-1X{%7Cqmmy4;Q2zg&Z1@Aw$Kx@&n9ne`TqtNxOYuU)a^c-^6rU3X;goX{70Qc+CEf-ggCmgpA8XL;&yKw+}jZ$)T$M^sC<`& zup&Nx^y2WS0x>o%B=V}e%3u!_jHUN)*+b%A+_fe7+AS@~s+i%3<lze)QXR+Jq;bw^eXk3dVs`L( zE~cH#Xp3?4t=inAK1H+ywDM&-5}E&+jafWctZ+`8XJ53uFi*hzo*@XJ{in~`m zWK81n7Q%*8k^khrkb|mUdB6Usd7qj{x`&I3bch34FL5 zrmtubzK`h8m)bk|9I7oiUX?LNhDIhGtq)3t;*Uo-EAfL*RMSj#Y-+J{X>N{V9~XMv zr&L6Rnw3TY%GsUTU^WNna}{&Ld3jMZMN7l-L;cO%_jVhDeB5C?P{h4WBn0l#D71;V zY<%by3UNX4+!l&6KL?Ij31mF}qMf%A1ZpK;p0hM^s^4Sri=FF1%~ku^fG6BE?+2@1 zb$z?Rb3Y7=v50vbdZL1CCymGZjV5HtU3zHZnmWYkcpas3cRcp6n=R9m6QQj%`H}o~ zhB-)wCPoMrb9JImdLw_67beb^$+{1h9G<+x&E-bfnVW&#^gas?2iGwI=)ltiHzBxF zP&maXbEjRRAoGMW>`UNCBW7gbE5sJR1eiL$%x zEA~7YFJ4v0*eU?JoD;9d@dQR9bg9;^1{O=zb6tpG?uH=zSJ%Zl>~p^p7}V;YU_sgZ z6?jp%vAR>c+*6)VY>nEO8K}aHI~oIp znDhR>){ox<)^5|lJ^izvz0-7t+Zt8E=?gkLn|>l3I~zU8p`*ddCuk&m*}q)TM)SrD z?eY2QD@i#x>JuJgiaD_~Z{fX^N>cumDZ}4;Agfvj*zVmImN_;%w(Rkt947rX7F|&E zGs0G};t;&io+2}&-AU72{*P~3eRcc00*I4~H0!0deZ-Ll$e(iBDB;485ZtXf@OXsd zX1Y5qmke?I)|EY&H%He@D@1&vhM)Jl^=pk^^c%qImVy<>+Xs-9G3b3>`Rru#Cpy)q zhAJbV5s~AR<@V5pd|si@ih2NJ1Jf@D;H{c0_7>`;ug^$Egwc#v;z044QgAMd+xnA@ z^FC?gx>Ol<6V0UUropt-|E0&h0-&fRmt*!siKP3V@nAZO^+1`R%SyI@y|BUA&-h&5 zgDdptOg~eYM<50z`T{wNjF`2%2-f4DtbpJMl)vAcLaWwp{RHwg5ggW*yCH~#DMmXD z69?0Z;G->Z^z&$?Bt-+PRQHl==a*-|-l8XUeR*!4W%wCWg9_xRR! zE`#M{I?sb*z)oU7+i^2>->sq{QNY#a?^uy;{Awaci;XW=_I>JTl2E;*VMK{@QtA(fiqxKBnl2um%~9F!x^lT@zL($S^F_B; z+-?8%d=-gE;4mD~vtrST4m4+Ln9nz4ICe_c4k9q?4!&;pFX$xkDe<~17QlF%_9~3! zt%9+0QQGQG@ zNB6K&3Br1x=enVo^gR%T$85MvBAz8X2b6j5JOJb6Wah{{T_{0Y&FaHkZ5`$DqfZD9 zMpp`})*mZ=o!!%IIMo#k`T}nc)LIN4`P9V(t?@&a0}GGL9l<-ym3rBJaZ1$0uE@RR z9_p;tQo5xK21PT&$*Ou|F*E?B`96;|YH7jaBmN8Yqt5t8^5%eCXx+u3*N_CAn>+{W z?(&+zj%R|0?JeF7E~g({;JKW)LfYaKpVB35jyJvT!1A-QmD}ejXA(l8Zy|M4CWM)Q z0#g42c21$^ZiTx;xf0g>ApL9SvR9~W_ZMS2uib2Oozz-Pb+ieoXthN?Z(Q#(RS|p- z2bKDSZI8S*90{W9($fBi`h7x+wnZMWU9rh(of=HvfxVCoC}O-`ryPxKF*&yt8Ex66 z-^YD(^Qrvql+FG#8Q~gNHBO|~$$OC#0IW1Asm#{^F+#mIo$pgG@YJ0ZkA*y5!1Q7Q zOIRENJ22>$KBIj~0we&k${RbPAFi6ESNvrJFV_Bvs{7+{t2hurEa{rZ1qwekf`?b) z6*GdNr;CPu$nZO53CY^cEnP317qsO`iMqeA)VDHlJe??rsb(uOww*Rt(2X{DS!uGp zcXPfc@PowQ-pt86vCD7>_0&{}oP(@Lv--VMkG4>ax}+H)$n^DWv%JpuOS21L%bgLX zd+}i#75%Pco?dDbJK1yhd%yCki)?=^BUw>0|8N+4CAOaM1c{!7)!_Cc0vbsadxrmc zcCKvtW}&iCiC}~Nkj3eMkk@qSO|J6D<94AZ95*!yT+vUDm&cox#6Nu2ez{s##OH_3 z${GBA+zM9_#xhM^doop7p*zL@YpH$ZknccrU?|hoMbfPW9tOBs+e*@3b%6GynskQh z{jqU;uF!}-T9fCi09wIt3dM4R!>Nw*d`h#kKZ{t+F;Fer9-~X`r1t3ye&FGgNx;2okOd4Xg5-3E~_ zvr<90EVt;sR?~ej9CyBLX+Ut>vRa{$59r<${4imzgEu<{*6((QXeBJE6?K`#_Z;6k zsmkuVbL=P;%cZa&6?1$0`ol?OeZa{YDo|p3jyZkF!B#b0TCZ4}S8ltr2kPI}yiQYl zV@6R#3=TcpUK-w!3X`)+Rr=$d5#yQSZ4}Mt6=Lze?~24KpGh^-UM{SoOXpKjDm4*Q za64`H9QVDLkDmkim57)6pf;bX$$!QhKKK>4HCNzJyL$%3DQACo8ebrv4A5wGzC6?R zk`B~)n&$@^%uU4_&P6rXKPM-bIOvP^C4p(Yd2N!t7 z-zCu=;|tC4H+KvyydV<~dvzyz)^l``vQ`4-{qjabi5!Pg%R5R1Pp?iB?e2F8ci4S> z`He*`ynh7v_S*v1q-C@%q*g=b?D9>6^>Gyzc6%s67ioxhc_}gfm6D5KAkm!kf`lL+ zhgQn|@RjX`c|M4nOL z5Jkf0LFZh;1pU=cCW6DyLU7gu3*A?hPMNrAsHOEFIBZNW417vZl=))0KFCuoPL!zV zM3ms4>f1jaEn))2*Leu@lYeEM76h@k_P3VU*=tYQyxN}rlT_?qFYAT=(9sQ8?ppmb zi0zYm*={iY)_(e?!uTUemh>?{F=ZIiKgtaL#aTn)05pfT8$-$dd7qcZNd%FZI=%W&KZ`rfBhvFATfPx`E&o@E9?JQdWdZgL86TcO#?;QP@zq@i^Y04ABHP38T~rr{>Os{|J~;X zk8$A`GolS{oYk6<6wk5k@>R#9Flsi&3DZvx4hz)HmlvyY{nSw0@+gtMFznUo|WL`M*Jj0dSoJQjTg3-(?;v~R$N6sH7ANu5Pm*@e9*S7`8L0*Ef+_oQeO(X%~n|RbpV$DBeH4y zFkQ&zuN;8^a0=@eHu12X3X6ef!gvnULzule}U*CpCT>l>3&1u4YGt4Yc6(S~4w~kt&Va0Kf%|xc%$AVR^?6;)eG_{d% z*haS{@VR8IhFtu47UT9*c(y`Sj*Oj|a)5XZyTX!BM0c_L^AX)30#1i-*R%HE zP|YqZemAEeV!i~8D72!R@jTC5(E`+VGyYfBaNwHev%;Rh|NABX&$V}e<0bUVaTM&~ z26pvtoq@Qdgu8@_T<_f7eod=E1Dx!U<#&41Bu-$c_0LijvfBI$g$uE0l)uCM=&Z04qHeh(rlWad#2*hm@@pumsNabFiV zaiE>Q(;r_BW_;@>7df97nMc#9$mN&|nd*Zcm{ETUzdMa6#z;DB_iZRr)t{k4+rOpZ zsf6*=-mRdjl@O$;K&u#4aH}nJre&`7`sECx>H72W{7cR%-IC1`*Hl>5sRQ-^{!~uV zO!>3|PqgJ?Z7j}>Wv%dKruCz3yWF>eaa1KhI5c~-A$7|IJPEjZ%%KaH<_1f{hju`~ zP#gOf8NHA>)H3owDg|Lsu!Q0*h%-8}AA}(t5olo;6ReV^%xo; zWBXg1^nV1mzb+u~OR+B`xga|&q(^5s4twMG_(T_~(So?PNC@=zYgqzuv_DW0NZ_AQ ze!S6iqQ_ma%euWj&CZs@=QhVwrEU8PH0xz;b${LR7VO6W-=sC46Ix~EEp%#Vx0kNu z7$2R~+9V}R(8>Xs|0(l8ym`CR;>-uFFn+IqnX`* z*k0DPt{U4uNOx=!Ai^&1q;Z;3j)igWHxK36^sjiGbB*P4elQRvxVlYC#1v-#$n7_>r)zzFE`Y8A0*_aHl6Grudx>X5Y4o7 zHNum?a#OW&wa792do1U7dyl*w7&WCILKn>~FGizM26uUR8SetW^9EDwrs3d4Td8e0 z2taa``3iJhZ>*PJ(W{uak+XR@tyBtK+MJBtr0S>IZ+qI}mVb^Hc5YLPh>vZAUS!uIhznkC80ADhJ5L2d)rx9b!yVFPS3L$ zc(Bx-2bhHD!;A`(N^?zj%tdLpdsKq)UsdMsK0UZLrdxUggSx7YuLwjTP)U;5zO zC_-dJAq{bO1Po&pD32^N^MYMdeIO9bj>zF3W4J|&hd{U%b8>CugVraBjB`LABw>Tlw$#Z?So8uRn$j!vT zsfQylkSOU!xZX|{<#CHJ3caUiQR3c_#ubR+FIM@LM)>rv^}od6g;(y8?d>1lvj>R% zw1(Pp1m|49x{pkla#G7>2C#u%X?WX-un(`Wl zJ}G=_3Q1!z8C|Sf9&=p)^qo?mXo3&h?l4Ig?eA+Fb+RR7Z66h^Qj>l9t@~zAx+zS2 zUx;r|bd0GaE;Bqu09JCOc#x=ZMtcU`$g(_3MD+(4xp?NQ#(cTxlfa+(ZF)1{s8eHT zdyijb@r^waAGYPk$^7H2wE1Q=LzAhh%CwKaN-@OPOs2mW4BW|@8^jBg+*^K#d+C*C zu~mV`W^}+L9A8d^qtcJP93b=*88?9&Q%o62xP}#({HM=T{XTcGuJBZ*5CPXoyC59) z1kkBBohrQ|MH(sP5T-ckj3mO=k!>|>bkWQhJh_0ut z@WpE#$1fhNTYMGbJs7^H2M7={kss8uWIR8&CkmA8gq;R!+&7BQ9YxZ84p(Hq!W|OM z&S3L89Rw617HdK}E?&#OdNAXta_CFr?09_%EFWVcmdA2J@Tm4zB%wX z-R*(oB7N^MzXT1;C4#rp5l`Cf zXKdFg&X|5soQWK4;Fu1f&3AslO*=&~o2wbAX0v*$)rjYR)SX=YL))Wq^u6Cy&009h z70J)qJgSlx#Q&ZJz^V;5l_(r&HIp0Bmg~{@CTU_Ulz@}k@{a5Z^!{zHaKTWIDWDDn z?QNMJIeqW`uS07Q!q=H2zEiW+i*FOSO~b0p+!NJ&mI5HGl;(3dOC3VRPKh)1t_T$G zBd66v-2bWv5HY;|v_GaqyW@MR#U8Ep;$+^w`%4-Si9_R!= z3o!^_pR>Z^wi6S}C@Jm+uI=W{*y z4BP_0!|CUYfv}(~A5i1eYLkwp=2Nw)>M#7+jb}?z(1ZG;G`T9Q;m`L!SnD7lhV#K% zU^DBC>QdKe#P&Q3d%Q4dy$&hT?9#S{ZJwC{IR>xQM_+}MAblPJcKUM(0tAj|av^y~k?hX49v z>G31*DA!Z7GqY2(e~3$K$sXs40~qD#XH}5qO%t@l3{7AX;@ewhmLD^;W|8q)pP*Kp z`Emb9i-@*j?R;lOe8R*{TX{0}bbGWLBCM}cf0k_2GrHz?1!!owvz-Wd)8;y}9P8h5%79zXfSX--rGcnnmpEs<0pbp*RyB=8-Hk87|N`$xMVs2F}S@0JZ4G7 zKz(!a_)rFs+y$O2#E8lVg6GS$9Dy!&;zS$rx%3%p$%jM^%Z#k%q9}!dM7Q_cW%`qe zz<7g$+u(LOs$B?xss<{Z9xjhIJivG|sZ%s#2Z^)MjMAtDH2y4SpP?xqxlZ>dMn-KB zg5};g5Kuow+%eak?`|69@xk}#pbN2bECgm7(PlaoiYeVD93a#zUo7AMW@dOA!L93J z@+;kI58^WiM;Y?D7)Mx4>Q%XsIFW#R-T1hmdPYJHq>|y)aXweNMe034En)Eh zinh;`jLyryr3TOfzp!ez$HB+v>Qy;mh<{#2bOiCxN*Q#;uC}omB#Amt*LPgMUm=rU zgpe5Eg&7a-;GG!Hu#}liDl#ikx{a+~r&bI|RP4X)=)JehpQFe!G$JAzZ57dBLbg-qlU-^E8Ve^?;$nawq3q z%BL91OIs>>)jHL6a?zl79YI(>eyXqxgYnY8mteXsxM+8cV>#lk5KX$JYHmkm`i74` zZ_Ueh2aLO1v3c0H)*|U_dsix9Lkq;uy7M zAyF&#AkS(|@J0VsUy zU8!*QQ)zCyU1pyYUU!-)0S6HhZ>R6!=AA!Nv$}nb6+>$0la$ei3zfd)u+>}P)6va1 zzI^L5SL=@hcpfpPXm_}+I(9#Pc4HA%c|w$^MP1o2#f!HY>Nl64bB$n zBOxr1`fC?j0W`qv{piT5zQ6%#x82SH5q^y&g2Ko67<|17RI0Q}l-)Uj`*|@?8JjCp zy0U?;ze)c28s`J4XA;C8Gz!a9Xk~?}6+)M2uu)@|a?EX#&otH!)WYE}}FFWw~u7bQU{2Mj_7y zTOS8llZQ6HCwxQwbSQ-{XYdz7Pb5&*ye~%oP>H1vgkUVGhF)BX^(^z-Rf9s3`g%*q_`2&JVpn=qDfy zcc(WILs5V(&`RDl@RP#`rGjbfMvh=9%}%GCX<2eDFUn)a8x+M({4|3pEf?y3j`Uu3 z!rF_>Y8JPrirZtpuQPTuPep?v5{0k-V(b13wt?={lKtZw#{j?yCWV<&h2?6Iy;c}J z-y5hoxY>;qZ9gjWb)M*? z`noU*>$Reo4Mz>9$#jd=^QfGUj))2)e^v}FBsmkEU~L^6N(i70&g zFGPjZCGgBu9#@-U`l8H31D~60X;-Z6>*E=2+jY8$n{?D)P3~0RVqPuiNs8KUxd{&V za3Yl(2EFCUc=T8LYoM?Kj#hkjhPQUV124Y#tCioOsg_$r5!TArXR{==&l%6pmUMsZ zz)9kTm;q3N`^E-CqtQWlaBQxbo}#oA=?-W|AkSbw%nYd*zJ1R|nFf3{je-IwBE4Qv6^?yh8e^xYfCP@adc#Ygiw)`r28wCjXRcDP_60Ik zcGhP(`o0%SOawcPKJvs6mh8i7dwu>)flsm`VCbRo*6M!u(7py@^Eb^@s^d0YAF7k# z7k|e|EO}Eb1u=bv#dSaoKJNvPIfaw}29SuEMv|EID?d$~Fxh8jk$Uq)J6WGj3R6&E zaT|IBK}JRniYt*q=Kw7zJ2-zy1U0IuQ$$^}IyrcB=)d{pfL2w&@)tM(DCtOv|@ajlX;Zf7;SwmZ{NW$>8TLnxL8xza zz>bR99K2#$m_9ZJS;?Kr?TqaU;~gKovTpfSF(87vUufGrT)AIW-`QfPb zfx0$uJLrn(>dR$!!3BuFgh8#EkN14eLUaK#*H#rvkptRBnR;fSNl6OeIo#cz%$2^ zfTQvaVQk;e1_~#6+>vZ^1l1}x-!>QJZwEb86dfc*m_Vpo`n&#cU&p~T6c}*na8h2+ zI_{*SkXMgoe@q91L}d)39KZQ3dI)Aj^HB~sU+gs)G-R4u39nws6qh!g;FN@P?bPp!G9Kwrf z?pJ+B*xM(zhU*bzqH+)Xe-P$%@|V{6P7^H@0p=glhCw8ZVZ4U3?1mi^@l0PgtPBf* z_dp$~GQCuh&k0Qa@wi`MRISo!#KxH`JAk!e21g08H14M(8X#+nywlW0s%R{s1w$zY4*(@N&R-kN?odEPQ7XOQ-qH7a5x^+L#BVShJZcs)_qi+=W-hqpvD9 z_IGFP{C0cfbAI35Ub7@I`k#an^SxQ?#ap^;AC{SMKG}?T9(%MMr0_tWe^2=Gv;2|} zKjYtBqXi6HZiiQIK_p0LN)k&zQ_0DiGSE=kG$dU)!(e} zLwI!Xn`0S`OPIgr2OR!2CdKVUPep63yzJB6Sft&_#p?tX_Y}J8d`%P@b*ADpPq5(& ztz{;+z@zFS;%nd(4aE>mgqDDcziYfvy2bM3-*%A3WG10g+z2jNp?vj2jT-c}7M+dS zgM5gJQ*;2J3=c*lden)`u1UU9f7KSkg_y-+QU0xj$te{P4jBEr2A2aE6vl>o3c`*1 zgN}(|h_uiEO8tD9u~wo}-DI1cKg??#R2Cg$ekWEVS{sE9r(A?*#g}p6_X^xrgcLq< z?;312p5w?MP2uANy7)xEFXoe!f%W2gwv%DP-Zb2`_Pp3~@aG?~QzoJ_HmM_rD^%lT zK>FM2&1N~{r&y?(5gz-ty`)I47UQ9}EK_AUB<1~9xEKqMR@=w3nqj=ioVGH)zxXdk zo!W9Po5KDa%}Ux0koh`A>uksVd2%IbF^e_U-bd?<={T|vh46}{=_Y8{2r(VD$h=T% zki?V3l^+MH)z>ugRbK(p6Gz?6sq6aAls^b;}Zje88xm(mwtP<(s~#->%9tlP|3 z5>$@{O%Ui^I}{Sg0{2ec{M5YFMO=^F<;mVcSmZ0I&EAr- zfrtz$<1I9S9$woWAUE_bS=NGNXVfE3we|p)g~_|2I8vfY(+Qa{{kseO9vYoCJ}OpD zC18BBVk#E>Whl72=!!ZTxn>$59A;aYj^`Z=K_oz8I4)QqiXTH`eu zrmHwE-_Ka|Cn6knw!m}i@XV~R=o$H&Kj)Mw`cEFy;ly)MEG^Kgq%%$AtGu5C{`T<_ zk_SV+;=lq@`>CL??7A>Sl*tB2g+_e+v;Nk?=R@>(50SjV*-l#!SC&snc8l4*#ADi& zAvvQqCv5B5OJ7GMLzA~!Cif@1YLK3FWIK=dItqmht_N!&{qrWuYg7IPdfjJ4l@C~f&&<@ z{qgqdMD9b#48J?V@Xr|m{Aa8N-EYBp;W=!^A)f81pvv_gzdj`tqj|;LN-CoN?b)p!bCfJYvtd)(6;8Bv&VI<7wS{_WUk7jlBut$t< zcDk!5L~l=He)ea_l;7#`gB2I`QEQ+uf!@&i%-q@z%!`lD>dNAiKoBl-dOyPH%4!}f z)QDHyVeI*mAW_>qKa+Mlkgyw%#r)xA{HL$w5h+Xm%FX#ArVHJj^|B1A**C2UJ9hI+ z+Z?*4=0=&KPZvRwY*N{pjd>++Nrbw3_2mSzxTdV6Jc| z*{n%q49paf?}30j7ho`=&JrN#FH=<)`rh-;Snr`3VqkLq%2lJH063|dh zZWKbss}6`+tqTOo0j&&?_cx~X-Z_Zoq$!BxDZI`?Bu_DL^w)|ds4X?GtI;=ZxWZjd z_j2gFO7tNg{GOAH3>`n=m8l^Mxd7)nY$jR~5Oj_>Op}W=I2{u5x)_~;6C5%{0x{l) zL)<(r3T4oHu{o=@ zoF{R%Bjm#tRC3{iv$(MGI&Whnn~y$leF3>isYo+NJ7eK?(Ck<580aw>$N7ZZfGw()~;hPNnCRrB#AD{YWzFs|Km=&T)Mg#7J>YK?7ekV6=>Ht zJO+XwrKEs#r!kIvmJv_ACVvLEXmEKL{%rVzJLmfMK1}J$X(eeiZQ{qm_T1T}v+PY2&5nD| z42I%|UafaD(|jNjNCZ`rhP(xb>DG!q80~w&{xlEhx4Ff(s=aa z9mJ<+(jT7NjH*f?uZv@e=Um?i&(znhK06_^@29F5J}lO6PgH2M{#<_4x}B2bMP9Tuu`axj*>OcwO} zD6(}P)j4fYna>=N-=+rAF~76P1#yygXBuUo4?-iHuXTOwij&kR-@$F|4^1A*v!@*| zyHEoHf0S;?<0LTnj-pXIQ#!^QaP=g=_?^N?BVZPN04%OpXKkIVcUhED`O*AV-{X*; z@z4o~clTD~gCUO##k)4T^p9p;5XS@zG9?n?`_p%+f(7k>7x)Ook%FN@3fZAK`q&D6`5H1pA>Xt- z>uBFCyc8#sdP!UEFHL*^n)2y`T31Ss7@0f1e7d}6FJ`_bwsekI|?$dCBc+$JB3B$)vlW zo4}(NtAt)l9O86wM0vbBGOzscRZ6akjHk(Ddi)~tIqtZN_deWn!)+&9+de2L8h#ng zi=r?J+m1b^_<`kQ@)8gU8v*4z{nF}o*dKiny(*LIP&Bl-HG2ckmiK$>U#CCn&Y_sS zv8@AiwJHSgrq0MT7#95BL|qQ7052x4yrk;Pq%rR@>P7`G3_34ydKx4 zUE}!HuaSw#@ni`kE;Z%#ruITut*__+OHu^)MLXSUZ$wN2Yravg1DGb|@3=dY0cb$$ zcku*_47z$1{N#6{%qlnS{X`f1_v>P{oeD1L1lyd>R$A_2qqPO{{g(FhpHiLQ?r+24 z*6jyAb@yy9p2}G*pI-TZoA>&{F6;x+U|XQ^y#U!=nc(i?Z9;Eup^sqlk$gyC#2fGZ zr>)bUV-uLo#X!u#Mza+>WcvARZ>}-uO)m3}>hVp3p?v~_N1<7Kv#wkK!z0YWmEs)x=s7*IpmPr<0TmE2cQ z4&TqZvkB;B^P4PNxoU^X{?A`Hyb;lQ;m81zsV&cGKHIfHh@Ppz6e|FZDt_d zqF7~STr}~j-g4gKDUZz~JT9ltgcT3i2IC0txyx_rZ4T#UJknTV`0bAvhp)x|w}22` zWaK1umM291G}vb9b=p_ZQT&aw9#8#%QsN6){Y6^B+@N`fR0ij&?an11?Q3(N7ry4M zN=~}yyZl?-&4{dULnzHRrBcZ5X=9~E-tSg<)53!>%dTdR>QMr&s;mpr@LfG~71Nkw zD3y|?95$%~mKfk@3K__eqCSEFjsDfwpy5`%W~EW?N3pP7i|}CCX{M%hW6OnQb$Ux( z75T9Cwl|GNlPMYzUFXPpUHrVH;|Wr=#XJCrbl5E}q5JT8H)?*Q@D+Fi#-e`a%IdqM zA=+8t6~(W&96D)V)GZt~FO9tx=*@X&kp~webRt=pTEsi@XZlMEBRrynnWJx zBwjcl&sWCKU2Vlv@Z%JM+U1ehaP$;il{SIZ;aA#o*e~p*dI|?CJstS2#7?giw+Nkz zxttL=6w7oM!li^?1ql!*-etYZ<$0Y%BpA3JQ#oI2tAdqMJY1Amo#{nkKE)hOBxI8~ zxf5IxT)iiqdM#2+t5%lTuFak<_^@uv_!3+82NW*_b$!D8E%SAmR|4YLEAH=>-hd|c z1uO;6GRgsjlMO=JyPT{T^dDPiWdaGoG(6M&N9d|L#hzeP1GndQ@3!F22EpKq#;C#GPI*a~n@K~KaR_v0T`^F73{h}%4Y01a>uh|p4TX%PR(FoD@c za7aU_shHA|+$K*2uzZF2g9lU6Nr`5Bsz=%wV;Z?hIu8lGEStcV|l{T&8vf&n-DPew$8jBa0Q{hKetN;V6Ip+axGw$pU1w%p;dQ19~r{Pl0I+5?=v zTKE5>V0Z|v*4v2H8&5HIuGj8p)n0~ZH+n38;X?fskg@VTL;m`x^cH3rOtem@bw4_vo!+9T=McIZ4XsK8U2uQUa zKOP<)p4A$rw5K0RsvV-?#5vuao9T1=b`zNlw!42zI-Ojjr(dgI`_Jwfl$5*oiQ5z) zuD5%&{=RwT@9Sya@@2xKgaj&jJPZ3@{P1sg7b*D|h`8))+5YEO2CpZW|66OI=<3?y z|9FhsH~;tG|0JgWPe@!&ZQ*lJpIq&E1>WDb1$n`tb|=%?`*L;73cv~1M5W>W?FYa= z;e_An3Nr8|{e2k_-xC6??@N9=!TW6%^U4(TBzy%2L<9>45mjq@dnNd=Z&o+!-u~vf zqY%S8e*N&hB4t$KrtSYm>3_TX^@(mL+*T+D_ut?1?`wf>Pus!>ZWImEs2$p`XaD%Wrzt16-V zs~-QglkDG%_}{kdU-kG`J$~3uf(DqA)OvaeM=gk_^jwTYbxNRTORy|Aqwvw2NU{x6 zd3Fi@JavZnl>ro9#na&a;BlQ=g0)5VJg^$vN_y@dEr$Jno&54Xbc zd#*;v_1BIIst5$FPCc~{#L&LBp{Aa#KCT?{|68QW_XY+|*jM@e)-OJ^<>2m)2RG4l z*nAL5z|!QCp3?yv;qG$&%lEZ8;eA(3T>^GE=*-!vjK^Y#2T- zon>Q;%xf?peQMg8`>$sgOur3k+to zbB#jJxIK3#5W~a9u#z|RT#sK#R;xyM_vRsuuBUy?<0XBxJ6RsvP zl%EUie-?35DQl1!#I^p`ua>7>9`>AB+tWg|TKzGp_{y=pCJN782?!lT*?fv)_G*36 z{V}h{C>${d%UrSU-kkfvarJyp0?XF6_&~j7!}mI7Gg+Cb>PyW?5-~HLo(PFM-l%kH z6oNkl<_1Df-=Rk^h%bLU^TSAZ<&w$jjXtZjTDHz)<`gKaVQjvfjyTwU&!b3N@WnLX z9CK`LMq&U!9lAN^G#?Y%hvRZk?KP=zv=2>{yViqMRW$A6u#Ss`lePxSoy}5XQ&q-! z1Mu&s6+2&kc$*+bC{kQ4iM!et6JxAE9^acj^^%Y8?W1#>xRBHZXI@3VrSb30q8r1c z8S0M24UPASiIS3FiGBpP+91Zg~hEAxG{JuhOj+IwEck2ZtDd?r!Ck9wk|*-2yeqGwt5%-? zMw26~c=io8jrdX~*Kc-|O8LIl-8nuWHGoAy`e_33LGHAucaPuphd%$je*`9QzD58b z-&iPLsmqA>`cs<5uzl}yax@)yVJ@CwmAkvU4kj7yFZ)OBNgOVQj?xt{>BK+Ph3?2q zpDeHTQc*rtF2}2%k}DUMq&aLVP>7KKMg^D{O5*26T^J?Pw)+c&YFAzIBlZS;4H>j+ zvYMl{J147k%)1@%rhQ zRO+oUovF1QSH>U~w%eF13I>*(@A}#`*leOk%wczi^x+fI_jjNdqSsfJTkdw_H?F6< z8xr2QFYHtSMTPeJQs>ws#@@?4m1sxmXvq4PjOi4E?V3Xxx%4>P&s=Qg7aCtn<|(T8 zW+I6E5PCkQ`K*GCvy3P8_$z)F_~$p(b{oUu%Q8=~1G0w{)HSLsrs+h&pGEluAO$fh z2-n)K4R?tgZ|zhc#1~uJ@6UVQ^h9R$=>yi9&B+W$t<|D8iBzN_qrN0P%)uI@&fZka z|7b%?>#3RA1|xb>)4h2&Zt=~pc{>MF#j`HGz^X{Cxg2lP?MzobkHLn0HRiw~(FG>s zfC-hvHdkj4IqcR0ueCh4imI81k|LQz94NIL;s7?`t5d}W6UjWsC5~o|lN<(}W}zoN zy>>$;uSRIr(@$>a2Z1Ic4$WpKkcpF77-B}FUYfpGdI*5$_mwVptxlF3x!}J;rzP5S zU55-DL(SL>VgFPt$@{<$KO|=R#g^VFc<8Ib(8hz7CP`k{M6s-_W3_Y~qbq2|B!q<+ zjzL}8PRss@J$lNVv)hjw*1YS4Q;Z4{WWQ5YcIzygOnqd4^X+Bkt=q~ z8^(O9YMdW^uskOhCok(+woEb&r9w8t?D#BHK2wx%*7b;WY#@mv%53VRaItnH84N-q z1gs48H;}-L-zyC637Op8>xP_=G$?_GGALy<7&T z@9nkw%v@LQ+F3lAmSGo>TA5Q58pZqhJWcf6k6pe&QBrH-rt>emehbS-Q8wqb{Z^RE z*Li}+DK%to&tSeuLa9?+IFk3?ZEaNQcG`Sx8L6rnrfk6e4&a40hc#wSXy9KeQ{sQB)Jy< z1wTXE&76m`O%0^)q?XE!whJXFBKLzw{@VC_??vsmJZPxtXxY=e1Y;)2OmPb|4tHg7 zh*-kessmMci1$8{@Myl8mU6K=-nNA8v8l&#fk&ku8CF``BNme}`-E2n6w`UlQfMp) ze$a25r1m@NEc$a-ekWr`&=20I_#Uc4u{3Jm>_YXt;GM2&uaLz~z9m*E6nmpm36|My z*l6JCbtUTh!V58*&xtFSXzOV{+s=Vk=}%>o0Bbt+@-L^OjfZpgep67Bg%t`$i=8ab zc0~`PP`P&J@L2NQsIuQ2jVuvHbmUwP$SX_q`Dk((mV9#``^x(G?B%^nu|q?z^3Pan z0td;i2P;9Nru(Hl628`{3p{|}O-$_XY5eq_3UIv8!k}j<4>vui`YYbFYI4s!QRE&Z z{Ncgje5FAQw|-Ug^r!rPNS%fXMUx?2H}<~G>enZ=ZkItK{ByoUqloT=Sl?GhtCu|8 zV?>||F|V`pDNC7{$G2p3u5;XY^(&@LpTyA91yy>^nAbigjk$)IO?7nCa*7UcWN1rd zEm-ALtIEQ|8KtVfXq+9kHpe#P-!sj-tnRXkIRW2_ZyDi7cYNIK%B}eIJJh5*Iw&xnV9Fj|!t|9oxt4Ls> zUgiJ_3j1_--1GStjdr_}8Ho*t(v;9L0J;_jX7}P6j6%tLl|k0IW0rdF@-*ft3r{2f zR`#^|z-A>@J@VVEhJF=vZRIgr*VT}drO!M3HbCqLkMUUm7a)`(g%LM{s1WjRsA^=h z4q&Hjuqh3o{-G8|rV|au$@=|qFD*r6PZgR+>DAJGPiAJ8_V5XYQh7&=X7=?dLkG27 zyOTH$&D@nZ0gfhmFnLPiX#I=O07a>8D^ZSt+~@(a2{xSG<$i{`^l~mPnEgWJe6SKR z?P#%eD%Z!wZV{IDTi4-9mx+G}h|MQ4Id-V$y{F>PhGWNbRZG1oSC$mjsNo8#Zr618 zMi;zs@qLPe9xK-xnlqHr6HBX+B{D>x)JFD+C8sl$xlC(o$MH4@kk3?IxIr>w`{FP< zOk;8$#qS5dK5xqs8}^EjMVh(-TRdbyi-F(IAc6T@)n>Jy5-ih;T_hIfI2NE4E4P%{ zmk7ifTKdz*wYY*HbuQ5w=C2vuf8tYumoUVg%sq4lHsoJoyb(lvNzl?Pwh>wbMW(f{ z4`!oE1S{e!MQ8YJ&6L1wB+F^X8M!`V{q@UQz0wUQWxxFFG+iEipkb%NF9KTUv{N_4AK4SN+c9hi---D~C=IAcdL$NbKnd*zY_|B1VqnnRS) zH5>Q$=8DSgHYeunpnwycDIa5!9y`mxddzs)(xmm6)4{B)}l ztJ&pclkT;d^G@Zs*|E`J0`Y7eC;ckpQQyl0<0zRUmzT4a7Zp8`08%my4Z)M~MrAP_ zi`wDrr!N~X(IA~HGi0&I@EjbEMXYt%NhsPr9@nX^+}WPAl`pGsK1V(Fb{l(_C7tFg zm(d(sIuF&Y51+zj|4>r#=9$}>@R-ueQ0>Oc7w*WT9F7`2k))Z~82;zE>Pm8p*q5|4 z(;l}GVTDr=bSEp}q~A?_zs19rrCeZ|wJ384liPf(0XhhMVO{nJi@n{Uv9x@3?>LfB zz-3wXv_P}6E?13lo9z-M3|zOTLk1EUVjvkdgY3-K%jCPMesVC|&eiqJ|4T^#WQU;p z)fH3!GY$C>$hT0_p#YOcUwLA>_O*63l>NCKjN@Y9dw-%)sf^bQ{FR*ArK_6)^Kim} zPLD(O`(mZO7HJuOoa7;wj3c=R>uJoX%n62}L@o*p(7SLW3ZGqGN?e3^F^NpfA071& zXY+YmTYP?>#^`Y+xGZ~fn-^VEyV@^ol2#VH_k$wNz+hKd&g#3=nrV*InY*f$>Bn2= zdgiwTzKW5^lRIl`*J+bI5t53U~d2F!n!zWX8!Ru88uzQ~k zmjMy=j%=ZW;E!EL+sUK46I&IU)0-Nj{R=!eVx1p{ype4# zc4KkzUCt_dy-H>Lb%u*m5X{6j7!^G%Lr8f*Y%$kBdOkNb;_{Ooi7M?M;rL`<8SW~-9ck#9Hd|LTN67(@_@$OnplHbPbot7xwb~kfl zKP0?*c5M?*$~dI~EU;3Uu2G=X2s?d!N(Up|4x3jMwhOgqoHS^Gt~T@y;g%EI=~ zgg)Nxnkihhq+q6Hl}oYq3a3ALNN*ymdF%z^JxB;cFaMJec9)|##az{%8l^y<9Z0Da zdI-Do)%%gMM<>WOV>jVAEbk+T{ijsQcM1%!=1Pvzc2swASK&s>?wi=!^H$OXCd9YS zeiLI@`jR1X@SQx>8I4YM-tR@FsaS#X0IAkgMO9ao$%u3;ojZrmyB%LlP6%DnNqSXn zeuCfY=@Yy%qamK1)W$M{Emm8YfQ-3D7t#8mdp_)oUrr4AuA{*Qtx01tm;l2#B<|lu zFA+sozTvUiGP_M8jgAMe2}3+8Nl&G?R8tF2jT&O5xP1EZtEz!cG)QvURD@JK$$@rZzizD_D zv4kPsh`699HC!d|)LDHbQdc(h-1rgX;0!`9C#aRzUK_+gH0JHN)2Anio#cLM-_Y{y6ej%xOR+gyI(M7ma6rd z0h8iH>sYp-l+)2V?})_8_X#!ap-}GS zxj1l9t344-OP-F^Q}*?f^cmJWgXVe4d9i(U-)#(I&_eTTxs1>{gRvFJV$NIGLym@2 zNU_p9YE#EvVIW;jVmA080WWIuDea!?G3G&-`Pp?qszH1Am+YlqW58GA5%d%#`V6Va$BCWE4n|r&7P3R$ELGY>Z?@m2|pM&%0eFZ#1Yg3ew^|js;UH zwqwr`FcU1)s`@z(u3gck3{GHo`58OQ&|XcR$Rt+12Saoxc(os#>`~);&a_l)_tqWb z9IZ-hQ~R@GeP0x*OlqT<4~43mjM=4d2o0dvtna^aPJ{A#E~jpLc-)qP8pZAtZ;SZ5 z|FDcLryyB9n~VEQ^y8Ty=@Uxe-Me!Sh!r7b5rh{)(blXM`Vnl)L4NyTisOb#KjojC>v_7IaM5(#f$&cyj)WxwxKTmBA}Xe6Zs(sF5) zjGiI9hF2AnQ#S)P+uYR+8$V767O3lD^S+9N>XBH^ah2(RcgrEw(d53V?s<~ARF8hN z^-wqti{ob_!VQE0zC(x)5&3^g|BwIk$|XRF)D=`c=^F=9x4b?*G3_%c9OKpDa^~Q6 z?~fiMap;858-falK*~%LHPs_jP9?^mD9Ysap;V36WYQ=!5ec+Qmyzfz$8n|JfMkk( zYp`ixN3x}nsvdqJNkF66uL9i}fs(C(;47&_Rtc#8w=A@$EQRzL!bnWq)jBsX8I2Fn z6ykNN%+j?#8}-MvDqe53_b}=%peV$<5H`I&e=J8o61sB{igU1$GhndS1Qm|BJ|E9t zjbt)f2;TkpNH{mq^GkhzVv)RBB)JTkMzuMFP{6Ar;tik5sZO3CL()<9B8Y zyW>q3O4XX0+mKE-5I!(>XR6Xv{=@t8hNqSW(Uc0pMZyc&chO=BlpWy{uq0TxTu&qq zR;U-yw%0)+%WikHwI=kM!)TXlVmsA+vXnPGC3sAy zhC!GN>`|%h8r^L_#hP>4=r;IvtsYE|rIt%9a53pe-kvrn5MXHQ>_YmH87)MCNZQRt z^$psOXMX0?f-pat45G#+{a9c0r}tlj*2rfryWNdt#+&}{DD&ycWW0G%ll1N50bPC| zbD!ff8rt0f`934`v8DEk>(dZfi5Ev3oGk`XiW7tyRfUWoj)h+BOjl=_ou4Kda>&wq zNkFJb&kt53K)a_ey~C5ev7b(}<^zp7!}v+kM|b67BpP8qQ$m3Lq0rcljRzwfJgr}?qWYK`d{t6ZvyZ6#VDmC9nIqc~*PXnvx> zAo%*VcFeTpA7R-9X6>xyRAEe^X64kX^Vlw!hTaRn=lb(a?$XO9n#`8Fl9bwoxz<>Q z=9Y8mp;xu9vv!&~!{9yi2b083c6bSJ*sjgd5_tr0LiSHjAtqBcPs8ruFB76uMMnXj z+#N$r@1xyWi!qSc+j7S}RDclcRfg`*I_ka{h(35YXqe%D#3MhiTe>&jfSl{fRcKel z@aUtSrQWOErt&0TayX;C`6z8pRu}m(gXBk+B<~}H=B=IS7!lmLvC_0Jl)o6#Syks@ zE`vbhHD{yYzzgFmW2Wg+a?VYmn_*G}sd8lBTd$5cn9RE;#-zV#`9!F(pS5ZqUih|j z{*=|^HCN}d%rTKxqbwUMiynWdy1fD5_6tXdq=tFDU7)k6-WIhQ$6nj|T0}b^f^C4i znfhw%WP{02d`R0%A~o*WLaSGXfM}B~xpYc&+3MWkf-!wT?%rh?X)uZDSDGq*Z&X%z zho8|_DjMirM1A7V`1#Ba8&5z5_ejG^9mA|1gHozUi_7mQKY~L(1ursy$L(73g_$<> zCKE{_Jzd(Xqfg^LsQJl04?HQC$t4*R%r5M}eU9pjEqM(cIdkI_l~z1?KdA?PIK-cLv7x>O|>^v1lC`2&?&w0WRfuqkv)dcUMketZ7n+Z z!(6)NL-(35g-yPmb(gB{&NWi+OgYAakb^VXR_Oyje1-@TB<}e=h>o>Vms0#iN`97# z#Z1k{X2o>b#qnl$H|i%%9(tOoVncJ;zG}&9^ZaSn+$TCn*c9%Uh|FUTgLQrD7D3rj zG&t6rt4yx%vt;~1L8c63a1_HEl?>_6TrBmr(_<^Z@AIp)^5M359d#0}ofza3IBT`E zdlIihMV+gvk(FKr64qD0OL$I1k_az!L@x_`wG2vR-zR9oGP$&9?ZIBa83*ji4)DB> zx5nvJYgDHk*UjowhMvu43b?MlZ&Nmp_n)%IN!WbRM8PWEg%OGu7YvQkvinkkz!FfHD)DHL~onQ5=>?D)cq}zcy6PV+}{GA%9SPtw~dC}D$YT- z;iGagM*aOhgV+2A$xJE7d(AhSbWD|`vYLJ(iUj<$TEiKxm_hiwP1f-{3Ik>7h8m^w zti?AHW%|}g9|50nh;p6Da&S*x^OCOoFJ<6xfF{_tUM>C+NB^u~>Y{@FI13Tg07hCH z3Kbgaa6HlI0X7r?12V4HS=P-)^|~(4`|)k81{#@lNe^3^&~KopsY%UNa-b7IHI&K? z$((wGip`V>0Tska6@(~v$5yyY>}R(LG*tyEy|$)U6j>#SWE_KJ3f@#=?&K5cBz98J z---oe*Md`Zl*Qh+Trz|wlr9~t_SuNk>x5uEKjISt1sLx~(N5D2EZ4XFt$VP@y+s<; zLZPKokz`U-JyGOQpglI-_F`^^lV<7~1UwwBCxz`H=n`A5FTifLVm2u_d#y^rZqN}E zgwcOy{3;|8^*#Cq*{Hfp#m~T$EP$wO(!cH;$7v4Pv z&<@7|8~=sgz-Ikh7o?L&NI;U9K$eqt=W(DTjE{qo;PdB6TBwQm!11s}>%9Ja^3O+nikJYbF(&f<+I8!f4p|2rDozXe&asgM5BSNg@l zfp6H0f)v#9#St+>|5rbL#}X)sQ-+Y%4;S&@Z~fDC{zrEL<-vzZAGP|T`oH?|e-Hjo zV)|F&|Da?4s>;8r@~>6-%fO#EA%pagUVB1QXJTg>e%0^(8zt@g_Zw)2Pp+WQs90PoUUKulpi6{U;ab&)~Or#Cxrd- z;rIW28aHNW9t&~^QnJ$$v+~$w+6tas~YBRQ2b-W@s~5){=!!vr+*LqQ>_0= z`p^8~U-kIgU4bL`S3Uk!k6)DHPgDH=YxVH0Zn?HSHJB{kDmz@!s<0oc+ds#Rq zLV&PGpvnIS7hHUQ3hE+Qh1a~isTc=AA4(BzvW#Ww-`kR4vqKM&-RX;DOp!E;644HS z@(Ge4p@9OY;zg}e+zY0Nfc|hZ3h&yvt>Bc)W1HUQ4zV5W%?f8iPTC1NFpx5;j!3=H9!`8qUFswV+hFXmm_ zf=w-;YPkAsATisYL?%UYsWa4+>hOrq51YqwUM`kSt5`?=1D{7c!!Eg4Jfq(Z2H4jd z35)z}B5X_=RHI0QLm-Q3_FHVCr_UONU})x?mhC~+uDs&S+^8KQ>|cb|unE$C?PJtz z&%ZqRAA^8marbg)7Lv{T>{0b4to?G&&VlIM(RZKx#|A?%Kw!!0Odmdy1Y$CYAIUV< z@Hp-!UCUqejujjvV7w7ceo^_%1c2wFz)I?_43A7PBW-@6#swaSmA4|}@|3Uddt5jt zJ;GxhKKcj{5xrfZPvd&IxX)}m#En7!AkSq@8m~fEfLuc@Bb+zp7>9K#Y;3TulDdOl zgSBxR$X>pw4c6wW{h>ngC)m^fGzoG4v}39QAM6vQZB{o~u(@pl&&~}hg>x#kABTMG zmmQJ&5#0TZ%;8Lbr`@az>?~1csvsWr*(_@+-aMiM?M)X$Iq2yaEdc=^tK}TkNcPZs zgFclS^K5uFFjI)w7~pdBdmbODJ`S&<9nc+9K+YUEkl1xEhwV7Z5OGQD|1hR8rIHJ^lq@I zD!@1>yxwt7JhkZ_3BiJ2k@m%rahA%^Zk6624T?ZXFLId_aWHI~M7`oo#N?wCyurIe z6&XVZBM3A*fPSi1Zi{;UOQ5U@${O4}@vdCQD>}E4xNu zwE%)2G-rr%WKzE$JqFvODowiMN`%GwD`VI2#ccd2mq`7e1Zg+{LTD#u?3)LCaVp9|6H)RF<kYfvVKJ^PaOC=}H$rNv%EYX$xf*s;=&<$>Vg`wE(LmYa0g9vF-@uU|Qx3{Iju zUrcN{d6E2qpckQE>!T#A*_7c{*QpM&!}%$O1`M*p17sZP8|~(_@qVyB%5HCF%0a2Q zRi_6`q&;A9OisW;G zC9YHMqwvVnfjsw2idlx>zxV^dA)b4V>hY(j5u zG##0}iSqLpXP3|AdsZ5rOa_wVV1?0pwkWdLZ4WiBMxmOqOXC?u4%-uNkDCYq*DWSB z-|0^@cFSN&WZ%$o&IUJ_{a0kSwStRr603Ke&TBC1PkUhyGe=LZ#N&iLL578zYn)|u zzZK5%22=1S_T;B6<>Pw-U`6dME^1jOt@?F`{sPsRThV&b-$2Ej94jrBqdSGEWCSbE zn=;BX#&O>L9A9^b+J0+J!f-G_PbYIv1#r4T@K2-ixB&1gTPo4uSjQCj+YFn_LA;(g zLZ6jBh{{vuTJf{rOGp@o$8g}YiE@z=yndpNeZor;UqiWJ<-RZ+YM*~fm;++(* z8V|BNTlZ$`8Sne%n>ivJR*T4FPDime!G{2-!c%6n$8!s0Dr%Z?E?KIVud#Zm5O2+3 zId_*M8%BP+8Xmn@tTbI{J6ONOLFYJ0uPc0uj9eyp`0~BVVSmJ|jH9!}v}5J17cFOz zOnt6^gv&(&Oz3b9^-wfrMpI@7XO=|m70Zg8IoCIOh8y`R#k|Mz-;yB`+5m`)#dfVy zYrULZ)MH|P@@%$#UGKU3#oiRXD}6U;JL!MjuC01uvKGpw4e3m6xLVa4c#6L`npr_vlzB*1~XdNFVGKfTEygW(l#Y1Myl%a3FIsodH*!4Zyqwp?Da{bYJfGDzao}+L( z9LPMF&V1-n(?Y?-GvBK-ade;^ga6{A29-))abpdyrQ!&$(i{ERx?}0I$XgdQVc8Y8 znSbvXzkQxgwteHec_{8R0`^S3ql|wj7VSv(fK}aGDW4zwi;9~W%Kim9tO%OP#No6I zcxU#ZtMpwh5bDj6f*lCiBDELVm6qeefahjWuqMWkF4$8h?cWuK``HJ1%=GIQAA%~J z2c?Hl$9Yk|0|Qc(lq=~Y`#Ro$& zEGCDBxiUd@J_hS_->OOYTi_GxCTy+SYC`)vbcLp8lk*$%<|#IAhtLw6%_EM+I(PxB zK0;q+EU?2$2pc-U4)q{?haL^)+qzCg!{v!E5b?)-f)d^*?r&Fy6F~`K25Ju#8PEqT7qyneKJq(u>9rnM&3^L@V3 zz?N@8Je5Kaz?B-F)Tzh8wIFIw;i5=pVx@ZFi|n2iGV zf8z3Dn9;|Y_nNNM6O}enw9{PIl*`t`V{Dd2)u8Nvt7J4)C><`#AI4%F1d{etd|XVlOt=>yjX8-v)99*0XUrtmF}j;dXKn&I)M2xeka`m` z1oRrkw9u`a)KFtz)lFTP(M+`F|F(fI!qYY|B`WY#K?nA<;o<1 zH~yL8@m$?|0;lx;n^OH516E(^&imr4aHri*=iJXvFQnX^<4A&@h`(Fu(e!}el?1OZ zt8fEvPn6y)$A$chx7U7nXQ%m6Y%xV+_9W{k^^9|$*P*WH?B>ZW|BMvqDy+!US8HR8 zPs7UZuwR$)=60e{$+sD+1;)}Q^a2W_IfUZ@u^Bnn%p`P3Sq#u*wKbryOYnQjk;~-$ z5)!#lq!O|31Evnpiwz@W>G#;oRrOq6_bHnjOdg}&BePRkA_#q8*A1FO5(xyFa4lZ!^?2#Y z0$z1n)FqZZkL9#_)B5Zub~GJCVH%B-oC-5&ZBep`$iRa#qj8663B=`08o52$ zA?kCP9Y%;1AG(=$IxY~WD|L{z>4F}UeGV5`-apzlo~53Abw2-f>vuSui9K$$m->ecf7Wt7umNIaq19)&NW_u@45rRgkLtwl1JrPH z1HdLz{G2A+dUuK*Q=!){7?LUHj1D{o-8X$!n|4{}YJO+24~=hclhhDgmd+mjft0j1)J}|BHj@Uc zdle$fNXOLi*6o;y&_2o3AGj?8RMZf5`^}1(ac>3)ofgJ1cg1}4Dd0|)q8kiG%N>e- zfIdFr?b(D(D_d;msu7Hup`0WZd>;BHwMC-W`RHWqkNZIQ!H^G&(XG%!xG@)hxH<6z z;Y#%tM#!1oq>0+`xG?mZyRPEvHPZV|A!={B1ZIP(?Kzwp64m4cr7X#f^r_|o`T#Dh z=N9?6Je#;P%<8B*2r5Y9hHn_E)NF6wH&<^nBWZa!n2k%0N@AQOx}5UKS`FwAYAHpW*tOk0aRmTh>e%Wp3Ss=g28USDjZP@O$@QeAMIdya)VTxD_P zTHhbvtY{hj6qe;#ry+ib?8(ixLvw>BQZvng^A=eZ_RCRjP@c$DqxBEF&_+hW9)zW7nl}wdjAd=*$#r|0*`O(r*6(RuHK^)m+ zmgH{BhO5tin290oq*&J9mLc@gv!U)#1>2eAvKY(xy02CEqmsD7S;@ri#D5fGx@&2R zwIAb{J6>HmY@ae-6tw7cVXwhs(oqCs^s^v!XfeD#>EDpgSA3|^=vkrzdAFzJ;PNGv z(A{OS%(+q95-g*ZueT7GW--YTJ~lb{bUL5V3xJ~Z5|9K47lley$VzXFLdkfoDRNF0 zSDoV)P4bH>w%N6VRciS>aTbNd(Lz+J`?`{)+jLmZPZCQq9d;73FR@{7uF5rd^5v%4 zM|maC=*eu?t}Lisug*&Kdrl4@UYowq?FYAns=cP09%Y@K2BGX z`@s|6cycK#0&K=oIMG^u3{{w<8;O1N>h~xdP8*0hb!Dl8+C}J?pVjE3@WMkC40zex zN?pD3>${Ld)@y#cejKcJiA^qV+DCV^dtK`h{`o#}u_=Azp0NZ{u4}&r)|un`>PpPX z)wzdP^|2Qn9#hPDb^(ZqRXsB>eMeB$(%0fWOMav(gJx49=*R~1UZ2WtT2P@$F5l-$ z97V(ot1CJg&0~XjRf@)kx{mML2(GXI6#c4&HPmEY;yn>eke*Exn7VnQ?pwq~{gsIF_d4v0{ zUxx_iW-g7FKQt|&k-*@czRmYxrOEF@+LKMT;U3a3wxf}RDGd$PmNH}F=qo;_y_=^W zZ(=i`_yd{02Ohp zWqs=?TjACi`1Rc|$7m4I=b$YcUqIG?a(pl!Wq$1~G@Pb~si4$lKn*Abbq*W3P?v&? zjTiR&r}G+_+CJgQy^a?1GtM9+@0K+-%O=P^sCvjw^Fyw^bD*R5BNE;R}+$1L}Q%)anbolKLbGDo6* z@?RHf!VR%v(dg#fi;j$E%ATrYvY&di0Ttq%F8zawJ2$G>dFS`cw!G!*PJQJnBE}~9 zTyLU;I2Su|7{rR{KVEMldzz=>M?y)?rbnUEKJt#R>`{ zDH5v)NT^ybRePbe}c zg%kiEJ>s5+8v1CZUf++)d9a`$Lo8Xc$mlfn($D>#+V3f9T&s(c z3&!48Y_;C7ReMeca9B`76djtvX{Tm;uM8VpkP>xPb}I+-iaUQv3VGQ#-u*KOwPbvb zpX5L)z5Yo}YXjz$y=8Vuh<#<^8>A$qCa+0j9tR@ulri(GM`fy5q@2pk@E2tJ5+3_O9_7_)vrizY z$kb_odLxyWGM2@-2L(=GKv-b|T-FPqWJZZ_j_!5*1M z(jI`bO;ZpCQ>UMZ6kEGMA*y1&%2Uq-j>f9yJ#Np>LU%ZvvvVZN)yuUlfRxEfe3|b~ z(AE~5Y`9DlO7_kfKD#0;l~5i5idV){qRGZljz^&N{Vdv7{#f;!Yw?89^h2a?j;k)e zxwVXo;7LnEv9B=8?7)iMP8R~YTA9D|)Fo%na~jGSVsr&jt(ai*v@7?01-OnndX=If zYby_O|2}cC@z>`^W*e|$cC!~n4;I?F&NSD34`TMg%@oTLve`d1bEaP#86%$Pj--+K zU{>_$eVTSf=W+h6gJB_i7Cqo}M?A2(e?q-{l4>I>uu;1=yp`@Qa&wKcxa`iu&w3~D z7+Tx;5pkpv0FT2n#PP;0^H9mA4C&#r>LupO@5w9dHecbUn&f3Q`m=oq5(mDExkWLo zSUXp!%QDrlS{7|>RjAqrf{6+|7Kz6~RD23Qj3Dv%b_Msr- zhu+2A?qis*>T|&mF^(+VVw@V{lip;3U9TC%{=z37aUorvu!ndq_kLE3B05VcX?>`C z)+Cqk{7v54rAw#fGQF8$E`>M|-*) zwe1Dw{^-pbrprbcs5U{FyU$rZbG`y#zq?_3M3cz~x-Un+?G5QDl=ipZOV1xz(;25r z59US*Pd1GJCAhBr?CySW58aEr4p4p?B8apb8xWUo&`|a80$rK<@?FgOU7UXJlmeDi zqCoAD`HN6;erf``Yi~%*eYG}k{9Y_EkB6iK5JhAgj`#$)b+B#?v`5OAJy|^SpDYnp zxbqEKPbP^EIL_|e_OGijtw)#~N8k^Ld#e>N(7gMmC~v<) zL(Pxcrk`U#H3tUr7za()k3D|uG4_&Qa&Fa&D72#~mTCTX=={@JdZJ6TmohJU{k7l-xL!-s)C zFEsx~Ed9V;p^3AUowu|jBHCbSV<~*4uyC``)r=pp3{xbi-zx|M1^rk>p}MdeJry$p zc-UdSX3jJ!#;OWc?=_UMw9P9m%T)|3UeChfR@sTeql>Gi6C>Lnv1bm<)CCm=6#021 z)H}sb>LxI9hGK8TFq8C@;3SLb&M;sN8ch&y&$QW0O5sKKig_pEcYd{abd|F2=&Oa9 zrVnm4m4dAW?Wv@MwuVht!DyO8Z6R*$dXMy&EWbjuJ6 z6D7u8m@z8RSMl8NYb^2rrQSHYQmIZHXxwiYSA`nuNLMYb&eHbDoQ(v25drID;7>na zy7J4dU!VN;#}C=0-ZfV!BSiMCg&b19UKh@A`$dE!SVxE?XkpCZ;nAYI1#@%%BVYBH z^5L*lZFe~p{F9AZr^G@1&y|OL0k)0)%zmEoYz}st)U_K8PG2QZ>Q>eF9*^5cYDBG9 z9)&?>=80KnPux{4cxkPz$8u-qYE2{a_o zrLfz#O|gO^rOoR%LaUqBjp7X+bUlu!ctalS4Eky5gKxE0JVJ<8TAsAr$x6Cywdca_ zIOZ~}VRKNrRBhCv<+iD%xcK{u1YUjP34ftsKYDZYvoMj#9U2En*@I5bN3U>A;sVPw zgvZ($uZHu>HBp#k25`&?jbU?J_o(O|&E6?l1@8OjoTZi`C@R`QFn;5G=0*>sZC+-h zc33;Tzx@Tf#Rt`UQ)fCl?uWh8hwjVD@bN9Ekx?jJ9knK3JutFM)AMsU9f)*mqvvFO z`Pe3oeyihpK}@9dh2I|6t0y0XCGrig|u%7jWHYMw-?icd^!X#P+iyE{3TmbiBbV%0W@Q0n4Pib?66f6JGN z7>X6d{i?*G=X&PRIR8l3ml4Z}LF-gM=6_sSTh zz^r7|Z*8S7Y9Oh1gGAqymt=TgGZ+=qf<11P5J!EIr;@i@<6GIjnf2?F>Wxa6XV6|u zdlx%Qq|-u^r-)!}ozw!sAdkO>!M?Q=6JNX-Zm6NiVN;xP-YI? z+xOVcN)g>^OKyK{4`q@lKAa6|etNP6wqKn<=b?JBn(oXF9=|lW%Sc0~VLf)i^Ps(Y zh%i{JG9|HMh>BP)=7W;$kT1LQ0DiFZrmyl`cw2HIwfu>$+G85ucbQ8=BY(;Q>b1+` zi?Yy!Dfyh`zC(#Cm)`SdxGSEoaBtEO!@mjE&wfb{lW3AJOY$81YNJz$3~I;3X$`)E z$GcHtwg-0WBUdf#4C%>wcKTwCH3my$!f`F6c!m0IjE1^p=4-{37NX>U#~n=S^3abu zhubr7C8*OZ3WGd&DcLP`ThS4MNIOGxR?@{-@ZKAEo5$f~$g>fK;rW&~F{6j}x`_M1 z=u)r4WUfhUzYlZu;VW?7J#Dr;aOTJ5xb6xTZf7P~g|NFNM)G!gT0$ou_s(_pv#;qY zdkF5tXnS^b-;h@+W@_|z+=vb{N^vRKE;&W57$p)^PPn?ExHdA3v^@qFMoWMm5es1; z`c2F`$>U%nS~K~%ZPbwkJ~_-KDp!l^JR<{2hOP|{z$EX!U0`hw(|P| z#M^Qiqu71Xs~i?Q3Jf1VorY_j4ja%XM(LG?3mPbSJCw9dzf!R= z*XDUDf1T8y|B_P5{IMTix62V^5N(;nU;b5O?d7GUpvBz5<2b`ou~M}Ri~f+|E(W;l zqq!G!^og{(Fn*^TR)3zyc$Z8fjy||#c0vl&7?VA?A+CEVHWT7Y^F9P7+;5|J3U4tI znUdS}JW}rD9wucqGNdh<*zKtQl%ghKg5U52VtqE5))d&0wP{c}5p-D7P0X5uUA;6f z;B{*AvhD=++oAKfw};N#S)-%mwoCHF(`AvNorj%q^zq9}%GzFdOWN)h6;ng%=A;Q0 zC0h8X;H`$WgW@5Qq`*z~VjZEvos6<_uBb_dyw~z ztVh(9|CU*PgW9Maf42aqWgR>^!tSm`+0zLZHyf8~9U)iNvjHf1kjrAu@ipz^ij}8+ zq~u``tz$L;&dW{Na_Kw$GE3xBbuPP|u6#!TM#mu_Bp!*vP4$9piMUs;v_ zo9d}TQq3uQ(BJ5n+|m&;9jEcRHs6-*s@@O(+9pgSqv9suH2WFL zwbjzgig?X%X>2|ccn3G7rjwjb+8CWCAgW!@e|~M}hTro{u|Fi)TH3Uaxfdibf>?e9Rh2({F!QchgNyR%Zm@Y*y#T`h?nTdO4y)eszE_hMK-!4Vs1;@sdfo4ct zjs6^kOWM|Q8V>soRDy|ya$IwJ3i@qi6+xq@Gj(H_Cof+ibS6`*l;GVs>S(!X)PNMT zCkjg>V|T5n(vsBk@LsX0;i#Vsge)RyWu`UZ`Bv@zkb3L>uvS$4f=L#_U)`!Uefyxe zXUeUW+bBg<@t_l$(&f1e{b=2Eb11BKGtv4i!K#|En`?LdbN}cEwq)0xl;SVXyabMF&gRvnB)q#;b#k3iM=s9Dea_i;3Ox_2wQ~^@r7|r$ z9pzHBaw(1eXPyYn{63Sebvvvxu9JNB*{xa>IPo3_pJ&sMHy=+hT)RoGp{RtMu6H^n zWK5Sw*6E|&Q~yKj>FKJK3ODNKaHGY$i`9%>4B-`fv)qjJaxoUqqi3s@OV&y|WCsos zLCco~BYm-bTZ;)A_EN#NgALPK4lhf+Mt`mPGlCxIo@)iFLfwMI zLV`PE0h4@vU#M>Hd5Za{rPsIsPmwC0*;5|4AXkjF)|l1?Iln%xz@flSFsSaO1J0G>hJI($-M2yHF$wYVNieZx@;`B{#>0!Q5~v z!ngP3^~a5|B;_DYr_l=6D77#wK`x_2Tl++hDFW5V7fNcZ2jjIIEUF6NEn{lKIzq?X zVi25#3f?ogHTAxs=T4-kpC zl%D?ZIG<7WrGytJ-0g#L(J4{*fnuSraQk<%zSdv=+u=v+MQ;(tkBb2wdh1nt%BuU& zu8A`7J#MRlV=wD+8qbQ8{lVwYan24*25ql>Frs-^chtIjq>z`gE#e8yOllzF$k%D6 z@H)j!I5S94)4s)N)u2sv~!xCILrB_(Wgf@Hed02kw7j*4I-5-~*vdK7(4E-85hG>uV*dzlA2r*`3sJ`SrI?VGtDYnpKraZ~l!OX-uE|{&F+> z^$~#vl&i{~=U%ZGERkVC30UOi$+brJ-gnn18;%yoRV+fTBRgPaI#~+TToIRO1}n$6 zs_5^^XKOVqlH|3inHAhg!M-E!co3rKB@bM!E$z*!8gY+nlzmu<3(CtXY|_<^O!a&6 zaSOuILHNNr4VrF~H*G9?uyTo(!W5jBD4bx)kP1O`aG*eKJ^F&v2zA22;TGA!%tOgO z*Z* zs2BpC|Cqd`Qe;D19Q)>Bo8VFA0oQ(Pr>)tpQJ5K~NJixFl(i9vWnNDkub!}qlFH5| zeCDT}h^UaJuMG1*9Gf{p8&KJ0vO>1NG#8~X_1wE?nv*_Z6E)yz2ghzp>pQH*~oS0k>NwBIbe5p2L zF9obKrrH2u$rt`L<^(H3PME#sCd*0neg$vqxD`}E@o}*a2Uasy4+O7kvG7=F-ma(q zmfL1MteJ_CC*>7h*x7ElajE$rRxs^NkqnIWx(?XfJ}0&N<+5e(I3K&76-lmgn#^a%j=M~o9iUPU8WCf z1?|+88bmuBzWlN@IxVzWqnM+?a=(i@+%QT^Jsy{`>+!dm!P#EjmIeLp&UGx4+O5X6 z*}>rxLxjRf#c9Wz;+J_;Y~DfIbM-ja3}fDXNj?RrE)8)wQ<8=s2UZh2Yp;_zs(4Sn zAgx0!uT@^6qWv1x$$=X)47HaS)WiFT-Dkku#3`aeqNtAcjr)NxDxRCIR916jcRpf4 zLf$w26|O?xkT`Hs9%rOP9ndqySimrlkU$iLXJTNf`u?c6DVE4-ylUt|;%-qVhMn3= zPb+PM1p@uJ;N6~d&yaau=7a9P_ebEI9{KVm(uU5hw?bge73k}wmFl+6#=q>B_Thmwsc@Rhhr1?5c^6fL% z)fJ6FH3%obJ*wtsclA+6H12|hA9wI%1PCUv`7%Ccw<7WJtBzXND7!*stE577n)wk^ z6q8|)ob8GuWF^d%QmumFET*fT+=T-hGP~?PY0FEb>8$m&e(iSfvdg9_ypz4BHHf)h zW3%F@B!SI4mJuaS`Yn4)r#VL3gW#^!P7H}rNH#5q*5%Z{8GgdBY6CQ|n5{fAv^kAs z^9G?3-`T8L?^HA6+_+h5NnutXS2HiR@467$&u$6LGmZW@ zc8ME}fO*gW=mLm`0TWMAwW;IETU!q?19}IQd)OnDhltIwSGX(jpn(T#clC6;`xBa| zsPXnLMY+PM0fuqMTByOZOHJv3j>*=sp(&sl4UdgS=B$A`7*^>%kY9*opS+L%bRsC) z(lESNq@)J%t0Wr|;3+dzg5cyW&_W>nkOt`Ppqi93tDdC?lRl;nRgf8Fa z-Kx`HuReiMGVaTcD*@TKbZx7?pR?8;wAEOOu5*@I!r`BPKVla)$p+g@sBcw=Y)=c? zw2?Wr)o#^mS4f)T$)XPLtOSKP)`vNz}Wx{rC!v^3}(FKvONd3rdt=B8JrdWqH z?4k$6J9IJ@STHM7Q*Op*tTZZ&q|deI5lr2$g&vG)&U&A0GSM~Q{R@-Rj&!`{H38WT8S1kU z>qzH29+|U2KsH0XFGJ{R7NZl2!n!!e%d#1q-nJqK`nx;H79pIYFVm}#LkT-=j%e6X zr~PVS)p0cO>B`dRT}>N!+@m*i9sDctYg_)_6kZYh4l7r)qLM!3PB=u$A1o+0&AyVL z?o=$Fan;oG+d#3=#u%*;Uc+f;bPBK4RU?^)#l_uAcAF_b?IWtTGckMxHLvi@A9v^~ zfy(g3To2&eUGESc{xC{WG2z}cV(e3BbI6)yWEB^!2MZj?9gFJK$jBIS)o0{MIXn?K)gZ`xx;QO@^t@VktxUDetPNxWk2KoAu3b z-b)8GIZ=9kc}+6+4#T2iG^-|z?_m$Avi1nc0 zS>f=08A#jdZdbw)pajxdbaT{us#WZ_QHUBc_BmG=H+*`4l-5+p5;gLylrPf!pb(acO$dHr$JKnu2 zJUu=GYvEqfj`JA$EBvkJ8x{nI^_%RKE0iSdV#XL3R49ue)<9b)?oE?S|5cxTg)L9` zoS;V@kx|%H%J!0n4_KNo`HqUR*dg5t(Mkw?>$0etzXHGAD}~!6^89T zdaG8Sdh(u%v~kZks;gt1`R_OE7vavAuFySs!jg9Bnkvx+;q*Snb@p1$c20vi^&%p} z;rlpV%_BB*S<8)5My9ue7`fE*8#?QX2Xh(I1lJ4|?4c$e@Dx~Ruw0K9F%)Ga7JP@5 z?hFLze7U*G)k zU4MS!EkgY(aqpLFicbIgQM#WS{pqmW{_$OZjpGR=-mPHcmzQ&S|M#O&VCkZK`O&K3 zyQTl@U4QwP@58SH*s$d1!QZ{A|NEoQ!78@S+VctW`VC^f zd=&Yj`1d+M=Nf@ZaaUS@`2xTkqhL+{F-(8#k@p={U@}F>`7LPv(o$&6;(ZMC4>3f* zioZbzqD?%fuaVh)Xfu}^$mXWs7TQG~*6}WDtu^Fs!ja^HKHFJvkT9WEc6P(%|E;Qb zu5=R1x#$8NK&#)W*frK4{&Zo2*~CDl2i`Fy zqdLDO|Lt2*G{ExwyO{s5-M_Eczl-^=WL`L5e`|?yWZF^e#j=%$!FdQpLP+RBzv4F{D7r0+&pUGa>CnDl7=f>rt6=JVI!M)X$yj>H6E5 z0ea>=91DaRDApmt3nt_}`4!g#lH2viH&QZX#{K|lBxL%HBsUVUL?kWb5Z}4o-r@we zf@2j~_kXY&gIBO?U3B*D>?xG@nb?iER3FXeBFCf>5@dWp-J;~>0Zixus4*t-xpp%! zN@wC%zoAm%XnO7o^-od*JVW(XiXt@7=A# zDy>v`8SXn5*a7an8{XujsY#T9E^|jhw!yPQH_SDY4(n+VCUc z4GIB1o&qJ(S1KO+FVdZgFpNGX8#A37!#*Pz18g?=VobzA;=RJEE`)8B)y+89yb;q) z_IRY{IhKg~$;Nio`VM_MB0Wr4Z6`I;BCnvrUq4iUE!u26Gn1}8?>ZmqFw$na(eDL) z$l-DmB2BgQ4aIFbld4PSHg{DD82G7de*X(v#Mt~2ug0OYJL{}h{|EH~bwFix(srrg zbCV}m6L0jN3PZ7D^RIsqp9xTq7PyDaefUYdCR3h1jN}nrw6^Ytv`wq3#$%h|q)Ni5 zdgKAG%`RglQItg;{0+!ajT1(3|E;B-ythTWLPq)f7hR#)_Dg2TBQ$7%j@nYI9RDk0 zT=OFNsp%k(5XBr|cXYm`z*&r1_ ztFu{L$!f-=FQeC6-v5$rbBHTS6y?CH14Hv9g4#*XSy@?bw0p!pE-?9H{;bD%XCwAc#MCf4vnu)ab8Y zsmeCS#G|aSGqS{LJW@o(2om1+;w-NsCfvO2A*hT9kU3tLvl&UnXk#etjNs>VTpy`I zG+@lW#*?AVaqH|AZ7psiRh2K)>AQM`l6ta};P3xLQVSeSeF|OVcV`)hXlB5tvKu0a zN5cmCc`wvojwAbiqnI7x6<}Hs6a?urWR9rBSS+T%hK=y(js~ch=1Un5x#Q64uOP$A zZdr@$c8BzJck^x$$7s9C$*FEm&-hUUP=@k6c8W!6I87GXY(WCI!t>rgk^2@BjO8yGK+l2V4ryMYEa|+Av;a$O&;1vC5vrzXRxnTapt5$`N2@n2 zB^?ZSdHE%_=+wQEn#l*1LW_imli)k-)J%2DeZ(oA+h<;8Q|^siAIDMEO=&$HOi(t@ zlMRIXXntuo$z)ib+Ekj?+0XE0{jjB;tfc*6bQ~XFp$_U5L?UtZ^EDY@s(7 z!r2-9=<8{R-QkR%&{^jV@*e26yj*?tQZjug-|WYC_os@bo+2@*Y(Iq zuKM!1b4n5oHm8XMr{E%JVR*~igaFW;gdYSZppY*nwzrri6t7S|7t2&{Om^EM>fuK` z>)n;%K6=eHKYcl<-4=uPrL|$0ot`B1_S4CR-393g5kRLyFB+D@wT>9KT<{eRRF1nph??wW|O%u z>QG}r!UokoikzAXRUXKNx2H3LIQxN=VFFBEiH?0Y?t;Q5hBy!Xl@Bq2%37{W4M<1l z{2EvI4l8}p0Bf>yozp4mWUJVGoFHgZdAt$i+Hd<@!wKa-n5fK9lj?})JNq0&wXeW6 zzfpNC)SoFOv6+7EhobY(j2ejd?uhBA0ie{t+NDA<=587%w?7Hoxw{K1s%P%`%4KSL0cmEa!@01-wZd8> zqkxAzavhB@RE=Gt*A(}W!4p8lE*?};Z=MT-sP^T8EioRoO*MuUD~SI#*WSS#K;|^j zkU{nr%P(!ma`GUEU7B8#V) zgn13*xJBL$6ywAX&c-vVS9F~X@Di@{d2Zw;_SDx0oA1}!*MbQKF-aK}!N&_RBRWk| za|u=rNf~QsHjDGJ_le$OT%IAzvdfgOO;`D_OrMAR0=ZE#;mKB|%s~y{1`iB;0`mY# zr{CBG`#LPL$Pv%K{3Fnq+XzKgY-}itzwd$cXB?{^`;7*IIn(fD>2x=6D)?* zsFjH6+*J++?5>trR>*V##R)oEZ};Bm`B@V#^#A=e!b&TS_zSsJFO#3|8qWeHC}>w ziQI(en$&31UxdAhoYSSXq6T8nDW{zx%gC~L&=LNWT0^#~{-7PJcs`<_v_pzvxKMB= z$N0Nb?n{eVSp;s%h2(!VTZrOmophQc-0gvQHCS3^Y5YVr=rs$Us-_$5(F)@u@uRS@ zms730d=SDe4JprNARBm@v>CUVG`?AT*2r~Gg=Y)st4-Ma52bnFhiPmWe;cM>I3xjN z@P?a7P59htNBd43*4`jRZ$XqqZ^>ue66$)kmD63E-XDhf?=n?YWgmh9gf6D5^4jbo?tI%mV$=&2Cb+?3 zJ=N2ngFwQ(kkR#JeCq6W6LxnDne(uR? zE(pQ?SzFhuk;HeSQgZ8v0TcLA2vpzaBs=v!#!awaR{#nNMT2J@a^Ek>a7#_WF+&z$Ok~`>8wU! zvkt%E9da&uV?PVdrgj~0H35~sa&FQI7B;NqRlnTgx?fRPYdLJrbw3K`G7Oo`h?L3G zGKdI0L+;@ff5zO{3P2F-^;^TJPXMNQuJ)4xBXrOVA*J zZ?E)e+yb*<=v}KCD%V5@%TXQ&Mt5-3ig%uqbzGyIa?7$pXYMquq6(BL8vXG(#Jqjt zD@^VLR~^T%&DHHPGq~1~N2NOC)fqX~+J(DJODJ7wP200`GR z{YK~qeSYWZdq8U*h=~W9>29DHA`z67=zAS8HZ;tomPnWmP!Y4H``zzzCa|=s-*+^x zMN0b$k0Lc-u= zrt`>Zcfn){-sajumzS@B=G1`#A7MgOuBqdmHL94&+Tx!}EbReuDHM;StYie#OL)6P&%z&N6n}0M%jI8w z5$XKNCnMmT?m@=|Pnz&z(L3d_Z{7S3>>H9qjb(O^Q!7+P1Qi>vV*&S%0H)LzXpE3BLC8?o`*c+PYNG>+aUKME1d$MY!FLW^+~9q*&kj^EJQ z`0FEW54g#qQL(t((e_MJdcSE>PN8AH(#oy~IQ*mbTtu5dN}ARq&|iaH+nun| z>kuV$vN!&|XSS9`+n<$E)L?B0FgQIH9Q3+xIt6F$md7shXBqhd^3*+^!a6l^JS|W7 zsET3S2Z?rtMk2t&NUF_Ow%r_zNeTN9t;Xhgypp9-ESQzHYqAn#-=JD*D7>&TombQl ziVO2fVYcGwmqZ)ub(^r#?yn48HfAV|G4UldkzJTwGGnK-d-D$GgtOgPmlfd6DVUeQ zMMmE@@6g+KUVE@Z!_K>4m{LW%TgT4cQ_vsk~w3-i;S=Cyoy8dFEQFn|NsO}gsiO~$Y zgtek|S-_b_z35L*WNB^55gnE?Sm4Cqv?9jBc9q*3xxAV`RoUFbWO;F z{hUMba#~O`xLI-*PLmw$gTs9v5u4U?j48qgpI7MJ_#_yZoP_O)aAi@_bcl+j#RHv6 zk%-zYy(nq3Xx=Dhvti34XP`ZHA?g0Y|LFzrJM-#KRT9ezyh6iZo4)54*Y0P`d>6eG zVqVKrdy~;lsRW^v-Jy7 zB|GV&kuP6iyh)jkmwczw9%ypk;uF}0T4Jf+nR<~xM(6({)9SThK~NDHD>(vEYgPBz_UUq|K| zhCj@COIrnhV>TD7UmJ4;Z@KBOBu#oOdGkH&jR(!2Td_+OdFgD6_MY^InR$rl18+b&^e!h8 z`NMAb0EZp5KhSTm_Q8z|pghI< zO6skW>|Kf#(sZX=US|o_J!I%2#CJEvGM)$x7i!J|tuIt+_~^|1gWH7N7BW0K|KWsM zr6~bXqL(FrJ;sVPYO%|&QM&T)7?XN7_xi@PU2mfx5+(H%lT)2(^n#u+DXo+l>dNIe z9Ow4d4*Q@(`yL1d32>^d7gPKKqmRVc)#~;>mllK2!|p|p00J^ST{2{p>}g7B{i#9N zf$SWr#-fk5uEcX0Q9oE4f>`oWk@YI24lWbFH{9w%`?@5j{bBG=(>VH{5DP|O#*(0Z zs=*7n|8W^{Fh2UzXBh|*Un-vC>zkXPwK6%q!#bC02Wy5ZZNuqK9__(Pq3~5#k$1+fClA$32izq^f&y zOPWdlm>@Zx#RNw#3uuyh$ll-0fsOV}LS*g$Hj{bjMksvKZ7XKLB}+R64URl-Cpb6H zZ`)|eM-iLcJBRL~rwoq7U*LCrS;?;LZp(|4^1K)$sV=`dw)GBY^Donf$1!rkl@|Gp z{%O)YvG=Z^PdK_NG|_JJh-zcfF`-~?%&hPst@1g&@hSKoTAc((D*d2NG~NpshQ@{) z24>=}kDq(YXG&Z(vM z|77%ZuHF8xq`2(;e;~!Zv4@*AH3Z^EaCvkU-po-QllQ*#m!f=ha2nh%6JUw4t_(2J zbI5`5A=;Vt3NAzQ-!90_Pu?aEWI+kjX7y6wT46mMIyy1gds%rdul&9N4Ms?e*`0gk ze$da2V-`X#-k+$K4wMN&Qa1>R=^-4Ef+C=7y%d)Nx-LA zR(-v_A(*B&&w`{PeB!kwgH-4DH-?RSXPqGg| zQX^Y8<>Kc*ywq3`EOCe_m&2R?`RGIZTfq+pKFWM&Ise;=aiB?iB99Vz{x^3FAMjrB zO-Ih9nf~GJBxurJI*D}BMHu$GRsa3Vm_Q9+K3YF#6MvZXAEFq7Chf`H%<4X;ME>DX zU$9EPBZ6{@xS8v|3-Vtrd+yw4JWUs z&4uv${fNDHRmr?`+1{cOBnB1`))zFnjtC)0wug(#jGyyOK`I|@`dY(!)WeuZdWc#N ziDPouJSVDh(>kX>xKr9T$F{Ii18SrU1r&~AJ0Wv=;l4z4xm*9B_s%JeY`&k_|7Ci8 zzeV3EU+|}YX>@X!a=lxkYS1VqZ>zRi`vL{aJHM?Rnb7UkuUeU2gkqpw`DR82m4qhv72z66KaVJrc1Oc<^;nF#)4{EopIXb91islV!&xNHQuj2_vW$iW^rFf8! zZ+x_?AV8;Px)PXUC$}bC3P8KUyw!;s6cVG^(rrDdD5Z9o`mPl|k+!{O!^C%+K&`AZ zzJZDc-5LyVifR{2%ws)lw;oYyg5DRDA<-4z3m0f)^!yx{oAWoAtL$Z5Eh|(gjmggk zZ+>mv3K4^5n~J?l^$31^1nkVZ!n}i#lO9uM{u1HMN2ILQ)1t-jOm+Ny8mH|8 zbt@r&Y}xshdmeDDC02pYC05NVR;X>(7&+g)qyLqq{;EhQ=^b>t!r;4{0V1%zRE zGRuGU6S-5h3ELyfCGwk!(><*EvoUhe*3;b{-a)m)4rVACTf_&w zEZY=omx4Xh_s(G0JoDLNkE8HI!MW-6vMs+D*T-7^LD(a#yOrPbrt_}`FYYfxdfFL% zK{FsM(Jd{+fQr>~>G>2nL)uW<>aBsQiVB@(ldNQX0C|2AqS$St@Dgf^Qtm)4yxeaG zJWgR!PJHj8hGU+g^*U)eyRixrJZ3(~y&Es=KmUyO!X!&RWp_$+gb5r!XgHf`GiC$C zSNrhjUekaUy(yQ>DO*z_O-GL#Cx*_Q5SY8o@mEo4`MYgl6cnIA3yC()$>S5=&br-h zyaIK`XbU5N-_WdREzlu6*6N*S7KZ2YilAMuw_6RgEwx?5!)#wfJ-Xz*XJ_9?HEhsU zV-_|u7dK9(r=!QtmQA(}N2@dxaLhV4E4ttG?YSdcI(QK-+fdh{rx0IVt+NCxHf>q5}U z!=kL@P$Ujlm3bwa`Sj5ICp568bBn_p^yQ&tLDK|xDR4xgP67|dp`d$c82?#=ekW_& zx7cSogA}Rlbh1M|2WX*myK=(D>-2cdifXu%t)sKJC%IM#bV7RG zJy<@yFMym)K5>gtgdUe%-(ciU)pwQsP!$!oMAyaTKepnz_w*<}E6Ks;^lh;LLjuy~=P-|G? zu4MglEKvY(#ZvI!yokscKJYdn3+8f6pi19JvumLW^C0(mgH(Ig{}y!Mu<@Po2ec`Z zufY+ak{Qz=>lIkqQ_VtR`tbfEXoZdt&smQsMW}R=l6dVSOSdhzC#NT{o+y51V!3Ex z-OINCPWO|~`|E&!!sCq}ShX`YUc$~gFjUQLn8J_E>s-`%<7UvXQo)cN1vV+^@RYMr zMK|_1lIpQWkwn419Sw%(sknw6lB~Lk1Tw6a-v81o2=!W_r^AmaTFo{<3}MD;v6oOX|8XU`oLYgrAaIn7ZfrcqZox_w4gRV@wz zrChh&w>ElmYEXJpucM2z69y2{OTtvXlvgNsAgJ>>xj$^G15s>rqd)sujk$TbX^^?T z7Rk0Csasnc)lD;Fklz2~X$8ION9rnBW>P9S;jtt|Ws#itY7)Ws>opt{M`8V9pGtXu zd!${EiDy^yD_kIe>WNO4T`)^h0e5G6wSvV_2xzgA;ozO(xd^+H-U#n)^Fb3WM^TRJ z-|i`?q-ruiHO5t}>Ky<*xsSHe3w5-FW+_lg`6P`;Ym_*wA0VK@rv2y+tRO9A>b|p* zRs8K4mcdq~T9$P2uvV?n&|&f;C-Ko9G~r6ibtUR>K2m0`33QtSnuHY1*T^4$pN*HF z+7_c+*QED^pP9~G#t|U3+IQn^IGyc?r7Ep(u668a1kTuzT|ClOXGMdf03aLFp2VoL#5rJ7@v8(wn_+#0u)6mr96-LOgVu0W26iLH0R#6Aq-=0|AMp@Ak~R)t~I9 z=%H`xw^7*@swzkIJI_j1=~qS~8_;HINxLTNd4ffqR+$x4qcifz%Ei^@bONiW6&%0V zdQZ^$Dxg%F*D>vkpYi0Qq;8RDN+4*v$mn*QvFT@sa;vbGda=7OD2NLZZ5%`DS$5PP zKiV%M{BYq@7=RF~d=^;*9p2<^0V?nvp!7)3aKaM|P_?#GqclScC9ZjPn^%>ET^r*o z%F5c%nJudx%XOUN)itZxT3m>bU+0Y*kC059wAWS;6JggpNZ236(VnoYITwIJYLO4G zfr#g}PW+K@JcJx3WSAKYqwN1-Yo4a*@2cAjqZ@&lAu8uz{4wxd;oaT}hn4yNjd&EEt)0ju1p$rhqbtNpIw zJp?hq-lS$$q+L2mEXjpfXa7uU*QsS|IT4UzTR-2|(exC$!ca%>M+G5(d{ zCe_sqDdyX2;HcSt9iYqd-5-K+xrm=xisKd4ow^Ixvi?*&zUh{=5v|BH9%or&($qqf zL_w%o#^zr-PVSbK`sS2&Sj)q}`80s0$)+vk9W#@qXc2u;)dNZ1E{>Vse6VlEXgUhR zRgPL8oz>lEsMOehE6INh-AldxAB9K6mBUsn8VV=ttW3r)TGVY=Ee#uql2BHiPrpU1ErQ1G zltUPUyND>1{=p;a{E4=6# zHJ^Ezz2Hk!#N{{$DZJ^$yPqGpqq03hiBMwP+V~7w>J>wbl3YwjbddYGjvGYug(Oq% zy9K#zdb;I0&D=}LDUz(Vl3jM~IL$HRG1N2uTx?G(6tP4YO17V^WZxjG-wRdnnQ)&g zCt#L+4AWb)-ts^g#VlL%BQ)%M^9t)YZjf*Yicj7Xw8R?UI$VkE^@VUgD0la3v|wne*N<-+_cdjbX%pj$INM|37P_c7_02z=vdPko;8if|^esVRGDZsb zLmRHe*X%*V{P5Vz^v`fr{||fL85LEwb=z%3f>4N15``iu84-{yAUTR4IU_kr20@fi zWC;RFl8lmbrWA@SIcKW?$vIPmx9R)7JG$-u^!|B2-Wd0vLk@>?_E~#{x#yaTELPWE z=V1LtcY4io-gbxMZ19SDp3_P{90h9_U$50mKpQpbF{>n;-oC<)mR;GRyK+zX5YgRW znv5?mY5v}8%)G&|UtUEw@4MH|@$GBx!(vN?x8;PT8**=`=8=irvA^^RI(Fc=W2V|d zpQd39lR$2xTUG7bmK5HEIICLDzUCEe#TPz~8|qFb!|^)UZ0Q;6d!NAn;lRphl4r`3 zzm)z(oNZFo-4&0e4Gqr6Vz}+d2&rcY_WtZ%p}iG-*Pk8|TBBdI&`q!3Rc&mY)xcLw za?+-MZ`P2C0<%GrW18l*DJ!M%Lr(if>&s2GS)dR+;nUfE$AO?b^vTR$dCl}|rtv*i z^$tdDe2jgADNYBt4b|!k>@hh70e)wgooz?=IP=UT&adotN1vuU=H_?zPAe%vPQS3a z&N%#If!Tb`XLjGqpzQ_aM>n?MZjMI>W((n{MmB83O0I_ej!(WX4f;+fG$fA0t*Wkz z&(hcWtaNap#zLzpf@ZJoxm29v@wEnLSr)RGc();Tb54pz9ot&cF3dU%H4bTPEXpa+ za+-y2vsLm=xGz(*y=h7=y&q?F-vKzmLd1L$Cg?=Rz%Mx|^GT9nPD?K+zbQ%}B z{Gj987Xy(koDENji8^%ENAnqzF8dW7M{Hi<(xWZW8|0`J#%Gzm0_ zyt|=WtOJNp2}qHoVoTr{!ED6!*OwdX?MxHOkdpeh-ex4TPrGnB0-HLWFhyx zJHWRV-hcK9NPHvbw&Ud9=Yu(>yLSD0?x@J#V;;4UJGaWH>lxSEx0Wnz{rkI)JlthG zs6#yC73pA_+Kz3){i%oF6Zuz4C%+#y(v2$$V+<=d(BA1Ln{!*gx1BhaCOA!*v=M0+ z4CQjq5k&>0T_3M;6{v?(Z54R*Es98lKsA`d$y6BFl6ejX-Kpyf^UIMW-zp}YT^!aL zsp|#0*`gHqq}83~=44;pY4m?_V~_u!(z7gR6|q+96ld8r+LvswC%7=Ob6^G*jh|9~71ql+q^L{AIAi&QC@MDtzY=N_{=Nk7~6HBEBkKHgrkyqoFQ zdUyUc#J)YE(+gqZoLwoj^X+1zL>m#liu`?5SCk(~!+HM^y5uXHmd$2>-HvhqNw5V7 zCaolZD4`lBJIbCSmjDY1ftuj~Hgegj7fr5@zBKB`APRiT|HZcaQ5~@u*`Z1Et*d@G zUBX%FTo|ho|2vtCwUu{>$IdGrpHF~w@`q+Oj5y@2#gk|cbM zhIPzP$i*u#EeW-q`&1zd`C_=737%tzP3#Jr zXcIE;33P?Q<|7hjro4I&Bu5rqnv3UqN`al1lb^ySAYymGinx-Bz|*V~9FD&%?n|6{ zWC}ogC+md{l3N-Ehw-E_H`(Ghw&k%MjSd1eS4UO3 zzfo93XnJ(n(djJS#A*o$c28SL6nqVYn2XSHKu4@vigbJeA1@y%M`Py4XQM0-hb?rA zScJpJ`CFHr53d=Cv7=W?6mabMf{uwUV^-=+N9Ne9*&@6_-yMP8lh^UnL$jOt+bV}iEp%7mQ8>n zGr^(Vv0`k1X43?dSTRkS`7U#na{9%3UE$c0W$b~;>fCF{U<0nlYL(W=Zb3$}_Q^(L zc!TD0t{!1IJSB8K>W)6Wlmt(pY+1SCv`x)!CWzXL{d}7$@%(3Q!*>0heu@m4erX78 zM^x3~0Hem}4Ml;Q+#?Iaqc-*@h}a~&C`BQ+YQ5F>ldB+BAB1I;oNemA$i!1r|PhpPcx zl1wr6V!d$((a%xZ^NytCQ2Dmu$Zh}Y7A%`|+fA`LDgvGdUp#!xBa`vQw1nh!X}uHW z9uNqdc(3ABWT=uz>lzo-HWV*9A0toYgcCU?y8^h-jx-%?HO6taQ&kOx2Gjng$=-Ja z_K!Qv>kgjxJ;a>ce|P=UMu{79?fqLOXg!yyWXfdM)Id>Ox35Cu-;7DaHXDN35X3f$ zVJ2w|E1Scs4OS&x2?{Bj-?i2==aI_y&;wZZfhuo|RfLfBO+rIpfQ~NhA)y#`FdfQw zBo@jHf9S{iNK%nJzkV%dIU^9d45_P|yA z9lv|fPA5AJYu?YTI+8IbJ7i<4J&@s@f7Q{Snh~qbWmP}gyyy(#$J$=my)W=w+f5I; zu*{WWD0v%t+!i4_u4(hGsqtC7mAX}hGPge<2J#-mXClp2ulU8=RDM#f9!&GXlGuTF zxBYOyCQ^c3N)i%>VTkhIc8(L4Oe&Z<(W&&-(2FlFj>$IL-5Y z$k{Pw%1}wa_04$09)J0Zqr34oX#!9sp|=vIXI+WTM;fTg8Aaxglo!dC3!XyXrm3-` zt4x!y`strPpN}<7_7KXg>$-B7N|1HpdXR#VZRac59-ls;7TD=&q*G1yJdQA~+_=@J zBuau4N zwRO|oGpSkR3$udg^|fRiQ{wZ^9_;uz;ff-?I@t>eY~+|2^bBu*D`qNCbjhik2pNL%*; z&*VY)l?CPQ8o)t&F2?dFNc)d7ad}4I;b|NkiNY478EMLe%P+&;Ti*?3eyK$1PH9~6*So_wbMuZwUBlf|s(aT01A6hzY4lOh&HayCty z{M!ki=i%V6YSvt~oYG5h&Ep3|q~Wz^nw3q5QNuW;Cs*kme7^u^1( zTCnX)gDpBv@QM71x~cfr6Ye$gEfXC*0rLT={9yd+?@W`Kt~DXIG`l(cO$|?uBQL|2 zCeN#1Nh&w?uL3HI9qA*nZ=Y(wYL7G*?Y?UuitDi@j0uOpcFhhKNsypXV2EIeKXra> zOzYbh5rgiSnNi^52Uz$rb0tve*XS=v*49J9erW_>C)8usd6N|>O zhIS^_r@dC>UlzZ?6lAhKz<-CUgbAmoD&)N~t7)m1Ob?h(vfKk<*K@M=q3tD@MQC~N zjev#i*hzc^Tc#s&@15Tbj*Tw`xigz4J(qSpd^_Bqd7a;GpVn@i8~qe_&bZ%9?m^Qm zD!XxyRkv7;J(c0bsujB-D8X-dm2C1g)z9*5sk}w@vY;7B>;b$5O$za^zzF%RC-c&@ zaY(MHK==aZTkNE81Cb^(ctf~3xuu@flURD_C#3vqwOX7PI(WW3A>9nz$#G>q{2*IC zX?p;VQNDTq`Q^>{2U=U>8XBDJCT8-VLS#<6pLhj&+oK836x9R@%F5^{8j9)OnPz2V z+&{0H>#NVPh`(5?h|Xnn0awgK)(%Pi97*=gu#pv#d;U%&wix5FHw?mf0jDJ!9gSPu z7OOl!w|UvfQ@Ort?2i)IMD2;T@cyQx!8CtBdcVm^{jrQe%B^Q|73=OZgLb-{nj#4b zGb13iItKz>70T^TFOx99E>7GMI$D^?Wz-SgYptWhyeQk=>Nvwe$YnaVvT6K=I^Jf( z4xsch-c;h2e^eVw7jyT7?)1EImp;iAtpIXshNEsiOoAO~=Z=-DQLa@A4b9ctv;#FN zt~GK);&AJ{OnxwL6Cd?}vVb@Q#JsdHA#PkCS|6lL&_4ck-4vKA5CcCxs)(P%_Y2E> zmc3Ujj3Y6Ctr@NT;dNqKm;kd?+1z*YJYdtH!IP7@W`&b358zC>HEUz2iIQ%{k0dVK z69+ttrA&txHGWH(Iw^Rz3_*=X)4_-ZRIKd6 zMoq76GbHndqh3GNl@|?YW5k6?gvd!+wECmh%`}4zjna5*YG&%~##jB4)10SG#vMrm zxA@BTgpU`Z>>BRO6A3R;>K(HdZ+KGg-3w!cNY=JWsK8+mW0l7%B`smn1nUfC?^*7w zGeYfmHcfp;!Yj!uyY(WKvpyki)Xr{MMtvkml3yOgCP}~AQ9r9^)y;X3)n;~$KYC!H zQ(v4sVx|(d&s61A-mem1q`-U6bHe~Nzsy_Rc(i=X$z1taKvfTII=u3gPq%oJqm^VkJUEc#UMZ+LXvkr7eS{|E3Yk zZjELIVGct(iFKKeQ`#BM3XWRJP_|h~ZwoXhD9K(yfH;J-x>cY_@QX0A&5RS1SUpIX zz|x4};r|6gP*Elnp-_mP1n8z?MSaY|-WDPuTSPX;;YtW>Ef^UD7+bvQ7Q)ot5WJHI zydp5ykA+_(5UdZ>EwO{tKMp;)p~0T2DUy=Dsjx!su<^S=jdg{z<(@MTr#S(b3i9I9 zbGY{fGl4L!=cdW9FGI3d{WC?wZ~EKvJlA8j?X5Mla@bU7xNdTI62w}-DATWw9d4ao zrSh9m6v~3SXRA4-T%MN?H&uDnHPuh;1@KCwLkkvX`PgHu=<8 zDbBmTs?kA~ElKV&xBMaM`o0mAKCBYL(vj8Qs+eX!OYPzJG4p-ui0;2qLSP0_VS?F) zpCWUO4i_J8rIieTZo8xDtcJO#lW!7}E-CS!QifjdO)H4Ce?SDWz6?7$;{W=ipps9~ z;}76YuFuOFAd`5HklbX{PzWYM56#xcJ?&6aIFgFPpu(LHDg0z23?``^afx<{T+`J} z2*cIyKh59+w}3rDMmbNIS8NRQcl&p+K4AMQxS!DEOlqD6LcO7I#hClJ-LTF+QH|%) z9R`0DMd1?T^Z+fJYF6fQbp!P&5KO#JJMvNfWVWp3vDR|jqv-}2Z`I_yeizhMn{6LqA2LpS8%5xkl}=7S;0Q>GHl8VlUR7n zb~j+#YwaCFq(K~$H^*5snXUg#wIh?FL@OAMMD6}5#^9aF)7GHiWvFv@x##|*3-#$1 zzduK@NtH1d{4z0PNKEhe7r6Vr9y^W4r}NlqX5|A7tDMQd+8_uB7JwxXU}$P|+pykk z9@{=B6iQk7ZT)FR%T}@>n_7Mm-=Wn?5kWV8Qsj7shsa)AZOC8;eW9z$DVpmCC_;15F!A4%39UBFv>rEeF6I^+`Ga^ z>LXjMz2Lv>WsCo7*vu5W+BRP~cyuM8C-a3O!yc z&%$Gct%|HcgD6jfhG`Nxv7S`~Wd#pCDJb$c3&z*6yvLkd&>2QAfz(eu%Np3#R;VwS zb%i8zgSD}}R}h$F7%sqb&Dsu&Qb1SpUFNb`LW9pQe{XUQ7hLnTJGx~`vOm)t2h4r{ z7{?&5Y?!S|t+wF&1nVo`GBe%Wa&CtNPwSB~!5vnsW-5_0AqE zd-Z$?@C!cGJ(O-?hALZQzgeIPcQIXD)fcbBfKgeAS!?7Vknbdl;7TE5_w_tCRpShU z+WKQVG;Fu}4UWB{@EUER+9krRF-%= z58#FKUXsMGZ*sI2ZHR9B-MXScLLcwg$KIBHBS1RxV<$SB)c)h%1%$4O`K;at+q10c zfXnmAS*|#v!3SMo&|cL5w4a16a=pkj$%Erv{#@sV%vOmD`6{&*dYj)2fuI+PGJZsn zKa)+)JrN zy)qULyhaZdzLha!Iv3z!jkqNWfvB*j4%cUB|0o;=jlEP&8Uo*^Y=n5^3tPI*HQF{x z^B^W+VF%YwHfLnA%odbi3kp0q<+RQcUZ?cO!_W`Bmr3J~g@TzBD4+|VIA12X91=z5 zFaQVcMfmi;e&73UaTVkEs6M z{-+2exoeTg?~~y=ho@c38b? zP33qHXr9f$M^$^K*Er2q$CpS$9~NeZ=D12E#-%})h$msZJ5!xj@5~J?8rM4|`W{!u z^)+6H!T*thFlK#mEeN4bfBbC5sc#iPw#TJZ+nxL_Bjz=oC7GlSlgue_IM|> zO~|EM#N`!aw>C=xTVhrWvYcBd!F%xG#gbbNY6BLAQ!(W%+2{`grYs&JhR@HL;Qi&1 zs?Ju*OZAjGeR0n(RC>|#vAh==qQZqq(R{3%CT-^faufttLp;kIJ%CNHR&K1L07;Rt zYU1< zVQpbrLGHmPD!$N=g%yXTTO^q(gvcXre$*TGDc2dNy#WHfOH{5S*UV4AIo@3`E2L|Y z=(jn%5GmbUD%XW;sBv0-f>>w}90l)U1;@AfikTag`#u5v-?`OYb_>To`Q71c9}n+0 zdJ%sdD4WnuUH=C0{Yb0v;+Yp03+7~<8@q#5htJ}nz{bdoVn9cJtx#USGCLYb2wqc> z6VlM+!4P^AW0sQwGSeQH?t5;1@n5?Hb4T~|^%2&~CYfr}CmN$abqn(HG5n7fz$VDV zt_@EqVdbzQRtOh~SVsk&pC#g>$Q?f0px{Od^76zwuBU~aYKR=O)c+|FX}qYA>j4%W z8BeuiFFi_<#~;(=zLojqU@B`5``riZ$_}1e z#p`JnyURL5aw%{#Fx+u{{r2i#IJ+R3l!q1W)Q9`W3?1a;PU$t1^{@%Jf90(6M%{fn zVV5Q!rN{Xqvfj9U^N1;DV8Km!ll1j7ES@Pl)o!v}Bb>x*5>IfrkgU1ITQaC(S=oy> z0D2-3W+k23r=CtjM4-1*P;_KLeckDJ{Y*fc~*_dO3?L8r!l&Xi1d&yOrr3Nx`ia`RVyO9b2z6w(c55piU@D8 ztFs;KYqW8-A5Y)ppm&w1x_9DWu~^eCuwBSn{l4&`*UDK$z?v$@U9lpEx1qpc|NA`N zbgi~A#$YPBQ)42WjDrZGhr}lnd@+i;x(+dngMrgCUK&=*{QAe7onJmJI`7fdCkQVN zYzL==fztBEnX`>6CUL)C#UeD_?z~#V7e1oRD_Ksixc0n@!_qm>@nmGCn-&$k9Aq+i zO=1U0Eu7k-=*`J^Ug_OL!L@Aa_$Tc5FPc+X`bh=xD4EPG8`D;u;0v(|5@vm9{ffpS zwWkf;%J{df?V03sdf$jq&vg_pYKe-t$6AFRGkl5K;v7 zn%B9m*Q^&?``O~|Bkg3hiM5P<3U_1T)5q&}Ge$)ry{hb~74N?`Z)ef~f-96c|gWw~lVU2rsyzzJ@J!RV-Bu?H^`2s(Xu0JHs#mBN3wdL$$Iq6 z{VL3GI@NL~uPni9?2f@qD0jA#`h#Be- zMNdcjUPm+Z&2YXT3<*&o+6fj5bTVv1Na=y|=|+j=g3-VdnVj0~H4MsErHh5QS)@UR ziTTEr>j^^VQ+rVLvnK1?Y{vzzo;7(qvJxKeD=Meoof~3N=&|e^FCns_?f&<8(|q>P z*(iUPX$c%e3c_gZRYTwz362=!!vS~TZD;c_L zF!bdfgHNz+BOq-iDBOvlBtOaE2T8Yu3kAB{<{W+9^f2EWy%I1NqapB>d-)sJ#=${U zH!+5);5i7i^stBWP@bC7^W!^IXT=mt(mi|5_XC@f>w3E$<^M8RFcaIE)2o1){j9t1 zv}t{YMAtoIWPhtydJNU0UldF>BB@#m&C5t7Sc^{1V7Cux3)ubegqD4(9~ z7T@!I!Sm@jT{WC+?b*dqw&5)loVn+X?Uv%WRfI2Pc{>T6ikvn%2)%ug#mxEXWxNg#!P{*NtAF05zcJ z{*kWn6tfEUv|&-uM@hq`Eq!t3n%(m8M(6Q$A|8HiG!{8Yf{OwiCNUceU|6KkK-w9g zYi&+p)xIugYd}R&FKp_yQ9kOp=Pv1!Iiy1B{2KOy=_%C!Tl3tTk`6 z7cnHgl^fi3bFMU`$clD78YSu9TDt;6w@o?$Ol4j)fj+gYtSr^`@RhJtwX*uNkL`CP zx121jTP(FbHO3dTRxdk%ve9sSa@ErG6~x{##w1o(0QphOf(3_-S8v35Szh*f1xX0} z=FBt-jGoPd_S|{!phCquJ!k^OQC#)KA0aDwY?-Mf?hBB3*t7!akC4;*hu^AP{QdH} zJyR5IcGtai0Sm%)OQ^~@FZg>SWw=qdf~7~#@FqM;Jl>bUJuqMN*eeqW4*BNUAaK4W3^~lCTvsoh<6Jv7K|B{ zIBX@f7Z2nu7WX;?y%degl2jx%h?%aSp3hzUs|2847(d5D0~)Uj-}TmP-CqXt6R~93 zwD=hIw>sEJ@=sgl=;o1$V74sBS0U5IEJ4#-0=xppJtuTd({B5db|VIoegJc=oPFem zOS)3lVq*{`?{%Ym)HxssawW-Ysp$MbR(7m?-ShOYXI4lUdxjzTJGsENoB=uzC%HMq z=~LZ`_e@#r-3tswYg)E-6hM#`y|EuG`44x8NKI)$1s2M40K0aKxKPn6~ zE``UiBlF1e5q#(6Go1-r?S`ScQQodhJGZ)bo!!v8teEJg#8B@tY1b8mpJMd0s~wU( zt?eFTXLK=|`Dn~sVufxVAHwtL(akJO<>Gg0)D~0zr?}?12Ar;I=j>u~$c-(gf-LJK&xwZyuVxWBlRCQIGplx| z(*<`G9z@uhe)^b+g_tr+ER^CT6myC3-1so&NTLyMZ}FxkGJ+bQ6DdJn$cSr0nnoFg z4c)Q%N7Gdvk#AZPU4+#gbjeQ)67N5~mXm+Hy>Wh=z;+|+A^c0w7M(&AK^9J%_mVJG z2z=K_|6pC3@f&c3cibKb?GC8;ck)c~zL1WWUoPr*mR2&EstSr7H3=8%``iFX!_d9S zv=e<(MRK7ND>K5dN^TH4uG0M;$lLx1*AIDz>q@5*#s(swIpAaNN=?>8<8J^kq4G%6 zn-pF}$B)|{&ZsFPUlm6h{Gh(Vp)uStR@8y?xd^fg@RRYm>(GN#3{8 zwru<>m6k{MP!CMcSWeDN>t3AHS10L<>$TOeo=3|+oj|ZFVC^(zLqfSV#ZMoC-7}Xa z01oKynh&;6R`GbtY&q1I*4A;$D3nHFBR@YPS2p-`Ckt2jWKl6nZ|wTQ^LGb0M=n!t zJh)`s%oLg)-#+`O2FT?P_3~b50o2?uWbpzGP5?k9KcyZ8PXjktX+uarSw)noIi?Cg;5H zsf1{76;Er1h2M42#!IA)-3Js-#eQ?9%p~_utXDNZl|9YNWw>5c$9uCKC=^p2zefC5MxZb zvXftt^JC>O^Wn1|tLp=St)u+&fP&6DPh5JHRGhmPYz*6sZ zTqGFvv6w3xYwaqcbh)g+yBWPvp`yrE^`(hei|cs%Q%5Ap^(dkaqua&-6sOu8W1{3A zVW7G3|Ms(tT@nK1PP^Hntc=S{r-tt~;zNhc`OVJdGv$G7eeWgwQI;QD&x~}x#Vt?c z4hw1?-Pw27D~pf}TKHP`?02}PQ-@?^wyNS`CCi31rzX-+mRW0;-be%}0YAf@esQK# zxttFm)2g}5Wzk&Ie?I}`!M+jd{c=G1<#Fp04Rtf0=IdkSyA$U+1xrA3S(!>Q?@vbi zug2$w?R8unv7}=zfz9S&)aw*s-Q_E)d*uMhBNKO*u$ z0knHLy&CwnWKWOlxf0L5+|G}{-k;OKe?4e+6zEA!ynX-I`Z`?aE$=geHw6E2OyFN$ zdx;hp6oXXfpBLyK76$xI=(#efYqxm#U*7beuJz#q3pH@<@qZw!^xq}@?~?x4N`K)` z{=4!2|MsPw3>#=mD(-3d8l%5{>7GYEhx13$B;DDzPG8_h?iPR3u%-b~klua7=Ivjc zb~PAY!(s6RV*A9VMja~QHpTx`p4}6F)>Qq6xDGOwOrT<6 z_Fi&T;)k=|zvmL$=jp7@c$$f z`Pg$pd&kB|uK+^0Ic4gvIG)FCXMU$An1J6eHshQe`5AkN6tBg`G~K&`3srJ3 zM5NoCrR!oX#`YN%`Si+K!B|iH!_98pug+bv7|1SfJX|erPZPC#Z1RNAxs{EDg=NtO z_aSmyQ%ft-35$gV76qow*S`H5W%e(50SIe7x#t1*Xm*n4-#+$#`G?ts^W4I<)h6P{ zd;GZGTsfaBAt6|8Pe|JaNUc@OL$F^zi>ud2{)nOf@zOtknm-)B#QC~prFfrt0Z!7U zD8h?+hl>67j_m2;G{RfcNTfJf?}%MQF^f+(U-8yt{Eu}}eVk)u`b6$ti0(P1 z7@iXF?-YmbnkX{k{v9ehXoTj0=ue}|`I|=rP$}B|KbTYAOzmS&1BE0@%63SBcNCkB zv-zXt{cpL#pZwK;*arb9Bx?XJn=F?BVbgw)D6#vItM3k1q&Y8|h|HcdY{=LmbjVm( zp$HO=_uk-WB;l9$Brr4d0TMOdPXtGJ7;sMb68&5#8@ z;qv!bE5!5$goUF*>G>Ue(dcysSTxO$SX8m>eLE7ko^_pd!d3crHfFQWKc7WLzo zlBa)zFM$gsXe96x5y$0@z6vWY7QK?{PCzrW49NJnQUDkMXFn^_>OYD_{b@b^xTz04 zG5iaBvsqRmQ0f9?MvC3=31J8nv~D7&2W%35Wo*V5{PdBoiwgusChRm*QrvkG2@)`c zirz>t&>+s>XoWKGSBckeKJ+&aXm4>Ces%?nqA>Daww?89;lWnhmRCaWWnk$B0Z>=C zcQGA~81lrb1{xxDfv{hJ-wA5_`DJePIZyg$UmWZ(;|nm!a$j(U86lUVj3sWo9QGP= zayQ-3j0RzhIX7N&*?Y5=AyZue6o$%&UTSKTA<#j-yQN_k@>5Fr^i{pwT>2TzcBI4Zc;w#6c{c>;Dqkic>L_P#w5~4aXc@KkA`^UjrB|=(7 z@xW0r{B$l&BK=E%x)2|hva19KR5?x;MitU(t0)9WsORkuPxk*>r2Nw=nvwe0A}~Up z;E z&t)z)P6-If_7v7L4Y>k~9OdexWc zzJdNR9H4eZkH-_jGv&HiP4LPLoE2-a`O>1*43O|83^VSlj*nf=$`uitDm3G(U<-ay|T&yIs1ighjHGo>J;JE6dsTNa|Ug zRE&Dxkd0958-H>`SL(y4%T(xFqgas9=v(#_XUGg=e%;%Gg2P_m?AK6o{1vX>sycC2 zck9sTCNn_J-;#}G&8;8^5;LlqN`p#+k+Qr4f9B zQwNp55f@H?R11k)!Vm5b_P|-E}!j?Ests+&4x5>r3dm_h);xj z7k>~hPh<<9Z)R#Pp0zZSuZ}%cS&>W$McYWvql+S6_3}%j7PdYGB6hf@bOeLr( zUTf!Et7lUR_jEgSp6HH2SM6SxK;jrb3=pkMv1=2BrV?nw=SHO<9N9f%gpC9owMvZP zX_7=Sl~fhmJ^>TXxq7+riIL@8?kz#TdPahUk0PXQjI^*Ic@vm0@|C9<&3KoDH@wAY z(otBW#rvqG7bcM$cbWE6Vyqus@f$G#I@ZIJV`r2Z%2G{tACTU+&7-Nqj+KZt&Ezw` zv<4Z1Xu%gGo+9RV0(EEfrIC>gV;s0Mq_||<8`u!Bvb?Yz^?ESebT{|cQJ@Qp=mM?= zlzNis0SgWpsn}lpSzJvRF^#a|3)@L3?xiU%?~{Q(SslD9ae9&cU8##YOgel`m}2|F2tMRaLulNB5;S(-B-kI`-ac4`-Y$8nlMsH z{7ijFEh!W?LX{lk0&T7Mb1g=7P@C3QH%8qw+`JNn)pV!8D6CCii!T9vTfC3On9a4& zHkPbAZz$TrNg*A@zddpeW#)}oZLt$K;0w+5tL%zZ)vZywxA+h>eH?gBwD@`c=A(d> z9^qfkMrTUoK;YLSc2@kGcy1j2J!2S;vB@GMfr(GRi0+{o#GIc)K-poA`L!}*=NN0w zW5P!wi93 zBr+GG@$UJXsL$V4u_sI2%`LWKbTCo+7){2hk<>XheKAsN_u|3U_S9-RTe_)PbL#9`i(kNAew?X zL6?^rhjI4eb#q16soS4{oaXYR55d2YCPM)CpXkeCqt%BcSx-- z6a~{PMv9hIn`=lbrO4#D)~Y40sGqu)>o_Iu&;#!{`#7yYd2F;nmpGU4qn=aN&WhpN z^wr7%Ud`NRf11Vd&$(1c=Y^(95msI$ci|?|j3yHgKYcM~s~oC|J`qukalfro^Fii9 zCCkL}xCE+jQzt_WFY|SEH8yXX0zkO)!}&eXF^5)MnXw>*wzRa=_=F|D%y^wnRD)oZmL^d~?~PVlj0F1u1y|=mJOPn{O{b-o zMk4vm+xc$WaT~I#R876HrO{s>!|}o1;QgkIMONx}yS=-!0n0BJxu8sCn33z#%YdBp zI*EkPI>=72MOTz1m&N9AS1T-59nOq8pHA>yfsKh?8}%!868fq%LV2@23jv=ybl;p< z!W8KaIg~j`w&WzH{W8`NWYa0Na+mrMw=bKtZ2S1CXN`HeX&7jR^?kh8zHB@kJXaQG z;?!QCRRQ)+Wmy?0GgeXuFI?BqC=W9aU|v_sW42_{3D4I8L+04Wr8Sw3<8S`5Q26~q zA`xTAF#%Hr30&$Gw)xw3zQZl%uS#XPG9%PEdQ*d^C;XHwsXdA1r;c}_5Jd}NU!?_^ zT$McCvf?d*M`h1*-rmfQ-pg)`fE8CS?n-8XX2eI%U*G>SXtg#`Man%iXHQ```po%H-A*?S$pirrvipj)elus{)`|UH3+pk(l@uzTdJM9yjuR)pMX%R?f;Dt;V$K zt(K)(bGTi+n(Jln4SISN>NX3oV8$%bdE2`d*7J%V)fn`K)GAoWd)3tH?^i3tbV*%z zS^C}{U-UO6pC7}@d+iUjNpI2#`EJN%t1{p)881u4Pj{)zcUW4_FUQ)>cL%oc2^xy$ zY6}(;gqO0+Ic;GMS64zbO$OU%9+b70>;*0B-g=bkdY|l9@2a10Bb%E~JTIOZpVoNy zXm>f8ikSw8w}rG;L`;V?DYqx%qqq46rUaRZoNldyQ1nXSFH6q_6`%L^{y`US zUe;N2al1_u_%M3*jzs_sI^%9ZvL9)&Q@z+=`&LWIs>N=z6gv$)PUKh7rpH*1N?mf% z(di%DPa@x&i==M78az^RNTT>voh$MoQ-pd#$-R=`Wi~GNtmPn}sPU;b;`l{Bs%hC; z9UjXc+XLXk+rU?vEVOfjlAhTDDRu67d3kRc9DAHSR^M`|RVdTSXqNqwukc>&!y7F# zVcZDR6C4Id$6W8TQ;oMlP9CdsOv9gsGeDB~I`KNABYU5iC3#m$`4V0Rg=jL&r3VvUfT)&oG{zOZrO;XR9xMCCNzsnlO0H(UuKokbKuSA)m|*E}StgFd1B)7g`r z?yBcYsx}f;%^Y@WI@OSez(bv(+O0ZOC)L(45u(PcO>e}=Bx zK;cJSdkF^a^46dJdkbTgUqOP$kb86WgPj*f#?aUuw z5$ykQh~nR~xVPDBoj>-MHg`xbyDUN~bXKED(_ZDl&fBHZ#H4EMSZ zUKO&%;><13JLo)fpYORsIB0#KnY>2pxR=m16nv7cjlHe!==DCdojCfJZ~g41Sv+gn zOa!IHEhqX)g6>tTx??9k4~1~hPmnr!joooBA%CC~HegyqP?)W#rTNRqRY%uzA|j^f zF*4dCTC4DM>DkFr`-2xi${=yo{hPrP2LMB(Nzo?>*wx9x8Y5^|SWD0v2EJKbu>sOHTF0&`v8YX+`5ms<`7120lU@mn zZ+5-f62>vxz4Fyr@%7C~fU|lH3PK@ds~WsC)+rA^Tcu#{lH-0@3}2#Z5k2+jc_VFP4Sq9C{0+V{_#k%S=@^LobKuO|T@+MT8c;f>{yC#*H1-?r${7xMh)fJ9GFs z>>60h=kp#q%XwpL_HngT(%B(&Ee9K zCiumIy=z=x=#BVm zL4wJj?o0g;u!Xl+OnS@3t+F{PY7GiHfir%4J(biCjFNL%-43d;h0<@ zKfjldyX4QFU*rXNilya`_b=c9I(qL$xYX63dcS`SB;vULNZ$&K!+??{MGF1chVYjh zScwfhg}byxz-M(D@ZvE7jFYr~4kkao`v+FAicSUtSUyFP;Kf(m)ZAr$`uyFO-}6B^ zM#V2Sybo3&`3~ihjx!$%Y}kP0q0-pAaPez*9=RUx7P#llT+cd-5)H@I8K1kM(i!y-&e9SAFU0h>78F&(_l1Y;ipMmFH( zh+lW?#yh{q)5t{SsZ!SW5_s)uSzK(7GmAC$)0d~J%UqVInq)5$uNMYyE!W($x+bQz|ZVUQ5iQ2CgVYCFgWE7ogd< zKU(wrf3-l7G#oBfcEj(+)gjA!x+X=7*uVY8Xd*5C@Cg?!)e);k{jsz0!E6Ur%x3?Mba5clBwd++o6<9_A6f86=wJo7xWX79DvT6@Lk?6VHd zvrTA_+vd=qKguVccK4xOREOPq=pvNqCiUP_={NSz0>dtL!qBfOA{{QQdBb0N+u(xo z1Mv)IDVz@)ssraoTin}fcy2x>40|n-l)>aRX-VHRKFd*Xi$tNn-(1V^_>&tmJKpqk zqYnQzLSh0rw|_*Q4LP?cx=yS+&B#jQ3Eg;x@$HL@Oum0;<^;qctdfM#GYC zaYjql0wV5XF1D0OHYk_XZhdP|DW(P{=~m{TW2yYJ(!mMl*?5(f}vuWAq z@w_cHRt`(z%FF6j#*~jQFI(E=?~$c)YCm6YFwMy^t(SUek$yT$*;`@WNidTUTb(ag zalFUdkhfF`bX57QoiU{$zc-XU^t}Y!*Hed}5Z>JnsN8UvJt&?y>UZ`^v^?q@%rPlm z-S13YZw_I3m|!>W{{5rE%vaxsdi9BF9I8EPIlp3yg}p$Ri)%5?LvX#X+PP)?>yi2n z&GoI-8_A4e#8KKrq4H^=GEet9>+7_ptqXL`tHYXQRT%ozx-8WARSFW=Qga;mg=$2^ zM+;)#ul~?tvAs^`p+I8cpC>bZ!rI5M@BW#Q>BtB2}i|^itd<+ZLHk5&vB)uD1BekSp)Kof}33 z^DDkM5h5&f(fOHNxR^tJD^_4jDHI_X+pwW=*q(fLv#e8|g`7(=*TB!hn7yBGQ9zXZnJ7pafHJZ}O!N#&*wZ`=~6GTHBZl(EjkxM`EUT=R) z_$IlcjlVp+1ryU?4m`}P~1 zTrR1{7s-P#9AnuK_3x?;zg6wq?P=$s&+a=j4r87@6^hh;>H=F1)+U>ED;YM?{+)Sa zsPt7wK5n77V(paSPYjwqyI;TK-JM!eGJ8&(ds8RNG%!O|CR<3TNIlKhiKK`yq!jcx z>jYOAUcIpz|At1-_l(<0*W7c}^BvI;VIPv1m zo1i^~6Ns{fE{BSZ`Fe)yCMBWqhXVwREN$oA!Dv%z({!Z|;p8tg`UXKZwx!~kgU1JY zBQ)b)AV)=#)e#nneHUR+jN;asRI$>xtfP$=gJ0_M8CGn@NnkM{m22}UV;l)wRJ0l5 zSf!|T%F>DYgPz8{&$ zLS0qR<;;84^@;jj7246}0}EOaoWO;X3y}#>z(Z891>&ue;R|@{iHza8FOPD_|p$vA0a9Sh<&E*atH(56Z`%JioEhDy&P z$K+oM@qWGeV-==fk`~(x2&6L%=Gqko)zF4kj!p(A*7qgO(fdvl^){w{i!{G9;^hdc zy&sIY=I@G5GdpMvOVy(zU4gs1OcE#k8n-d)?0!`f-@wFu=%$l(ehsBApBC1;QFpY^ z{jO%q!fI8+*c%fObiaVRu5=RzG@Z6}LLmYP@?_pDnWs<|%YxQg9vwRI!(J3`yX0VPk|`2WSgVr0Eh_VTH;T^w?AI?%j$UGBQ=K>SH2rHasZKad?!t8egt$r6 zZkp*laa>iX*dX(*=bd=Y;{{Zu5}Hf;)%vBL;@`QL!Un>#V&ZGvjdK#S3yFfSz#L`b^OuzJ(D9L*PU&@K^3#28UKg=Y8<50`dQ*k6B zTEDv!9}Df0G=5f9ZW5j%85m_@yEZ9cRdWJE%Ml}T_0~nL+Jo7GKVlG#YSo;C?4&Ej zhS7FHGB(t;1DLYr=Bu4P#i?_TMIAm3XvZ%X!THABADk#2^BgWzt4qGX8*@t)Eco>3 zDH1M@q9av9k8o{PKGkurs&$da+4o_^;Gfh?if?PpY>Mfjjwg@_TGBU#|IsEMZMI+` zbFkIxzHX*=)|q&iibGPri~};?zSsqoK9~)2!-_QYK^Dtz##B;#iiFjObHk^!QF4Sc zN!+tZ{bj;O)wZ!khRo&H{_K#c?I8^tu$`(XTqA}$6VNXU^hBrN&%BJStY{!pB-TQ2 zAzdTu*wy-JY`sQP2sF>ry6!xi*bIRSFDK7ThvxR+n-VbwKZ(WE{n$K3NRXQ@gwjzy z+J(t56U+wrDV)JBY!rjDxE!iZm?TjVK`4GsXWAN`UOyqC(Md;6UY=5$9Mr6bjBmaB zyMwEjdHCfNNxV*D1!50&?Qjui=xEh$%VK#oNQ^7Scqd=sN<9Ks(GGkGhvrm5`6Nh!f0J1R`~&~7Fp0$zeI75 z#xRtd2!b`6CtMoYQVDuHr18-XofiWnB+dTM9{1K2`zJ}3JOC*IiEixx-^12g7e4|Z zU5$$7T^)1MSWvT1v|tsP26y7Bw!jl$wY3H&6?hpEAl)ckq;tacDc&yVxi9`lvy;LV?HOC7m&VEp02E7VV z&*&+Fun^H!qMa|L;4YR-Co^PlESNz|F^JE~5GQE#zL3TdBmQSu2kkb%4{U2@)|DE5 zEjz+F^v4R@Z&8hR=p#~%TC_Zr13gv|GEJfYytCjsqOw^xKrD5>$J^*^iogW@4xmb{ zlAnYfLbyjQ=vzE!-P$p{hJ6&s6G!A3yA|y=Lh`K`Jxgt|Qix4M!)vL}JS3XhgOLO$ zV-O;U7c$O~<0ShrAr6;bwr}3{MoT z$~ph$j|i)X~VY zuY^?%J|LQvx!=BBVj81uh=o5Y)b>}8C`+LX*R*9dI1wP?-V@li1?N~V#GF~?mR>QH z#zS-ndBuj@+G2jC75A~D&^J9TqW{Mn;*Uj#NtR%M%$))PxN6=Hz!}ryDZc+k$4{fw z((SS2mdblGvQ5faQ#_Z%4&++ZN{#hST4b(nU^A?+fs2M|L;v`TNU|x;N}F+*go_AR z1P39!aArus*Ugh}i)^7Py5ox!o|HS*DWs8u4s%CEFPJ?3d|sIBopxU&`d2A0%i z*a9`%(KUSpV}V`EgJGuwJ9PSu<`HeW;f#a{EHY;U;a_{O7W+T$<7AzyrYHP(0?%DG zd^{de=SPqPHd*m(DXgW8yN%Tg!&$Gbi#AP`bjLz?E1V86XUqyz8OT~YyH#>-oUXUA z=G%jXzqk0hpv`hJVPtii!DpjDrv| zqDIGJ%n_MZFK5c3U^g_@N~>M{94?!D@JcQE@+cJ3=&|rd;m4Ry?HJ8@0NMa85j(pE z*;{{lI^=4K9hs>7&7QENY%aKQcPJ4o1dra#8fH?d= zb#=U?nL?qT_uJdKks0tL6LZ)_rT&H#Kvi_R<7wTpLw&h7PzyF&~oAP{Xo`7q33 zP??kOtF9W_q9$1TN4O(r<*s4q{Kc51)dFI`RY{jEg>dX9ORPd!JV~&kdc0c}oA76K zDfH!_eSq3c!S5j|5WUhN5~6j4$hSo!y{ve27zt3(ibKrkJpOnSyL?oj2+VTmj5)F| zbwz4s6KZ0W-g`PKclbPa>ky6pB$@oEztpZ$CK=XeEKPVE^FKP&1+kSw&q2slT6{NuYGy1$*34OFZC}^^P6%BGoc*5)Dm6b34YuS0di;m!gXWeNkKo zkRxR{>)0Fw@}hL~{nqegEb~+%_W)Z7_W&Lf{?i_m7eIZM0KMRM%+(x)?Hfu*2RA+S zGN#B&_TQ%#rdQf1I@Ew|jZgS9>#DxLMV<672Q)$$M2GcDi3&j6bjr?%7DD??iOc6m z3vQbkto`&}B`g707aj5qu;BA|xaUs~cLZ`ol7!`rg@q3b4n8=U#kbM|KH}FU?rq&!U9u#L8)`nq%w!GI!{F1}; z=WH&lel>^WDIU^*3*tiT&^Vl0MM+17)SiFnRC{43NEtP6G*qmf8)g2rZLSIM{QDZi z=jdjq9|on(XRZiLEpZ!nI!OuBw``;yIgfj{BRLdz5$3CK7JQZ_Ix|ohZhb${_Zh;t zcMQ`ge#*0gw8V$p03KfOIQ-JJFJh`yTR=pFulW1JYhT4n%OEG$GDH9U5jW9z`|qsq zQoqan+)YdB*%KZviYf7Bmz~OwyyF3CPhKm_ld$3AdyYB)XoDU+5agJmUM&=x%4#z3 zxlY`maogjRw7SDJuz^E#cyXWi5pWcHtgr=sY_020e5?lNy;U}yvp)L_eBmvuY06=H#3@lL{&yAE@+V=aeTmevJ{yK63$p;zkNWO0bTaRd^OxQXex84%4<(8`TICJFXMGb6K z3A7m(0MOY1-G<@Xx7Qg*b}uaS={>gHH}6$`_Pcono_i7|fPx#<5c!Mq)wK??g`Q|% zqwvB-WGhv4p7`{ZCVl}x_RS%|9GE_|7;uj*``TO+ z6XW5FjY{g@wTD5~=*B%k<%^x;#ds~v>GP9|Hw#&BrA6oj?kEI9BulVCU)_Guoexyu zS4$U?eJGTj9+p7|9y~EMleBAFBzfccyyf?SH4H+=?@;JYR=K2wSEDRY;N5hR;5t?& zKk5j+HeO^bSfsb|j!Q!s7m~82J`{k1H8NQcH@V{zwv_RsM zD{&W9r|sFgSYDHWvrJVL_v=at(o7;^$BU1g8$zN_K6lSpFAN!zy+ONyQoSq}G&w(w z7cg08aljMd-m@XEdMPkLT{Y&X^kT(k(Xi_@Tca;n)Jmb2Dd+wJ{@BB%>Y$>0(ER3H zKh*gNSEQZ+haRcv`egRg-)n+Rs%r+ESwxD=k@Fd|cMV zefGIY7+UylDdU>A_{~RVn-cm{Rw5iBGkE4F`?+b8p_<{Ks!x46W9SvB$eRE2Ew2Br z50)Qd{_HdKx7KM>OdG9#gPE^YQWndrs)%tPX#qnkH4qjbcR} z_0_0EwZG2X;=0&$2lHx^%mByPGI#DMafl+xE?9}Sq7#MvEqIzP+Y^9oO6cQtu6C~` zcmw(Sh~uqImz`C8>ubYB-Y-PAz?mk(v{pWynzG_unOuDnDAvrJ;(Yf&a8I1+7edLj zJ`8}r*$o)5(I1BQJht!}V<}vf>R9=-;b5;+kTRUCB%7%UGp^n?v+wpHjIq3qSK~qQ zkxExqR!8&>y(h03`TTw5=Qz{lCk@M#gX&tTu7C>(`@JeB&%W(Sm07jkk|f^?NWl%&;5g4%-zhJOZQW8#O`Md2d;UIXAuE=Mv+a<4|7N#95w z1Q|-3Q!%v%kJOE^{S89@Q~u`NYY#qj=bVotpdlqljsy-B{4f9Zp&D9s${Sp!4;k=Pc`8Mud3+m7Y2G^9JvcdI9B>|cc9_IpW|L&M*g$)?oJp%_CDESfv1LW@?r}Ve` z%(pDiD53&{+kPuG_!w~jm&(0kTzAZZ;h%lG9Cy}v!uzz3098xrHh}IDTNxoh=p5-! zAw^SlABA3OSK;6;_2BCRgdMvsc7hoGx_~fxLhA1l0ET}wz#6wJ={(l`1SvpKIm#R4 zch19kJI}hD9W{n79bh^M7|H#Ak61L`lA3_&V1#wIfobfv0a5FUSe5wS#a)8Ias?{A z2yR$(Rh2`6fw!n6O#8yzc!Tt8i>;vd)6b5{9mT z&sg-i$BF>lGItJfZFswk%#ZY@UA<5%+^hDNE}|IzrIL}RIqLzU zRsjb%_GWh}-dhqETX)hBzya&bR<-36L=!q~!}jqd+t{K6hapG3ZA@xmhaF`f@6xN6 zxlccNxbh5F!a>6O%9^XpXcq?zf4{aU9jl(f;{L$SVmrJ$d1+%LtlMkH@W>k{X6Tt) zf;AZ1CS%h^&7oX4mC`kfXbf1}rohAQVg=)+CJOzDu=#p$Ld*P66}kHpf}ZC-&rC1E z&1~~IYn55(&>`DccNs|ugHIVI=*jGmAIs5V)56h0@(Ya^T6n0WCf13$y8MM>F*`&- z)_?u#z3ScT%E8AdH1xj;6`X|JDaG6E4|MtEremi< z7WDa#$TRT)2Zsf@kiOG&fl%U8c1ukh>63Ctdi1Zse3Wm!O#rJ0-5|e zvoOggx1mBRPW-M=@rM^0_FL+2M$1h9j);FXCK}+#H@#G*e8yeM{KF|e@E8Pr$10B< z;eSSs1$gUB<(yY{I;~sQF|YyZH@`^hF#j|1fZJ&Jb&UBgpZq6O_}@~OeRwdB@}H3d zu}S)g+BV@|h4*hu>bRxWe1>LoXBPBFC;z8rF3e%KKQBy68a-Zc@^@VG-?o>aNAoKE enf=+G*0~pwQ9};C^kA(lJAqbb~O! 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 z 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 K`}(|f`~MpUoHe!p literal 0 HcmV?d00001 diff --git a/docs/user/security/images/tutorial-secure-access-example-1-user.png b/docs/user/security/images/tutorial-secure-access-example-1-user.png new file mode 100644 index 0000000000000000000000000000000000000000..8df26cf28ef1624d9d23b37c696a2b13df851162 GIT binary patch literal 219096 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⋘we$7sc9eHy}Je=$N}`~jd-|{17xj4iMaIbq%OS{ToDwC*m=UFr#Zo7d<7Kt zt^AYe5v?XHhg(_(2nNZ$p@`w(;X`KL?8MJfS4d0w6yqo(DIhCzxw*MYIS8*z-t3%W zxFVSCbxfDlAQh5LK5KOR)lELnig5tPBZl26LJ=bIsielP6!J>Ig*-zgWajIE)hZFa zahW!NZh0einsY)CRgO?-SI7$*NXBt`FNv1~A{U@H?dFLU?Mn8DA|-I0Gfn!CA>eig z%AWw@?7I=$PnsWM_{slWDjrVmIHt=cqY6ZcPKU9k?G9DMGPwh!wpXJN_UHtHKN_BK zCfj>xfV6yvEHv}fN7>KS&7nk zw#2QI-@#_vi32ptKm<;3PV+`6j$a3wMdRU59kgq!5Q%{KZe#e~ z+5@aYFxu?_Y{8BSfHD*JFqWs^QfDXDNRp^+pBHF$t^*i&XmBtY4~iGB#gvdr*-TNN z&aU(}xbF;2Nj595=t;=%mS_uRAk8sRaDP9i?i`)FWWBGJ%Prjn8cR7fs1b(1s%!dJ zRadK3J$KL)0HD+(4!JJHu|PV~u6lCy9v3A_?`u)5Cg3I@y-fG{rh(8Qc8QU+#O8_O zormgxXgeLpbT%ehX+TPDM`N?@Wd``JW8OndfTh(?nL!=8b- z;<0V#GmDFPvuUw*J3*wy&8A6mQ?BCtd?~9T7j+|bO-&d8-n14X7C z^wV+YuH9|rzukA~cAu8gl`~f-X@L|8rw!<`RYk?c z6N6loZEZ!xMc*Lod1zJ9Z5^f|ZdlqZU6-D=jyhLJN{~FsN_(=j3%-pK(t%G;5-*1HNOtaFxc+C?Q8DalbmcFe(_*e%Js5)Z|!mi49{r-w^{g_ zG8fU&4o8pNAw{5X6;6hma}`%sifxQyRT)4N09~!(>}=L89RNRie0ebNa&Y&SJL+2= z-B%g@#vMKPF>coO&Dj>J1%Kt;E94O6UBQid5(1)rl_C&O0=9wRoj~vC=n~x?9-dIO zp8f7)6uC1bc!q>}QnCl-Nz|&}x868~BS|Au?;gL!A!FyvP#G5_G-#uK zCSq(kS?+Fhvheir41ViZS7~dE#MGrE^8o)IT)6HofW4C$g`GJ5to|hjT*cu#Do{0n9oc69*KQpj;kve>Kq1V6jXN72$~5RM z5Uynp8RZn{GkcXv?9A!xAuW3@5^V1?8O;t587x1om1nedd9iTn_AYC+CuAtg#A9cU zk0e-3T~<=paJRxzVebUl* z<1TZ2xZ87HUsulCI>?FxvBG9^#1pmm*=k8H0>|N zEG;cr%6Yschdf&x;d^tZ=H`C({(i5_#@z!6oGWHyGTCgzFE{1x0_;&_ibu$@|5A#~ z!D`6MF&@~jZ#-7rYwlZjU0w4+c&>T&X?h0i{Cu$QFXuA)$;A(eJ_dZ;ukFKKiRqU+ z4Lj@h$m7Ojr-J+gbc*YrBZAf#IXT3;&TiR0$?9DFMw#!>nD3r7Rfk|mng5V`8-?B{ zr>xTV*|ZsR$zIuc-K{Z)ti{554iCqX zG6hT9-NWSdR18*Ee%H(VFeIs+lGS|B!dGLWldtrG*#fygU&*JSQVN@ua5Nh2zMSFP zQCvNBSz^Y+xq*O{;qF@r5$iu iq9@HIt%7$A=jf@{jU@$rEE zkL;#AruMPheKLHUOhuxObFC5XXm5#DX!XoF-^C-^puJhO#PE)c zNlivRo188bz%7^XERhN^kU0J`kU*@i45khwmGi2QMyi8y~Oqg+wUR%amsq@7b;7 zBz0PNnjQwEam>NZ-1soOmyBt$<+i&k%0}E^tZ@okcGf|~RJSC(Mz2t{>4wxjDo$c* zm&1X>Y0tZ+w=;wdPBJJ1U}s*`l9dU0_qSmoS5A+Kw8YaBCE1vGjXaZtGez zn=84#`QbfW@u9DT#)(!6`boj1blX@=T~}3(;@k%ASa~Sk)>lG(#4vj zqq+a)TvTrqBscTMu&G;m+n>PN=lJss>V++e<7sY<%$gv=Q~~3DopZYi z&6C|nnnRzBEC@WW$h8uylB@y*kZ-KSbK#2P_xJ=jJ1+a$_-G^r*8(ig8EC~+tVKHx zVLbt@>NWJiL)#+l+itF=^sn(_YvmvdD`mMiVU|>hR7iuoW5R{ zHeWpBH40-?FH|pj{U_)%*!Tps(OC*ggRU_@g`y<6MH&yoPs zwlj4r4Reuvwj)!x)m#TX{pH8^fCwbJ-OWMt&l(axmp;}jj^D~Vx)m$Cn(TTPR{{xJ zOp4m>l`C|*iSDlG{U&HJTA$|?GIWLN_{!0Y5t4speM52l;eKL}UCQfQSK@s(ue|73 z36ZMkX2+K7ADDYL=fJ_`>umtfw{=`KU6s2i)is^1-!Y9GyXG@xpQls&TBi^I@0FEK zR|b2Jmw2Y8{#+OW>NNmy^UAET>=qjv8%?1k!1yEziHeHfwN-ZNJmy7rStLPME(e#1 z1<99*v9hk!8SDniZ7RXwnT9K1C=KAx%o#lIH;n{fc_Uc%En!phEEAI76$ zLq4!0R>ox{r;&%26SnujJh-QlSd$ndzjdP?(S(Uq&B)(B?Dm zuP^Z!>MXC9!yTR}Lv(ruaf2~GV_h)^xbbx1tBF00rLRJDR@N0o?C|ceUJnq_DAJKwHoZ`F0=Y8G*rb zR}VWBj!Y|2R&_rY7~`U7#Z5}P8nXgcS4?bsD(ewA)s~`)*jO3Q(2kYdw306LNmO0D zbzO8Y4(cL;d+fL;&ctoXn+O)Kg2MKG+Quyxex34};9xGba4A!rUt+H} z3e`MO;}+sD7CDl;>{^X3wT&4vj(T-FE;>%(KoY>UwUSGtj0FOL$*zYxuj5*yZ}%pL zv=8VWU&A!4VGi97#C+DTaW99(zJF#gTfAMhTUr$fVDGx`vL>)F){nCfKT$x=2sD^v zJ3U#f5*0l5TaDoEa?34<@tt%xUa#3MVJ;RD=gP_!>+qG00FS&oY#}q;XGmk_5y5TK`ZD&R zQNd5KqFSlkRHuTy^@={5EpDWR@FtLwd3Ln1X0Up8%LgWH-20Nns4LAKD~D+n2yUbG zo$+?=R+tHD({|qmRkxQ`2_P3BB27yLd~@tG$%PAbUJ3A+sY6z?wnp4hv8I)K%kGG! z>3I)cjLh=nwk?uC&+p1BRkG+Nn+)R?G+VS2qJR*g6@OK0HE+|b_egX^PLgH8gm9ev zfk{zi@2M$lPCFAg2$Pa`?|?I8?%Uos-4PIEEhqtAEVsBYZ@afSn^Aw2a-eF$dO30k zk2>_TTc@yqpD7lLhfm|55JEUL1uN~kvkK3SOinVb%nZnEG^Ei7`}p6Y{bS<(IsV-5 zxB{-cuTfiIMIpQfFrLu5Z|&|o4_+7-&G`TsXS-nac-@@yj87NsR*##2xqJ7cG`EYs zGoEf^!hz^ov-PG40dB&rR-fhwo+Jcw*5TIRYnv(WVO~HCM>wQaET=%Vo`%`->wzOb zy`l;q9PVcn;BODSkB09pKf9=oUslM9Ff=~a$Qg-p$nqCy5=SHKJBpBB`sTj8=%iBA zmlUOJEk}QEiH+Xb$ex75CmWVaCTvq7Hw^36WU(Q~cq{(uX5KCA#D*7!H{A-hqFT0I zJ|mc(_sr>dL)}*I0=hsr$&lci*gpQJI13ajc>wEm2t^=VrW>|HD(18-t@jt_-k<3! zmdr&;I|Bsws&3x#{-C21pi^uz=ms-$Z|{*s(TXVX$%l=SE3Nb81Lb(crKME`jQn1r zz`ZW|T>H~e)jXL&yu^e)GVNaM$l=!NKCdfxj4Drl>Y&n$d4r92^))($>#(x6N2I%Pdz3K)fR+Bv05#WkV)TX z0Mw%b2+U??-NMEzzY@ZbSXQbo{_WzLgU&7)3Hq=80QpkUd+1qIcHm?<;}DSp&%ZD! zwf_B?O_!DHgI#&Z=W1kyi-4$T)A}fD*0EZ3*EM+K+wfRsW3U|2UzA_N1No2r7JIki zI8Rp4`EAfA^)cjw;WAVtUu&QEv=H3Nx;AnMRlc=|y|s|cn`Sufirj5C@tY0frTvB@ zELV=q1dRz>TC4$LsD7Q5aQj0bS_cwse~XAw zk$P?O268R{JHY{gOt!I@U0+HG%ye`uF-Hs5&r;CKGqJnWX!wkydcx!)m|HQKLpW07NjLBcm;g z>()2ql(BApK8XsSDU~iMJw;?POafMNI;Sx)678xqjB=ZwpSdqv_!<{g8DVc^NFUse z7th)EKG;bZ_(GQ*0|f0+`w_W&)A@Nkg{4(aMGe0q%YNPCYya8*q0?O#$RcE=~!GW^&RA*z35o3x@(6!X3j%pmiF6P2Z1x*14v+{(C z>S=n1G@NF?BOc`9ZjA&a*5YdBvKi@K)aS3R+ErwOa$1KjAsvY7$~Du_?pRU}k3$*%M%j=%X~TsZU)D3}E1+8g*qLw7H5EDyP!^gw@Z|o(M%qpUuv|<_*k$YKbe5d=_#r zAU40FkO6krs_gB!94HH`!yYidu=vXvzlIO57b=d=$0?jsFm-N>?89{R0wpFqrd~n( z!1Oq*A61WY;DUZ41pKN_IZqB*3D(a+Z1*CCbYxfF5LwTFU)1&;mwkTTDO(ieq2$v& z?n-e7V0seA%m@e2C<0oA{ZVCr^a23MNBeyaHbX-pdfq+?N2AKZ+h1Q9b|kWY8tAQW zGc>j`E0LKw`q_f(`1s%hjqL$%Ja*inRjO-Y-Av+V(|m zok@M|O7iRG6rnj{Rj>7?Dq9gza`RI`IRcSWw z!dUoaasgTnVEOVRH)gVcl7$VBPqE}^sR6!^m}nT-7mfRT%Sr0U3?x*|eFFM5>gr9w zz1v@?I3tPNe7m{7x3BWOaaj2h+g8$mZddi+nOf40uY4_liHKw!dUBFy88C_FpEv$A z>xb$@M+D(Qhp}2kGaH!~uP*2qcDI|uG~&nwZrN3Il>{0z;$~lPTtXhILMro`&Spca z_Tlb0IUGDVF4N!%y8=w9VRzWfej~Bjz9pQt3uhdNp__1HN6u7xY_1#u`=Dth#u4k= zdTJq5sDfa%kbT3$pRNFkQkcf!>TQXYg{9TlT%ZHn#2LLizr~ZuFLT4&i!QryZw~pM zyIRG$7R~P2b5UPg%&->Yx0;`48zVL%Fp(t+llwqWu4I3PW zQ;rliS9r1><#FS!YjYe~!H+`|#DOXn-Jh#iih?HrH~^F?mzwL=+}>CzeHw2_2HgK# zxu#%AU4y-*rt>AA)>m6e$aF(A{1s+@a}+=CJfLGHQYA;O{b^8j2Egb2#}uSTc=$;riS?IHO1A$mHnT|j2TB*;GrC>u%M z?3G_`5J0!lzGhU{#QE>%EYn=6o5Mfqc(#}%ha4sVw8U*X`Gw8M7Kw4kXOdfcww9C$fm51CN_RyD+J{qL-Vo@v4`P5+zW77&#go*H~X)^j&-@QWJoP1fAK2?Jp1ay2fP4oosf8=e4kcM=AD8ejAO) z?c03{oJ4Y`2dB=Qez|62+ErOP_@cU|paDqeO?x&@V>Yc4cJR7cCP!%476`p~bjU+u zWE%KXK9S;Zcnj9hz8ZGa2-~jTLuv}}rThBEE4knaN4~EL?&qMN(aXQg%Q{jse>{8K zCN^R@GR18%&P$29%!YqlR1I6~G$)q1(!H9?%63qi-nG8NLKk3T70y!%_;t^+Uj+&! z5Wj;Z&claedj~}o?Lg$qq^C2&<5^~EJh{+M&j>`$pzA}n;srWZ+%kA`dZgEWCN%Xa z9Lpa0jc3h|&ff^@xpyka{a0F}PaIQjR}~W(VOV6Q)FcHIqn$W}?KPaoTVn##Qd55= z<#CN?_)alWUG`ER3aN;b`=yAP+2bFx-3G{2(hXlW9?q)*Eni__<_p-hnKo!x=oC(B z_eEA{Rofm&$72uH+*9F__w2pM8GQI)=##FveAw7!*w3bf96`aly@XMG zHU5z@FJ@qOKub=$;n!**bBFhcDbU&VR82DkkDsy_hMLi6_6W6{b)OQmrFqvN`dH|& zF8B*?OxMxFFw2WZwa_FCfQ~XH^S;kDZ1-lIc_G%(C5SvvAH!khesOet)_2-nlfUNk z;TQxKGJ*DOg_{xTvWrm~G;@vnOKD=qGA7Q&S*=;RGC5r!%KrsvwG4DWaZdZ$njg9h z^b{JAugy-b`0Uj#r=Kem9X@(H}m|WBDzZiB?k10ibqHII^>)%WZ5MkNWa4?f)MR47K22U278mDK_ zh8uXcGe%-sNJkR$(^c&d>x+y#BY1#x#ox#i4ihP@$95(|a?e?~UW*?NQ=#}HS@c~Q zFrO<7>YAQcK@V!XTm##o)l>Z~xAgFv2-$^j_7bbDr$<1O9u=l`#BDx7Q?PVzJ<})i zC{KSrPr;&MqU*?`-PHa2mlxg>#+tST=~w{27@e&&q{+^4AXaepxvx0;TZ-q_D}qjgc(f;!tDh#LD zu~T8W^1!ywL~v=1O}C+ahrw#iV(yyFvIX|z1@QtP|G1N%XuR(prvzRkhftu6zvY_G z{GFKAVj|H|peo1oK#bUg%inY6PYM|s<0gR|#6ozPmEE|##BHv1OG zv0y!h4T-=F#u4*Ci{ZhwV44pZz8KT3#tm5By4*=rC+g>)X;vpDpt!6Aw65qJ5;kxh z7acODc!p5e{i*4)sVXxyU=x84J`#UKlWkAm2=H&Vcn;r)>KPc1^J>4mp~}Q^H8R32 z$hM?lL_1wlSVw9XA&J?0T@c%IDw_)>tj76@p0csA7;Y)aZlg*-vz8Hl|e(Kuu_3Vgkorw z9X8AXf}))kVTEJriWFGI+6*=)KyLo_^8RLxwjieMHru^o6+>iEIhj%7-2t*&{ zYPoT~q6fR{Q4NAvJ)UjjP0j6uRT?Pq*XA?+QHBrIfyOY}Sw*n;fIitu<%lIvYUt=- zcZ&vIQAaU*s|Hpv*eYzYJv_x0sG0 z*cnKcEaT?5fSm%4F-IlTjhNoF7`ozt;H&GhV#^!LB!t^HfHg8mVeN>S{$Xq`M&6#fVn{?ceCpvVra z9_0N66%yy|^jow;OD|z0D#(9h7|%B(9RGe6z#oSF$4LG$lK)Yc|Bp42e+=WlL&X0? zkN@kV$3KSgk74`=kG}fXtaD(sup=vmoM2_RlLz4@ko?gB8C~vRt3r3~A4@0D8=cIS%a)ukD+p zA<|XT-&j9$x!R4iC!IVb1Ddc-qE0=o^Jn@WvBJ+}TUTWN3z9HZa>8$hHaC0UWV;@CEK1v& zTf;fQV|=0`1PXL!r3nzXHC>Po@&g`-)E+Cd!A9Jub_CNDY&1xBKY$1a?0jq{%=j-) z?QOQupIKgc2$UY8h?_;l|J+ye8^R3={04z|mlX25@>>h~#EoUKWwx9vzr>TwgYF#u zR8x4F=Gw$vb+n7+Ce&|KX|7i;yM|Tuh|h>%nwF=V{iSQxdd+M?_m>4Bo}}dsif8~w z0!^ZLU{_a%Hn3gP4N1`XrgcHeBR64t#lx_TxM9l#*id29xH}v}$(mf=Vj?l^r3q{} zL%lWKqOuP~5U>hDy;8Wtxspi<0XB&lKj=H4=%6_JcjWj_>h<5eqnHJ7*2GRvph(Zl zZ#?!orMyQR8A*YikN`IQ1bB=+iLtP+6q`?R$OPdV_~U(!3G}Vu?8gmulQ875g$r^@ zoYeXsarEH7Dgz=ZRpY-{-8b)0so2`uYTzGc1rh7gpOvC~{9}4xO&UdI?M}aoS3q+C zBhbFi5hf&85v~!;+V4SzRg_LIlNUJ~oXZ&G%5h&2c?!GYl!VALL z9S*d|i4ym^B^VQXw&$>BZu}5F`Td;%-R)Tflipebb+$K)I|)04xfCD%0swNjIv4Z> zy1ED0=Aocq3%*g+>RgJvOzi%1A0Auwk%_|8pmR+e-%-}1*`wQKFg1Lzvc=MSmmAjv zWZHl|TOYEEhZ#c=;GAfZ@}2wj#4X;`*%=1A^?T^+#2J!WFXdG?632S=P$C3aU_R@Z!e z^!XWG%X2XK3Z*5Mj+@rs85)(w_ zkUX`X@ciUg%u%1Go6k~r%2>)w`rg<1F5gI&S2|A?7Mt+)$gg*>BX2}CG*r|gVH=a`ZP%CCcocqs z&e~o&TXA-2h%UP)eK&UpGcdCed>|v_hT)G}yhDijzd`}(mqAU zc2z(32K1W_p7n}|NQFVMo@!?z-!*r4hsEv`lM2zLuMY&jJ&!0IZ%OZ4ij%vlohk}X zm-77TkOjLU7{kF@`V@S0xW7>E)+Dm*GTzV@RAO3T6i&;zXs#x)I@qK(UK!ZG!e^En zovoQ9t_ok5^;md0dB5ttCp7SbX$4h|_8O}ex1>d^LDF`R@2m~}(>_Ak|8mAUDU0=c zJsHS>6;qOpud;5rn?LhOqapw3J#*daP(|7buF@{=^2f)v{{2pm#wr|ek_rL>I=oXs zX_sXEzJ9Pu+7Al;bv>?$9$xxpInxc@pC=Q=+LL6)JF~tMa=4ZEOC>5VBY4VjfAF=4 z-~B_HN192Eg2mwK?F$oC+I);}Dr7jFrqpI$$yn6SUXw7&p84~nREBa zPIOL-W#wolB@A&2;C@#4T4o&9o#hZm0q+7&@l6`B%=mxUd+(^Gx2Aveh$x6s6w9Gw zL8L2HI*LjM1q0Hh6S`C(6tRFP(u;JF08&B=y#=Iq3`TchOh&43fE|F>88MlQaE*>5c_28}XyJa+uJ%ZASpv_!EZk71RoYje4nB}!b! zYi({G7jc;=5}`!j0$Ul9tmO`dK50rIydpa4UH=knPq)HuJ6DdKG&3mR9|y* z*3>YQ`d{zWA-+9(j~DWT;oJqbX|c4+ui< z_6$n8C9P*XP7-gA9jJ+|v6ZPgY^Wm<=1$;)eCKNzLMn(UrO1p<$}A?y?ry2PI?ZK= zS1vTYoxUbrlISB!id5`avPX{|EpOueu5+Fh@O`5oVug89@@QiPx;~$8sIK$r{cR4z z%HnPrrhfzDP8Q^p@E0J+`2PHnvtML$tZ+^QqvGarhsg4ev{0D0j=8zzP^lYIA*Dvh z>BrqT!6sz<7qd_q-n2V3$UuW74oQ3!Dl1o?SVP#ZT*7jKiO~oS>5VTpND$S(gVSl@ z%QY^yhBw{ka`g&T+hh197plZc?I+HQ*bF?X6wNc{tZ<%oT^ss0KI!>nuP6_@BSFvGN6ZrCe8o3O*;b8{)IdDGRVmaklev6GzX7LLG z#ST2i-b>Lf*T;s6u&}md>8d`z^uy2uF~@M&yoht{#Q0;_c!F~a3uMs{$$J-d=-G6a z7)HXU@|tU_9CQh86@5MQ&~GRx_Y?r#sY|B+#${)zKapefFDB=lPA5m#?#$?W7GN*R zzcSWRMQ3WH zd{x`tCbGJWW8d~g$ok1}Y3F``t0jnzdjeh7J~BI*A^XNnidztEhaWB(Ni_aGY}=*z zey17Qgk|#^<*snXMA+uyUxI%`7FTLCzzR!Fz&@Uj+)c~{*OW0ru_7k zFxhby&{L<4?elozy*VZkYR0I{)SDkFY<;&UZTHzU&vXSwKS2gTvmN0!HXu;yv2#JC zhjk3z^;+O1v7DhVvlZD>auzYL;PAI8-~>k)x8{bb@_SIX2wxAYng1-PkKpQiA*H{rcbl%3J8$bm4$8dpmd9ozQSDtxU-l*U3FdO?^i3^ThX>-5qBJ zQST^1;#yEN&%~vMKpJ;$i;->b3;z@_lIQ>7FH8nK){Rr4h9`;BbEX+HUW_#I?h#ZiCRBLtY9dY-pBRdkLw^BDr0cd~a;h15o?yl-s#`U zAI_QEZXxbG6_!7c8@*1LaBEg8$$r76eX^5}F)lmQmBnx^|UT<-Q5$n`AC`jdr)h0js9e^%6P)I0<#vT&wj zA~HAT5cThff8Yw(%a2gPkC?FYm8k1dyKk=!@(-0cqMoN8i{!nhd&#)ATJyu*`p;e+ zti&_t&ROC7@U=e9-+vwp3Vs!3Ixz90CrPplt`ym9#w+>T7JK`HEv9A`Zq)T%E>vKP zxpy&8Tr5*XyE}mxGSm|<@_N?T@>8kPH&f_fDspJRX@H7{E=E#^AL)l16(_{HpA`^i zI|T#rn&7+LbrkO;%N9Cp2p%+fNj~7jjKO9gu^cxhq3?&qcw30Dq;)*Eq3d*Tr&Q&+ zM_iPZGu3E`m-j*)IexYv&~s}#AyZH4ynHT)XbC`zx3PEH8)!vDT2^{&Jhbzt??3J9 z9nWO*o85ZBgnwnn=2v`EIl6K@ail`U!*es~h~;K7%%+`5%gE)Ujn~-GH#iS6KS$Lh z-nkp{2b=i&Uz85}koy!CKyW496uJU3t}}|T>Hb0UFF)=z-)PWo2&4`lCVoCOwl=u2 z#$*lgO17XOF7{~|J>Jm`P5qZw74*?#QOkit2{gX;4|bF2&4mu{Y<`n=Xes53;L^Hm z^|C5E!QB^yvn8DKN<8E%3bJR;F<3Hf3$&zYNGLNde0+k~(!Hqd#GB+2jnOZ8lwB+R zQ;y!#bL&sc+nwpe3r+mI78~9AE^xgP?wOw~9{sLlR(O4tWbNDs_2L?0<8MXfH)#K~ z+ZZl|a!6NttX}W_$Lv7v$FaRg;;c6^p7SQjuK2&BQ_PYZ?vZtjj3<76W2Ff|DNDQL zmGB2+9f#tZ7A7Vp-G5RiKxaE0Di<=Uk|f;P%@{f+e22JCo;=A465|Z##rU4lOz{!i zlehd;>(dxa?AKxnYqvtCcI{%1X^@dFe|YZxeV&xu_&6w5#>RCmafw6$>vwlNmMrAY(p>ruUQ#v z^+(r;628v?;($^++nHj8Uk)Pmfxk%>4uTk9M%d3Yg}(*5y+^7KL)m!sdCzc<&Jqes z9kz9C`tvZ%BjvtHgYxoCr>7&v`P&As zPV+CER3x0)DiWBYfv+=qd~Z~$$h)r#D_3A&YzWm(;E)exll{g_EO}IM7^+{ob;WH? zbY-<)X44hhx9d|jfVn1d@}B~PrwaSQ)z`Q#sbi#h40*Jion7u}9^V>*>SS|Bgrypr z>)IF-p3m?y!q^V)YQO9G+PvG_3+4N_ByQb}7s@|k{D}b^uKYBpWvh(rKVJM7U7vHp$V-jEUma z)hx1XyKwv*UpR!#*F3}+CpTO;*^+)AyWCx)ns`GbKqj#n?i+QKhZo%r+mt&G}hV=F{lzoA~4*EoYq;hX2&DMOgc!rjI% zir0^iM~5U;#&uXX6*><1a$(WwB?3GR3c(Rd`PG(d0v_yYs3{zyoB3u4%gkm>P1#*; zNM%9i2kaCDsRT$#5xLgC?8-SZnc@zqUDchO1yNS#Tk(;KZ@xaTHbRf|?YxBCYFGMlRBd(No(D*^jKTXr@`Rz;qVm;;@QLAefLfx3QvNOWE*A3Y)tL6>f$E`CCr_HlW*pn(E8;DIuoL;ALmF4CEmNX;ulxBI=cCrO zS?xAn`Y>b}g)q+?|6AYUANpbEn&5t|;>jqexhywjv(cg9>X> ziIHf@s9B01)z2(N_8k33F*{N1!)KyULgw%AdGhD#;KWp_LcC-&YD@a9wjd0%SfM$$ zF)tNh{Q>bPlA?)aVENC7i`HTG1D#Ok5k%Sbz`ZPinrXuC6TY8=d%|;Gtu2ZxQd}VQ zU7XL-^XB#A@TSJb2R-P|$36`WB4tJBN=+s&BVphrHf|gHlnhj}ZL)g%$ZV>rF!b(v zTlWk;+91U?5-mJL{*Nevc*3tROPp{p=fL?u0bq{cQ}D~oS|aJ z58FK)YGb=rahPI-9`ST$%pJF77(m0s#iO0Kd>xK)v!2k_lUgq~?|l17JYzE1vov~0 zz_2nZcgLy1rL!h{Pcp(a0ot$U`>XQzh%St-aPVN2j)xL`%$;G61=HGW^+lNZMlm6J z^wfq75uLDMut)n$p z`9Zy8m8T%7R#PhbqjtwHCY0HQyI{JNh6F9(cT=A#d3DPN?u4V<7bCnq3CgwJp7d@w z0B;CoDD0BNM$~EU2X~!kI>SE@_%ZLw%dhYGv0L!aFey*x%vW`>+Npih@_iXB=#FF{lBb=l=l8#%8|}< z_j4N?8!I2WdLt?T{ z5RkorAIzo?6HxdKkx%hBeV>AgdkYU|J&*a6{f_QrxcbMw^yp$JVwvhUI)d_we|fpf zDcI%iY;W&7?-5k3!^O^erMwIrE*UF_R(VHxNtbFsx96T0KiWM!{<}@4leMTfwuYx= zc8)>m_yk?Z&llg{$Sda~F>C(Yat+WHgde`_8B`Z(9(HAZViWpXF!uPbIC?yHI)pT0 zWrvd&3l5_c-ggOE1+}xs2?hjyCJ+ipzWO|(u5I>#xYxp#@twBhXk}>X3eHpe*R%b< zp4^Wr9$N}&JSByp8=Q1Z9@=Yc*DYhPmx9l_=EqWyINrLEEh{>9g?-MKY7COqvxBoID?O#Yn-}aQD6Y+BU8^iP0ey4y{$5Wu^bAe z!Kq8VQXC{(eB;7Cl7^{TupTCT+EX>ToV3LezfLJ_Tw-{HC<4Oj|Jx6rKTmhgL!E|M z!Xa72ku@9sqEQ8N{$LxQ-r0}z-^F!GQIb54l03Gqkp9|x$jJ{OXASVtnIx*mUP$I1 zEsTg^juyXAn0bwcbUArN`!BEKNwvKC`^!7}Kif@=(z;d%_>enobm84ZcCUkF(8;k| zA5m{g3~x|)kC3H(u9C+b_jFC%^Xe~Qfp9`?f2j`>`lM)oTWU~UvX24>Zb2Me?Zobx zDn%MeDV;8eT~tlDth$WpifBYKgph8!j>`To=7(}#bk&-&^Mg@s~=Z-hn3v7E%5>At&pMJGirX<-pgZEF4qKnV8Yp^e# zIwnp+*!c78mDnf`LjegL)0b&BoqL8Ilvh5slJ;VaEMNE9En~-&!Sq56^fr zJ}yc@?SJhjC1^8;`Y&gcYmjU(e+r-nJFGgQNfe;m0BqdTt6>9KEf0f}of ztzXVpo@z?}ygJy-{**O4Cr$4_iND_yz7wi#b zYnzj}gIBq!wO2a?dTNgN#|IGF}|e(j^D!QZR?1F$UYVP~iOh4Jks3ZX2KApGP+ZLI|g`6Kl@ z=+|b^dPU@Suc*axjBQPdYK`&w)k<|EFIj*~WHgI!n%S{apaX&vuWZn|+S9k3Q2itq zZv>8AGg~IC8BYhGIXJilk?wJK*t=rB{*8kCfqT+TZ5KJ%5;{uWJvCUZE!Y3Gu0!Pa z!9LMZp!rJ|zD~f_+TeqhZQ*GxosKuBm8a92Ce`HU%AU&UDc0a_N%Q&_-@4{`;zHO= zef{4&6TARC=k(EOXA*NEe+NGM!y7s(_zNNAT0tG_I9PZ0mhA2@-^G?%OW$Lz47JAu zsKW{ht|I+5TysG?L-T#z_OSCGSDKod;y4b4rd;P5G}3Cs2&Pcb?pzGq5$FAssjd{V zpv$3wGcZkYa32*UhnTKzeR_Zha@7 zU!;66o6&9I=dpPsXXSCJicU9IZ*c!nrg~GWk*#NMLtv;f9Kyhz@0O%u`29Y$nW=ih zh?^`?c9*pfow^xZ7C+q?-ZgQtX@2nTx1Ga*Q_ok8K1(?!kA_4NAG+Pwu*dRsxW;6O z`jk%Wj&g*@2`L5HzK)Y2($-*5?%RBsrl#<_{#)-=YA%;@xT}8|?89FN?hT!;GS7S5 zbC0Ik4mETZl+XhZc~P8~4VE{IS>O1Kk#_nK1}-<3D|!(9$MG|*R)%6p`KcKKAQhA- za}(FymTm>;Mm5zjUmdy>nb8(v>?bxM0$pH7^*A-hb8ZsZqMm`A=Eo1Gwj`mzsrKjw zjL!&)Ev>o6AsIsPhIzChD{Lm&3U~Zc{~gSeZet=o)kuKLUpVP_72>L$yY0?YPm0b* zfo1+tV!P^;~GEdBo)!U(D?DOn~mytuPLe(18 zy(3CIFGU@9V3&C(Yu_EkGm4cf*o;DM4|}j&VRYqwc*M-h!*-I@vNTlxeChgYnK1mI zV~9uYt)=(Nv+{4$e)5dhzjn>l+kU~j{q>^Id&8W}Tqh02xb1-p;;ysCp-5K-^h~I5 zxan;w&y^|%9u>QGs+>BN%TyxNHer1TMjT+9UU#lmx^;1PCf5CPR zvsk7barq4{I;#(3C>)k?zL2Qn&CBLjddJkPr(D3~V*ssm@7?y8igB#0`$GB3tQdNT zSdtpRp<*z}TzNl1UHWLk)pWoU4mMR7-2^nRkw^E4N+-xgfF~;6g;@ybxI-?X|-4?S2cR%!exTpjX1keo()sLA->lXDn;Je|(MpROJAbB=oM$rhw%1 zv`&VkkU@^vm^DPQZ~BN|DR;IHVazL&Oh5eN5xC1HM)k20&kZ-6c;kHov~4I;zktyP zB>@SiFC7EUQ50RPfz%6^brBZlN(_0!ME$;PF0boM#6R+~r)GghmkL>ZH*d&D`3{jH zEt*2*67K^8@%(JXr7dOTI=>P>UFKZ|% zbI#GT9guAF+(@2#&{aW%>5K!T-khv?;;j@3i^?%GVeho_%=Wc0i=XF|eJGNQ^R(o3 z40Eq0i~$zB`mm0@e#y%+;WT~@@jl3>u06vOr7nTKe$~nAgZQB_qsp+DA0ss25?Y*{ zIh0y_)Xi3TY`8yZ^4!P|8aVVxe!ozcwECyIp(iGjNp*wLBDk^!_5 z*_A}hcqUvd^0=`>{Y3#kOLC;`tFxjQ*yerIq$t$O&j&NS7I3u8wN1-@b#9bz6^}4s z6HKWz_yAZ!55Jm{6${A@U43WFbE5`eQw2tur9IcbaZBgzNN)r?&D;;|M!=m?$-ER@ zyJx-oxIH}yQ!%Vb#swd}v0c|T18ZSPhlfW+EB%0{rhZW}FIbl)tW!0^a=9*Z5Sb9b zO%eKbHuw|hDOB6Nk$Yag%5CwdclEU17)oFqMeCKEoIm(U^iii==)0sfj=>pCGN_>! zjR;;z-W8-7(XLoD7IEFaeWgtGi@Kz@G*T$+?~(we?jC+`&UreKzy~wmT2h$0T@^3SILjzu6ET$c*o?t5qp4wyYo?E7+~(8P4XxXqtY2v?Dqfz3 zoQE)Tm<7+*iF2ys{>3I~#*box7W!%svqe$ki=Y;P9?Ry>REw>(BYcb;m-oh1r6@Hx zJlk-8b?z;iUgSr*N`Q?^V5oYE3?EAst>|`!#FwwQrJFKdKLV-s&Ep~0R7SSn;G^UF zbK>oZRlNjb#_^FA*zV7V)0{=#{h1k6_qO#kGY8hwHEUWt@thv&v#X>2#r`#t@iwsW ziAf_?LRL#cdslQjjCQFC1?|xG^cj|NG2lT#pL99^oF1vdKRF|s@Q^>Xf2PvIW|}~( zgE43UvE|evcBXh--caCkcswQ`O|={tt!IwgM?(vrS}3ReNQHK1C?W7?J!kDLp`g zv_?tFi9Vct>>{9d16o~Tms!*KE(94n|Jlq8F{g~X`WhuS+$oNiP!X);vBIv7+UJxc z&Vqy^jvu@-k1dp4IU&HhT3&Xh&QEq>T3z7mf^+Dgy$Ac^nm)G@K_UJz?W48DIZfPV zFNZXzdNQ=x+O2q?M;aIG;W&$aQ?n5&XoxFFkqmR!YH~&|2U+6!678vZ)gQYBAdMTS z6vytB6zRVIj9n=VKjrd~240aevYAtBSXNJUhF^FLSC>S*j`yKf+AepiQcd=fQS@|N zoJ03!J6V;f9D`Tj(;q#9Mi0H>u5ew zS9GxUq4Qzrv7s-hhRWcDufB#0`O&LPeoPdS5-75Rk%!_rWTu9t{9I- zFDxB2IgNu9y!!SR63&o)Wv`!dToMy>kj#-80}mZWfj$-gp7GB7C{8!%_O-PT|$VDr>h^TKGv)yL?zVsVi(7lfAL@)7;xaK#qo+&P6_fV`YonYUT#4%8|EhO~?ekD~ee_aG4WHPa_$BWrh* z3)bMKIX#fztzG95YQglci1wyFy9fn3rUqpIN@NIftRbZILjX99_L>{ z+H)Mc-_3gzE$kh`V?|T3J)o?)TAF}pxBj-2p>0YArO#D19LarUI1FM-0RZx^JXosC zHWt>Gw>P>hbq+f<<#U;q?xn$Fh^rx@9vu0Q98_33o45IfWU0>`<eJM(utFg$p9WcR1VU2?CbSCN0JJ;Kqu0-sg|Lbp(ERXlhg`!2Y-DAewm4z1nCz|g z1lp1*cV~r1x7sxtrRBY5`=TPqtXpSB*$(uYx;9g#^Ob&lYFoRWat)9MM>81*a;AAH zvRkxF)xksr5w^60dkwnfE{RWe9a;KlH9pw89YqO;rb|;BK~-jnbu68(6zByj(Q`^u zp}>8fHH;Z>2s#GmXxZCuFGoq=?Xh?y&ol^oM#|=vvN{rLf2g{&#fbQxxfAODcPpx# zA{9JCE`BFHrov?+oK`zG!jEQqvYK|AxCjbw9YTC5QI)GUlG}D9-1`%`c1mz;DT6{D z38P#W4a(PN8~uwLpBHVZl{S*2N6#ale}r6YQIC<`-5Bvs^03BO*g{(u2Tq0KEF>wY zQ`k4x*selaiZ|YR5Y8zgd-|4ugCsDN_L(V!JW$c2xsHOTOa7cPJg=5>ciooJ8=0dE zE$FOjPs}F(Kd=wp`YI+HwzwbYm-W(@0869rqPTj%Z^hKu`XEk()22c$G>#Lt`@wa!``6@(X85NO^KT`ZcTbtEn+j~H0W-sZxN-1vR zc4HfJ)BHmAiQ&P?zX_(B^6Vw#Xx|5@dq-*hyi7sMQhCLDec2-2Z-O;Kz_0do$RztO zzXGh}k`chG?}$JDCR+hrBxkeF{C8mtR8`sS!y&7)lNy6>2~7R@9Bwva(*(U?s1ASM z;i?!IFt|aGwA(YR^;N&H-WI3Jnn&#NrGl4 z)#6VZkS6ozt9$k_J5!{%X0^K;9)0Ue?ed1Le_{|DJBp!!k2$*>@mwyX*fQ#%`J>|5 z3mgZX2zlm>I(RX_drxEI-PA(6b(^7b&m3{M$puN_x2Ie#fTWDL9OnV4g2YSr)@`n- zrOQxvLsf$0hAY`b+f;Kd0OsjW54?1(AFX;yNOZ^;Mckte5aPK6wvDO`OFW}5{8k&F z-Prdevx;M|IXP6k$SS&iyYhOh5o$@n6VSbu#x?!YsbJ2EVIAkkG(E=A!Et$}m|>?e zjo5*R=DF<3-SRIdz}`r%DbK!`w0_*;qYx+Pk}L&mg{i*jis!%+C{OK3+fDG!`8Pz>Xhq(aS&8 zsr~nJH`VO>skzpW9OAev$^i4OHc2{LZisW^INWEazf2J1ZI)jQJw`8g;qo0*zAt4R zVx&e}1JH4uU|GPL@HOdv>CsFK3}qG}=GL=$q;uB`7M)@BRBNs=!3;u;OgkNp zelKee+gDa+@w;TJHApg^Kxf=2`F6N!6VVC!$YkH|R`5O(;pgT?Cq{me+hb@g+d5pK zeH+!Xh|m4$gLgSqSI`CHmIlh5K~vzE6&jc>s3KV>yUjkylZo|r)p-Qu74Mtkn=gvc z8_a|;rJyMG60OdJ-DHMLSzx&@w4+Njc5;da%5T_b84^Bff*a8X0%~I;2X;%ai7tWN zqXhS#?{E>*C=Z9D`mzzWk)P$_`PUg)eA>Nhv@=~Ma(pyWe3we9s~%SjA-p!bmaUP^ zYv*Ntx$lckC5NGsx$Sv;Akb)Yyr{osx4c#z*NqC~TqjHXO=cm0SPOjmcLcu2dXw!} zi-c1mMXmup`EEr1tNRKeta~K^i4MYg4qOzo*tEP_Ci}Kmxtn=tx~^Vcvo|{`LR>wS>IYCm}-!FSgs zHkg%I$uOBmXDPwIyqB$*aOCq{UNpAD7T%gHoa79SGZb%^6kctgM^0y^c)WGw(k>1= zmg5=dBRmQ}&uP!NjErSfvtvi3taj6|Yz!vmL+0CK#8Fe3*aF|#8YsIO=E>$d@F|x# z!$dvjn1`18L|qbCMr1B>ygFCnIOOdxTm&&n5$(YeO8eWrD~sVEfDro96QJGJ+iq3) zJf~DLXY2xCvwF=|a42GX!KeJkE1=tMyk(^N2Ry2__Ib-=>NINBoub*T-VBpw<^jLi z;sjWbj&XnUzT}1j)MVQ}GdRYL^i52&Ch0dFPv_fySTc)$UOEE^wh>2!d8r#KqBL7z z#~dQ~`JLW$!UulShyTiX11f!$D1y8vpTI7VUg!l%q` z9i_^hO51eAnPM=1(3i^E#qy(wR>~Bjl5P3op0@~Sv|*X2shF)jigxwvKx#W#r=5xT z#BGF|0U~=69^m1st6|TmT$N?2%Vlxox$qSNC>~fWicLtyTH8QOavUILDyjq;I96N_ zGC!j{eMtkCxIEu2Yd*FsDsJhOt5bIFHc#}>Vq*}P!fPbwd>bXHqt4^1-F#nD(tY8% zH*x#UQ0=4`tb7GG(0t#&F9bwZqyD1QRnR7WpB>(Nant#RFjWYTKin!eiJhx7*($N)sG&e3NfuyD- z2TEGkXi1AoQvU+#VX(0)=F|=~64PoagN2fAN58A#8h*hghOdAY{q zqg8jCjOeSgTvre&J_akYbrt%~Gq;?{_KPcTk7?cJnO?WmYtx8z?~l<0@*HSML4@DN zBR;F8sL9(fHgDNuQfA6Q5-53&cSBBQbD1dxGm^AX^|_>hu;eS|{X$}u8Byn97-V~? zLR1M53m*BKCXt=VRlUb@ZBp_Fwoc|q4D(@f(y)(+_#oV7_Me&Ce>YN4`ugWEC^CsI zaI8P9*!4ppS5=~}@JC(_S$&Y~vc3!vbp2wD9m~o2oTJmi8lNp|JJ#2$$GQU_H9dlE z4rPnZ#z!X{^pjKa0V$-e)_UswVnF=A?v?f${e=+=tLPu&vBFx$zHR|p79BcH&71ET z<-oW3z6BcA~8qpKyLv7_#uuR_v*(-GHU|U85rAsqa{ZvF9cG_0n zFqlBJUtKrWZDWP|XM>#zD;W@cr`O-O$9mB|5l!hcNj zJkIQp7KPq#;f2k~5c9`i=8Y=(@%#v{J?BR>3ALwQgF^TXCGO=E0pfou8AO8)O4ZrsUOl0D5Ta|) zr&yz8(||!#S%CG`UWYZ!^w^E6G)VWj@lv7Ina)}q;MuND5Qd8@v_(pc)yncGa$d*H zOZOwR42AE;c54)98Om%-@nAf3P_00J-JR_!SD0()J2?NoM{VmDmZWg=R3XLNC?>cg&GuUr~`f1H4$1Cc9ZW8&qte7!RgA+PvVM$)%k zWO#VI5*z<6Y?7zf^`C&3K>OPCZh9wJuj(Rx%#8`Z)Xp+J0-ccAK_PKtNF7$|VS{*) znhDG!ylr}b4;eJ;8=n*HL3s5)ltn&+LDRjC0Uek2q=K6UyIZga-HplNS8{B$K^2e# zVO!D0)N#CwY826?JLuU!m8|>s=Toi8T~_Jhc$iv{4|VjmSxsnKOGpCo?TDU@U>06J zKeeBXmQ9=+nwxD?;XI@GJ@I99Ut!^lfu9T3=F65X-=XyL$i^N1xx{Yk7ovZ+57AYU z=?H~sm+0{!w`SltquwqYm>=Cqs1DnFjaUJc!6c||f{C&F;A9T2r%+MKl)ueOj&7f= zjO`$4_#;Q`w?5sFtk9Z#=Cd{}R%AZJ?P6Vx0Ko>Mb3mk-|wGs7aE}`&*B|!2#_M4=LDM?#hBloz;hq+KRJ$@f}<1ueXk( zn?n+=;A^WI0q3Ii%uYU#Cag0~C~nez*gb~L_shf5SYBWK<*7Cnd^IR#WVzsdW?&-B zWzJ2eIq!$p?~d$jQ%q&W2(+ShSwlRM$L^&y8wy%KGzOg~ow)CRC)z;kDfjwYzNt)y zAH)MsK|T#8Z{MX%N&S{*lV|L~R@N6u!nyY6$0DagBy-wdnjEITB?YRyVBk+z7-Rya z5ghqyKN35n9}XAm3fgbj5kwd_DtCA8WKiiX#0f2TiOrkWKfTRb_SNwGBF26s-J(Og z`|SWCIhv_GDu#Io+2M#vmk z(WB?@yQ^2bweIb;Q{bBhId2!WFjmz=Es2s z@Xcx_j#aKc+5i(mjIFTEB#+w-cH5i8D9LQdqvp8)ZNaMiwuTIiXJ!q%$8pdP3(3RO zYABS2`b3?8|SwF zR0pus3K%*tjwTqHL~+m{AoquV-6=(C&`Q#IUk(}bZnVk~H8#DZ3xa4cEs`)nWyAU` zzc<8iOcmvTON2Uii8SRRe%hyqicCF2H$;QuPL$npf8(b0)qXqCeUZ$yqiV z5qHiOl06_CSaTS<=Ri(gY;J8y@pdolOELp1cUO;-khkmx2Z*7{rdZmNBxB2C=X13e z-5ErjU%Kp|Ejqf0;w(X5T7kPMkEK#;E z&j5Tvs0_f-9@-+dOP>iv9(bAka32}-2CUt@^@?ucvOK*t)3t@0P5CMn1L?_q8TMA- zcv>E=WGjrTL)9qQjKC@%A0d z(vPrhi`|{WmcbtE_87cht66A?aEq(1nxTP+eELx1Z4`!{z^JGWQpt&L0 z50f^-TsmPF*IaX-XVS*Ld`X#gf9cNu6B#jrRK!lyXCncfi`_=o`plb~loa07nHRH* z2%>K>h_3tGsFdHP@5pzx=PGRAKG(hX1REtWwRPx-e1I*R493NlfW%b=3pmuWR+2_;|TEAH+OL%<99Dd8xiCGEFb}#!i43V#>Qy; ztPYGd^3pxaXJiusxF9`4wVYfi>_`13T&tzja%6k5H`Nbrl9r(!n=d!~ouk8iWp>H3 z^Zg3~e0{Q~70h|6l?Wr^XB^EfrQ@_zRcrj!6X-aBxVX&)Cn|G!6LflT>w3 z@LVHKz^3Xmy1EK&`W<4yK=<`YSNR6B!xYq!;5xu|Eb)w@B;X)QRf} zy=Y`1XR`S~S~nl;MRYxy{* z#gp0jzvA+#8P?9IsMW29ggUAT9;^^v?dK)A=ted~m19`8~fa8~__tAq9&d(}~ zXL5C2%@MA$w)k;Jo3zz}}2;*(H2!+b)PwOAol4}1*~oNgh- zef#y^B`&wSC}N%evzc0?c~AtXIjY19LpA4?4M=u8datlDE%0*W zfGLuz10C4la1xn}BZj1Fd{Wnct~>(Ja=|6g5v33|*+;spQpV#_MNZ$UJDlzLNgAi* zuI?o`Gi4pfgLIWVXa860CCWVcf9(;lO-d(!9tK5ZmMgY9%HdvkxMq=gySAYU7B=NY z@^rX1*to3KE+=D>4}YH93#7Yt7ry>Be8TQ@<_I`>W|3Ql-}nHnL2W_?sMoq&D#?(M z|9vn90gh4PPI*7dN^1Ylvq5xm*M}e_M)K)7@O{Gq(jg^(xxW(byEELsrZM&xcpjX> z$Jc0dJ@oZ23w-i~7QBPZ-C5E+Zg2m=DM{^_SIU0N1yc9i&HV|f9+DUMXCnT1R7Jbb zZ$l<8K_qm%@LcyK$*2EA!@uJ6J}RUybG0uXhze9VKY-l(c)wVW%R#`!?gV-QhL0RC zJuptX{rL=XG?_)7Gl{PR`fLh*_vXS2LOH3p0Nprq_ywu-H7oX&BFp=gGmPYaveRYn zeSfu!FiP_2-k6ws{ZrEEFS6VF=pYxDGs;OKD9Yz=f%xcP-=z3SKK+mQ|LeTRzY+h! zIP6w;5`9}NC-?nhj~z%X_NI~CVW^48g(CzDYR}_;{O_~@w#E`&j>KH@=vGup7}yZF z`!~zIpDI&w?TrgMf9-vw^w+G_Db1el1`^e!Yu(q=BgYmq%!JTr}028kI|P z8NithmF&KntR!-;b3t)<9fvo$)3ciB?d;Z|-BV=C|Uh7?PI( z3kx^nG@WYwq!n>ZzTCVk;?OCQU7!QAGTQ{Xm8=H@jQ@wuljqk~ep5Doo_%2X+HHhm z{uP0M*y*VryC^PqVQ=K_Vu$=kX;L_nd$^B1XTJ!&ts?2!0uw)Hd%2;Tw9JuUfUW43 z1>oQto^5z~UMGEfx_N>0#`aHUnU{D~FKIYrr(NSDc@0Y8{VgT42kjpu2D}Fgp#3ez zFZ5PI=H;lfrUEG~2YDK$_#w&Q4BBLAFyNQS<72K3uKa z!9oIhPe2=wb$W4wLR!~y64kr<;+HR7PbKs7eJc)2JSipoOOfQ>9k-_BTT@MJY)pLg z)VfmDs+9Nso#QJW9oq-L_Iz*H1e9U6ndXbjo}M`=rv*;Vh}n zoI2YYb*<*s?c0ivhlP*PT9W^I>RzO(_m}!EPE9qFzRw?r{KyzpB`x@->FMb?3k$8L z7AjoSr-l76y(G>V2+5Ss^9qBUF$<}=! zu>+dxpZ?lw-XupSw$+giRg(NH2?Ku6I}rBQw<3i6uAd{_hTq?gR0;MU@3b#Jm&=Dq zJ9_`e2OK==iJbHPw^X{fz8%cG{huFN_g4c@+=<_sw+>wW|NK|mU%`SnA<%^s!~iP% z+gID)dSNTUf`e?0O<)M6=Oa#p`hIR@9sePb$?Fl{w-C@ zZSUls{O>O3+5orHgPXIgc4k%nm)|hhyVi;?&zsNP|jp;Zd){FMawic$)mG9AGLGGt{Qt*x58)BeW@OX zH@EQnC*Ad*+rLY$-|D##>78oAr~FfVH^k5Ce-G8#7B%)>`*gnyk&`N?XDFEW4_9~l zXYF6^olqI~{tW5GcfQ~rz~Tvp(aC>ULY*t!-YX~2^tJMl{+FxUM{JIwE8Pt_XTX*A z5^S#BLskR2VkKv^6%+Kh7D@jriKXq|X##F&>^Y%BdW(5)9T}*E6USgyyr?Z_E$^H? z0cprm_Y9XfO5EjA)7Bm(~d$|VxdF?`#2jHOJ+mDp$ zuJ`rGyuOj*%}D5xHSUzeOWlJ&qGeH~H!FKuQck?eM{P*V{9o+7XH=8h);8=$v48~y zL_vxbAp)|gQnRt3(rkndBGQ}m4x$?iNKvGBX;K2xLN7{*(n67zP?XRE1PDEpcO`6- z?Dy>RjPrbBynnuN{-JQ+Yu$6rIoDisUh`Tpwu93?mbm*;Ib(hv&Spb$t~Xq>*FK;H`$jIk;h@OIF@(pD&o7Pe zUhc*!QZD*u*7e-9rV+%!`P?J&mz)FCHMFjH3@VE_y{R%y;LywnHYc^yqqcEpwS07lW&Nl2ylh3_OIToTlFQR4=1(d6Q#0W8+1v;ri>r zc0{CtsK4!eoFBk%@Rp$IxB3frF9b+#0<2&oeXj8^op z??cr-I?v1_6JF^#V+znk9ie?DF=AWZsJOfuIzog#>;jF7Qhkvx1Np|wtQvFMue2*i z?`zMH!dgkXKE*1aO~^e0X%CXh^P|*qgjS&~q7raCulgbgr8F!dTzx7uIAF zWgPB0yT&$*z|4Nd=&5Vc!^ii^<`V!!ChxN|#wO1Cko(GjPr|v_a0N>p+alvPLK`c? zEU_GN8|jaVFY1ZSwnz;5ACef9$;F|a;(8rJ0}Ezu?mJi_Ht30)$rgk!FSk8kfnn&x z@G1ZJF~8BVo+aO5Bpf;brLjFTZIbB?l)D6~IyB$K@i_OnAvNv4wQA`Z>7Ev-?By&T zIF-c$<5fa}1p5b~yDTB37i|eYDKX$`t?#n&nzuf(-6)@M^|0LKu_)8o?AWd83LKa4 zlOLgdYc}Pxr_xywy~>IJ=}|f!%ZjlnP=`r4PPAFYbUfOhL-KzkHHt>FrQ?lLmN{R= z=ki`YdVT&lYU;4`#>bM;ZcKsw`rgf)3Yno{(E*oam91mkUW<0HA$(@jqvuP!dq?sa zxBgl6p!I-_`#_3%e~QFI8qXR10!qS*4z8D3u3s;#ts47xg;a%#5IiYe6YTLM=ygjw$G*z2{CtMDZIx_7SE zGSRZ%XZv~ITDXoC7n}YQ8+{3z{*p+a&({eAoqhc$vT~~|oU0nN^$0b6n?BW$aGhB- zxAF%QE=yu|!?)5+dJeDRyzLh6Dn7_^QTXQ|BkVkR@w7w+&1e_zce+uQn-INk*{i>C z`E0!IH7=Gd=q&Uav&^lylilduX<>q@o>Qm*Rq**WHiNn&@&{j^zWQS1=cn%OthVl}M-`Dzb!?hckH}3tl^mYC>aX61&u?=2R(w=oZ-@8BJaVGq!O||Y zRY8k3+`z7@$kDFr3&WFQHrO+Ve_DctFPGAPaRGqR{V4fnSM}Lx345C5U@rp8p{;$u zD#|z_XDLp)Rnn-?qKiMv@(mb>~Fk)I8EM9W3EZ4qMt~U>I zZ{07F6I1iXLDAcrL*?y8&jT&x5Uqr0?8ky62AWZ5+|NZF^2Mq7as7K~uB3%_9{+gq zW;uRP+GuSwB4#-8_HJ`rPJwg(6R&LxuR#y|<^)0?wSi6ymcL|WtrZrBFC@&)*M+JX zkIJPd94nu$FoJn+E=fGXsuX{1oWT?a92xZB1&C18FVEIJ(gR5P!7^wjHSw>(JDuaf z-W712O;7aR+-z(4>}y3XuS;3m@ZI2QgCoJ`rG!GOo9fx(xH+W?QK z)>WonXg+YEThpk>Vo8|LAah{dc_Q*Vndflv(WAFX~O&_bTVU1mtyz zOONcXaH=-y@0zCN24d z+^Thc@qSmr37OTV>5Y~BDV*MQ?ZQ98G5O=0ZmEL8KgMv$PPpzqw{-`s%I@KuFPYYp znjSM^*qYtTsK$TiFpPIJbgWszf-1E=?3FczdpoL#vqa4?H3*DjDB3cIOX*UctIWcj zk?=&PT2_}B0*Ve0s*Lp;^A{>LL@gN&IQ6^+H$?r8pwj-ifLkSlN)xEiW4y&GQakT5zDJ8J=c|Kgy6*w=rhvhBDPh zKtq`#yP?|b{kM1%j%zI83~-VfI@VpTTWf3!Wevw~a)?Aru%aS z2rSjbb+(l4QOt~U_KeelCAj9wBi3=)ZmpD#Mq_9e?Liv(m}T7RnM|`)Cbl!C%!sjR zS!Ha=6TBA; zAE>Jvk4xjr6c3(SeGHrRfF<-A60HmD8J=2~w3|>v6fOP?%6%E>jqxe zVcruz6(6B0mzx^nq=k+K%dbC#32yNXxD$RnKm6+KVfhrzuuZ{o-H3}hRj{%a^Srz6 zLsed=mf9!vI7Xq0JEy!xe&&7NEBnEXFjn8>P2+=UO;3S*xa4=7;sC8(6#0emTm}}r zIuiPau>Hta%_pDfNx`a$MK7P`3h>I;a4@)0&=nI~7T;VJZ6(ahG^Qa>LJJ#T;yBH_ zsY?z56mWeRxc+%qckVwulDd<3!!Ap@NgCauMmjW;{cF~~AIK|iC%Ah4AFcaeo`6=8 z-OiMluOp3${B710f$aPMy-U8kTas<#*uVSEzdwe0GR&-b_ z&i}zVt`L z|D<;`FIzfBJ~x4lGm7?!L#HpB^sj+On{f4(n6DTQ6&jIT;3Y*>;-zazL9{~z-sYii2RBHt$_Jkq_&C_q zL=)iL@$o&0M))7*)MiZUO6cIEjwn(qu7i-d_23)okl=L->j ztSs8aHb(_?9$Z&fH*}-lNAtxhw;%SGfSrE2IvB!=6#|Dd9$a8@Hl~ZNxLP8BEb}1<~AKA7@Hsb zL#m}bcvpiu+fWx=dtpmHxw*gnwt3j%OkmhA*(Q3DU)yLZ&H+#)louQGl2&weJ;tz4 zJnoB`@rv7_SHB*43Wd|v-_b@_IRy1dUu()7D?&KDrTlW2Zv!7`1-m6p(~4=+gwQ{J z5Ko^S9zU9V*19taF>Oclad%GAUG+H?Wj%D|Dh4Lpq-+f_YP)fZqUVXqJCl6O&#{+g zlA{+wV2Z>koMGQ5lY}C#2kNZhice_YdXx^^pz_MLiX%R-sPh!;R@SRvn-JLZ13 z`b?sdtdQmpsqbi1A^VN~vBG)UFS|hZyn0=@Auxdnfx8rX#Nq_?3GY;>9i}yNtmRRT zs>oL3U^IBg)|q)h_kCi~aS-OgwWq`g=SAoP^f% zAMd~lwF7M1sgdjuFOw#J#2Z^p2x)7S^kClff1oj(u9}`8x8&$~?n!Zr<8`Ye6 z?r?!Oj?QxiKBH(R)C*|QRB}4ipZdNa=MF6+qsB96zL+WU8Nj5lJbgfw+{axYCC9M( z^~KF!N_oebJY{2v3>wSW<+}i83<<`Yu~6SP1@sKYE$c;@@qW=aWU{L_>$;C&o<%6%#pyJ?I%Q3kxR5i89O zx_SS4+Lx4^?^0Bw*%%Lz4XyjK2A?i~c4bgwlRLiwnX=BkJw$OQiPPjM zH`?6eV4@818{Oz>AX2WO_KQ?i{H_S5Ea$#XnK6^u39>VO5#<(t``4<0O~98AOi<;w zn_`sr`7(e-%X%7Y^@<_^WAZKpa}Gs6r4GS#@d%jl!fMcsKPc}@lmk;eI@9KzXbgpqW$=Ja`Hgjo$O|)pNi0ri;?#Dd)$0-+PTR#8apncw-pS zMU>_Qy#zEjD>$B}#KL}qYzKxW@#$0UUm_ilDgTeN9A|z>0NO{6 zMZ*SC#Cd3@+;|m;RHiEVF2&xNNOciyuf;{G+Wx;Y-I(=@V8cHSZodm&p23JMCAs?i zH92S~i0~}mCA26}Ec8JMSwH=@nJ;_Nd;)t`4LIqMPF!yiE+@gBg$rn33;41PTMz~q z9I2N>W$HMy!3wRorNE?Nkj)DkM8?HdHr`d_VzLq zdx}{|*E45V*hfs{>Gwps47yEO>DaJ7-{*5u$EvjU@k=q}sRAT8cW~(S=t+aTK19lK z;&R_|waX~DMxFg7m$Tz?FSDBD1^2~?w7$3VH*MiY^yc}ejK;w2e2(X$~R#?$g+<8d*k@R}%UID2^HY z(5doc;6EoQ@WV|8BmQQg<+3iYh;cF@03k)wG+_|Y}b`T8HL09tL- za8mj)YP#31;n7m=dK?<6J)Z_{wYSuDpA4(-EWx$L7`0xJ9vv5Bl;5~~PR9@qK+Ab; z3XF9JMVjvv+=?6L+aqDtW-8otNd&n;Kw=pJ?*9)S!!pV}5Xph2cjv$8Ah#d^%141MUm@h$PoQot~{a4f-l+0A)t;;awJXN@|g`V~4&fQ;iiJ+#qEoKdi>^S7**z^QGn z>#-FN*|~sPkfzH((T5&ykNSQGlzN4zdUdsUNI0TcX7Q8Jf`H7*kPn`ehRKwL&?EL9 zERoHroK3q4L4|P!(a`S+ z+S85r0OV4Yek)}Z+|coy`~1?aoaIj)w^2bqynXMvf*_qu1H!Q5h`zJE$?q;We~R$a^dFJ9Y}#4J=8h{hr3@ z(l72jU<`UK-Z&WjU{*68i1%2Yw@51K@ZkF;+eUTZfOM;~?I?lT`vS7tzJjtfqAArS z9$*x007+;8%YhtOhpv6xB_cZQnXXBqH4iFa1PQ&22NKXJ5?)Td$Plq zEq9wwmf|Z2Hq!-o-#$pniV|K+=H9NEr@M~?uM83sT{F6e;#|;jK-E?(AOT*)85g^{ zx0PA+-z;#Rt$pc=44bUM9Z4Uv7H~z$C;C|k+yjwd9dD2U@wb4AQ0gf0ne~0Vy+upoon8Wh)wxW3(1b*AOA!@u~ zb4C7rmq69(hrIR|9CgRy*aFn#)w;*Jyxpwws5WnNLtG6=C&)0VkiYcq*9*vdEGa7$&)e~QJ~Rj7-$tXHC;d&-WS5jr zVLTpvwL&WNW@_YCW_i6W)EkZWm`Q*ygdtvgF240(#0ZI_(9=D*AFja1=Pwuq53a+`gUDd6lMK6Le*{F59|grQbe_ z6I;E_dFtCt(muT4pS|7(oKp{*CV2hP?}hTx8tUl60>HuTYK`uaIo?vA(;fd4_cgn0 z;6)yfM;Fsw@Mn!`(K)Z7@GDQ-rA5@`2|?>?@ePGW3a znA(-m)roGW8H<%m1382(;_NFelc+0M@*{1@1o#=-@}>32;!o^4Ek?bc4BL%1Tk@N5 zxkIw5l3NqeDi*Q{-B9#N(|G2U0SUW$#MY)z6YP(yrQgH^!);zhBLq}_<~af^%4wKE zvJOnu5W!+^2@oyLa;fsEzJ;R^+xK{H%|hqSygNWvLQ^P6diLY3^)yCv zk51X;>9C#yDWfcZA)cW0AjDU1LyA+*B)<9NkOC6(&5DO2$UXbtM?mj`@{MQPR^C## zPZa-ZVH{}U>>1ZlTdrR3(0uf|zM!i1<&oeecV*ortC^ynW*CNlu+Xu*weVPvmTCMu z^;FiLZcT^E?AT}8NBVtC^P0|8*Vm|{r51uPwy`Ny2*%E{AO=qpoN{Jyq-c5cK z=j36cVwv**#$KUg5+&atSU$}J$@#Q#4wBmCscOz6U|k=D7|EWw2`NZrMRy3#%@dPJ z*b+Aj;3EsvFt541nh*3<2FZ@i^_nFg%C|S)H9r#SuDCLbGwHG1x}}rvY+xJesdU%3 zFj}E?Cmis-O*-`bnQQfi^6{e=$XaCMfOe%s2>Y2XGLy6@%d)BU43UIb>CyL))%V$K zSzTz#9e&CEqK;HfN&4`p9N-4ZoEP{^A4BX@?I#g&z%eQ>%GnIV5=|GcT75! zDHXetH-ACLcyy7MK6y&2Lz*SHP~D8UJQI-aw54hZcyR=zJD+#(n}Ld&cEx-HW*)UN z7<}4qg&npZ8&+jtK_c|%#%!~Jt>{i>rZZ`e{?O##q}cPt-@XWb2gZI=2~wNNI&2|* zTf<2Sl9C$M(IG76TgVF26cntQh(+7PwD?wYJ<)`@D4z~N%x{B+>R6Av{Z2iVeM=lU zcs8HaT7{xzHMS$t(~++8sT%q2zJ*dz5B@p>8eal2R0DTU8%08mF!H(6inrL8vaK`m zv=!2`Tk_1Lgc9qLgAX@95h@+2(DW`fF0e;yF95(#ppsCzMdlAswAXhVEs|Ufd95Q6 z?>u!NZ???Rc;(90>V0w$aXN#v`I9ycJ#Nv7&R!ehK-!d6YM@QkWHhMStSJd~X~&0y zP=Q|1Z^Zw%g7gG;$sv700jlca9-OK_xL!J0J3+%e&xA*yYm<w&<9Q=dvlhE~4*f zmEImM!3KHci}x6~sFMyNBvC18ykx$a6?*HhEXWh?3 zl3S_(fFAL0d%7;YIVpQV8(|Tpr$4LKbOUfRT8c-Fcxuy`+p@ua$E^53qMT+cTy+QV z9n)3Giorqg95!!rj}?PZ{u(-3)cUlP(dYB<-tL@-g*Y4H;~7iF6jp;dP)`krVEkEG z3~pDC_t~nK*$AH+Pp};uBa7hb2 z63)L4?7nII$lV!rhpRG9%A;-zz8{6b}O)0%mo z!XCGrg~vN%1B)L=0F~;fZxY0_N%UXl$x_o%OjGX+nvu0DZ)GXewjiNs)pN?5};Gv2Sh1i}L2ghQlVy zM#FIn&Z&OZ#RKQ%Hm3>G_pE&jgXPvGo%_vE*>doZ<&jX-V~kUp$KexCtVJzhvUN^1 zzAwjr`}AvPoWw3H09+Z9d00N!wgHx~Zvhty*+4_lMLmNjH1wTRyql_rJan32nw)~1 zn~Z-{d2cf=#CfA%=e0^%j?MV{rN?`V2gxp{Oc#oVh&xaBerdEgn~wv5OGsc+Z~CfE z*>G>Gv^6(zwpSc$eMqB&H=X3i=WW%pC8c2ddPcn#xL(#$VhXcwPb*%O6>bpwqgSiIISQlx!TOrmE zef)ah+G&h!`Dv3#!xtS>R>olcwdX$ygoIByW4wk|e>^{eMfuDg1F!*$?g|i{86i0l ze9kRCO3yXTiA|8)5=np{8>^6Gy{&PXF@l``!+@?Tr8cBXXLbNZw7*Ipxs& zGjIL|$H@2*`3=oj`>CkDHQ#-+Yyfs;tRKPfobhMY)x%f#kKn?9+Vb1&W1H%DtK52p zxOhv!eD~gdE)cxBb*G8Wbps(yURT=fIw=ExkLb7!F~O8q5q$6_@uV}i`shojwrbL^ z!$JrtujplUl`12SoxEaH^IjS-6V&a%M!av~xnkt3^!QWe3(Bup_TEm)esnQgv-JBt zr3Sb0<=2NfrC5ZFtH)y<4Evo{h6)yj1BBQ)va9tk6+IYV-3Zt|4nw$~)|t#MysGD0 zD2=a>XqCl(=t#3$(cAsue)^S6Jtf{rS>oaq>3f$2IQiapS7M~{rt_QXR=@ZRdEsWZ zn~Ha-Eb*T5am=pvUU?8Ze3$*Ej#(1@qXDPxMq&zU6$!_;`nb(>ezttOIXC@_f%wq5 z!_w0=7FnfUgqGsGNt5b5Q;2^10?kq;K}*oBzd>^I05*lH2$0}E1QIm2ihJ!}dMdRR z_2`RqfvvlYgP* zkRX6^ealwmu|9T&ZD;5EUnGrvhonQq#VjyZ1=knRws^C?{Q7e(@*q8BrGx^=W0QAf zj;G95$x8H}sYc$`gS}!DoQO&20q$EwJV<7$F-(|^ zu~tD2f`nGIUMkYV4G_Qfei|3jxf_lsonG+n`eK*rlu^;tia|PoRE3@(kOU)2cKcDR zhf1szhdW4a2{+Me39P_zuk4FmKr zXUw*7d0A#b+jo#xIZ1*8XIFN!=Z$G+DPq3(n}$jQeM%~sY|vSNU%8KA`HnHg4;Uo} zx;IQ&IyRN%<~3N@bw{N?DDMLFOss7Bj^-8XQ@E~%$S*qPRz3g~I<0qGIu)^x)AO41 zPU^l*t zvBtuS2VZZxbH;Y52xdpX%7|M;?qP6V4URII(u_1MxK0>r$@flm09=VMlfQCUzQ419 z@)F^Ql`BQc#^h=%ESwpWND0aIGnuW^Rf9X%i|?_^dwY5U&oRkJ|hsP1MR-6v4eS9FsQqQ&#t*(7>C;$Md{ew77-+*hv9gw!XEJ4@Mji$ERnDQT)*3VN!d^;O;PwxD~N|i zH=F{g@sRFLJmh4xh=D?AZ>azxU)xfPl-_;>n618wHP2!(g!^8Kf<} z1C~D7>wwZ@gbd7x-s1Sn96?P;5JaZ42ED5kF*NR=Sx$`?3DZQTclMH^v$>;(l2mThs!&7^wdknD)quN3hnovp0~NVBCHoGGG+(|N>oXXYx7eYif{45Q ztEN#3ASGeA2r)s5QQ4D=%8>CjYb(lf1GJtY$PHiEn6FrWz$ml1=wL_WbU_mF+YoP% z`m8V*Zw)}+Q*sKLDaJ^R#TMN6*87!3zGDtPJZ!l>kW#BkJhf9@Gvwl+Rxm(O8bEYl zFSxrxE|D<}FW2vP{-kmTj8r47@0)$y$ zD+p^xin34#=>&s_2RR{CVK0Lu-4|n;XU#De~E~e}mnZ<)&r#rAP5sq_?7N z&=gGp$I_=@8R^UqNp8wetL$J!ofr>pO(9Q6cq=r^SrR{H@^2UbyqECch+ZLf!QUxoX8xF_0jocsa@pHQbIsz-ihnzTpd6`H9S3y?8C zBs|Rtz<$%6fc`-hfby9;{W&7)j?u|i3$rccX#6git63~rs(}tB?hu+q+Rw75iu?C7 z-dw_HesdG5hXK>Om=h%a3+iLF_<}}|<~xF%IXOK;oiWozOW(rV=$@g20SB1Rm`t}_ zFfqgAXCo~^dp4yweeLHqpRw|Wq}5|l%j3exX_%r2FZH*gVmlu#ZdyqNfPfB+3v<92 zup|K0UB*=PUL;LW1?k!x}`01_~5}vij1N6!A=YiKT{69#9!qNFc?5E z)OxeCnm5He7Fu`yjxM(3R9E*KJw~fb@BK)+^vLz6{7UeND;GG_{x@*16sR_z_1ECD z`7_eYP=>T3n}IXhh>yoqv%a1*q++^N^mzQ*8s2cSfuc~$b2Iap)+m$0-?i^=BL)+G zeL`YB*$43x4W72sd_h~vo`yFZ+_f(P{Sy@5*xbX<7}KmnWPZ&-YaP(+15Y+qC-6yh zQ{gqcd~ZO=r*|{nbT*n|&Qqu!9bcq){--e1$Gg}^&5?P+-e3Oo94#zcFHxmf{!=LS z=uJqH*bY9>a1@(qc3<;1EhhN9C$}xt;gI1L0B{i{PXqM$wK-EXf%XR;@;Wu~KL0m3 zYTCag&xQoo0sb{%EtytNX!Pt~o&d#K0R8p+{o=p;hN^zFzxwY-&^ifP$xzjSq^18| z37Uk)FSGr-h)4?dUv>JgI{mYwA?wP2z0-eWMgM=^CzO4BldisO07jIOk^;pbWWR#XLovLCV#Yq?G`Qe z?e9_@-Ptwe3i@u+=;B3)?>rWXB!TFLYE7-qo{ zuNYgUrK>SA1cBHHZlA@^6a8+lH#SxTvr9TMgzs>W>^-3?xeeuuR^PQdUlu@zdz!y~i2@0R9lj#XYdFQtzyRdFseY{4W>DeNu zma8>t;l%^Oporl&ZRexy9Oe3B%VR+ip3T62_hBhf;wdlG6f>!@ckW^IY9c%OYp?yXNxnq^mX-SqVQ3~OH^6}i1m z)xJCweEqnVBT3ay~-E84SWbHj9W9|mEMi`Fb2kEc^~j?8F}5&mJiC~RqsvAzQ3;)oJBOyf!h#T z#9xD~s-XBp>9@zb&3D_B3aCo0eYZeubmli*v#(e#<2cimj-9JL97O6Shse+UsLflE ztIW42^(kNRLcP)_a_+Y~K#Zf;j>FjyIqfCK~H4dM+A-M(D3$i30D7^_pD{(WA` zc{;L4V3PpqV|8y8SAtdsJ*pS&mt}+SUdq#VRvW}L(qh8px@=}?&at#Yo+2lRvK;I` z(uVucs|?DyP;K;-!;czXOU_1sU&m?S+^&nCfmaVe zkGOp{Zh3;DyOw$jYsb4G&>(!bK*u>gHeB2Oo9kMbMghSB+;Pa|U%4_MUmg!rAYnYX z+?CjrcAJNKRDWMaL7ZO4*i<0U3=Tfk_^saDp1L_5i~E?oPF3l;C_lWeOj@d1UM>x6 zp2nLnMdp*-3HrV1>*KWlZMMrdn$#a$%D1(cZfxllnwdG)4$x&4IgWmXj&^xpj>pB= zl->1Q>*}$qJtQ#-DszG2Q&I32%N5a*PQ2~4#BVMTSkB=39G;sElsU;Pw$-{Z!Fv-yLC~x%J#TQGV+^ZmUFL$1 zwl0o(X0g3KSNo`Vx)}7p=iOyUgI6ph7^Qu&FdZm^a}1O_wZJrSUj0H4Ks!IUR;Q~_`9@>K z04}#O(l$d%z-xiyZ?;N}scUw+?$RW0iT+*9_5)w5GRt`nI)&cS7*zq?=zOtDKQ>pc zk$5lG3$?WvUb6-l8b8*~fN+{)zQ#EZ%Er5|M@`Gnx8{^gzsuhE#`}EuUA10#m?^ME zg@m*DtkoTU(S}73p=}+jlAn9EFn~VAWB6P8@aHe$k&~M4lK=-JjgJiLOpqAzgoyXA zMyR(Bt|FC$k*6FUFPS?P4D;LZy;-J^HIVoKG<}|{ELe+n)`O}L!=G`W;a3Z@IQ{}h zM3&*Qo zS#sU@d4zGiwtOlRP?Yec8;_eqnmlI9WOHM54TtpijeO2#4w4sN1})9mYk-$UWp*vY zX1-Nv91`?kXSs5bShVemGS_S#dr@`#(muG*ZRR$rZv#5V|#Ku z0V81>!BG2h`@L+js~r$ZM;O+Brh02EM$=|Zo=wfD4at2Y;JEsl8~=No`|j97J#|u+ zxvWMEkWPV;xnZ|*6^TB{!!n5)m-6a_dKMbDS%F!%cu3N=AJT*(-^kf674H`xDYaUl zchKFWtvyxXq;$&_yZYSd+(H15)X)*g23BpkZg3Lkgb#OFn<{&d}206eB5@=JGODzb2qZzh-0Wbt=e$_Urcwt6~(BP*qIb{JLdTwJx=GI~3)WCg!s95Ka^ z0i1F;tz4Q!ZQz-;cS}|3TCA&kyBZ@>>$q3alBMfD_E}5e?e62;@*yX zudKhxZyg&^O8Ufd7$Qpwu9Pm7T6t%PhICt3#?J$84O1tvTD|(ixRw5M_vQpR0U&*O zM6SnTa3Pcz1v=H#`uVq(Gj(l2!OnPDxTsbg*jOmK-YuqsMd=tR`M%UpSY(alwd#vARv~5I?knnZrguw zZ$q>T&E6(#qra5cVTVh{4PI5QOomxsk6s7l>|A!k^Od-YF4B6M{PTL=`AH57S+~?` z=4eu=X4$0WM09mykc>iA@9k!a#%Jw1UL!{xNx`7iRs@_t7&;RoZt?x2rt90*HIa2a zCoQW_-oYCifCMK%1hsztoCf<%j6?3`aMDZeZy33iW@b{mg~>R;%z9;G;EG(1Qs}yqFo$c;;&s+Vw<~rxQfX2b!r9Uf|tx$ zY47~bTkiW8N`UI+cEY&JU1V|Gm(>!b6qSIltHJYu!v+G7GF>lso|*FW+uF=|1uEo_ zECVBW&V0Kfx9Mmh{o@rIJ%V?F*Ops$MPu~ZTJ`pl4WQ^3m#@YKl@BLgJ&bBC2h>-y zrMTs6&(D5r$iDH|gklU}nqt&Z6g-J%eRfYn-_6Nemeo4|z%*^mFWMmbOak>>`uN5! zSs6ybBq1+y@0B}(vmFV^)$2@*y8zq3+cG#6eY7}A3Ji;IlPRJh%Uv1<_3k*^2LhiE z8w*YKz~O1&mLofl-7E)$Si@hFgIb0FfEkC>27F9dM&Du#!w?qqihRZC`^?l&e9yS= z2^vcB6e83YaON^Pwx!pb+s%Vqt3D~9uZ-)5^bB~caOMsBH>urE*tqa-$OXw-ThTsSgu9FVW}TiKU!(B_y&nP^s^vB=mv86* zXmR!S=U&t5>TXX*=Xg4gdM5p{I{-d99-;4iJ$7(B`$6o8rgf1z_W2RHuUAchC;YzJ zrLlc9X45$9)_N)<--+UpcX8M#)A**TbO11y(syk?-@YhT7*kJE2o&O)+(EC&qz2`W(5xV2&>p{(PX7~^qH?8mc50uH&`u#?U~9#()osVow9 zPkL>nlOR5cCXv&C#)n6XI3Mf&C$%b*_kfOdh$oqsw>diQ>>$szN^|5lbE+-~Ru5;A z_FoH?Zo%wu=f^)eBlJurEqXe?0l3mz`Wb)2nn%xBnEE~NvX9EGefn+}X-Wuq`Fm~B zR5)pN%bF2#h3A6&)$f1%gPL=6pf2POPTyxt;+(=G&C{YTWNga{9^{k~t=ist`6WCq zF4OvoRH`Y+{|N5&xl;0pb8OWrpc5p8R5O(H6BMk6Jc-r^iFTR@b+dA3krAiPtjjr{ zRK`iT8_-VS1n9(0lUV)Cx-z?1Y~@XwBToSI?g>D!l+rbfE;J{^EJh8hh|z}Fl;wx| zkz*qDRr%j)|2b-+Jr&fH%n{Ltn;n}nZ@&RlyT4|PA zuBPnV|M0_qKjXiv@egW2QFGD{|3;~Nhg2Rmm&^lZqR10s7P=(ZUxQjClixNiWk%bz zJ<(zTX8Nn0`Njd@fXxrg>ZCwcw8Y!um1r6(P$suHTH6z@a?;ujdl;1A!yyiFeo&n+ zyIUC%L4~?N6SwF@3awcI(b;k3EcsMvszsUIAxEftjkHsr;nGL-kAQ9 z=U`%WfIg+FKs;WS80#VQ^N*7G+41@KA`QT;S>7|+j^ws1dM$2!y9q+u<70M@4qO2D zCaLyC1Wb=!Q^MZ1v zKMFI_VwLy9-&R42uTz%r2jJ*>g0AVPUWs^a-l;qwh>qB*9HPy~c9NMHEZqybIce+Z z9{>!=On#Z;y)5DT45pqXwAlJC3U5fARN*;agT03Ww|3vyG=6WMo_9}M$$cfB!h?~x zw!TB9a&XkN*4=h*7c^grgC5)J;9qNVNkJ?l%{v4Enbek8QPk@JG>$s;p- z)UOcTNm85q9wtl6(bA&A0}onWlGvS(jJ8|P_@ENgv9SLz%~?SE&ziZPXR#RkJ`EXKUlYh>*RP*e zGlmj7e2x?bo=l7R&?lF^kBV|=>nA7DqcO3|GBm~~%Iv%CIUxTc_{2#B&gz2DcO$AT zolx{$K*Rw^kU!{}azCYrqp_%(Ix>_lM$-YcLJqrZ6?5JB+PW;IRMw4cq&RY zIWrQAh`^8Y9#qm46EdAgH{gh&u@Pt@iC04`cx8f*Y6RawCm}2#K94%Yg&?xasEcx| zqSz$KD;R;#Y(OF5=ksEMNcE9k5bGrdWWv1Am%$4mA7e^ z?-<}s>6RHxPN#-OcLD&?Pr$u_Iz*%-`Fz1_I<^L*e%zk@Z%70t2cglFLG~AtSaFWe zy_2Ofi4^SU86ZyCO~wE5w2^pXqLChpG_*JtBxK`tlqPiuWA4$m7W_*)&}sUr4tba$q<;VZ9!dAlZ=IJw~yURjb2U zz2%s#zLEjwnPYKM*5a)_ClYp(nlUA(CYbZVrI5YbfQmfpP3I^m*JMa8mxLAwgGO=t z?6St&SW$gbx-Pos`;NR;)tL!Vw=MkX-d^d^GbQ+|BlI}vKI>L6s6bK{+^mDFRVwau zdQKB%_psK=QVVQ+{LaDxi%iZcnNe6~?|1sk>Cre5&bE!Gr8UyRJx+=nUSufwi(l zVwg9oBk$V<4p3n`Md$aI_YVOG+Nk|hU5bt;IW+Cgn4(!Ko^hA&ao`)4k(Fa4N?Lsn zBi(jf^z_~%G7l3-ozvSTF`P#qZB@&LsM!~ip z5h=o?)>2Suoa{Re&%m0e$1{<5rk@*$z9I3-%ws3`$+Aei0u)~iSv(a*wT^P~qBtaA zW2b#x4(ftW4y09zLXx1+WbN!upYO zp~}Yyte@_=jTRsb4OE&w#=a_;##nTb)Us{Ug5d%1f!rn(}0tv zv8Nrr?GwARy3}KU&C1>49P%dWfm}h-qO!w{a_8inDD;cNoZ((BWiO|&Zxy+ko*8F& zU&d~tOF`iumpwjr5NNT#QAp{7@AJw8qvY{_(uP`#N&i>7JYJ*ljQUNe{WzAIT?V9^Y)1M)eCX zeV>6;ossQv8S>&b@SHbR7VCN-42WMJ6Y@WF+VU<{uAENAdC%8t%wIL9F9R47xv@wi zgs18Q10!8JbI{Rsf7wI)$&Z@pvVw@Q2X6Wg3|w?kz$mx32}9c^K8KqDDmhi2(d1-S zX>=9urYfLb*lum^h*c(dhHIJF%pGT6m%Z&Ew|V9Fm41hAV)^e6Yo2x_95rb8)Pe7M z<`XSX9YH5Bb8WtZk|rteWYJPN?Byd3{*NJ?VALO zNv+fGbDPzx?r8T}md_x90AE&#uKIkGf_#K-2ZYP>qf1<#l0eb5Q*L#iwL-EaKT3h3 zg~)iEkKG2&fO}-1gOFP?ykJ-Nb6>=loA<|-GTMmkyu*JotF}zF;@oazfBKR@Shjb? z3;Aftsme|EO3o}6V88Jue8b!~Op7vklk9%#IB>UC*S*#r*S&gc*Qrw60D9YW$D^G4 z?aF(N$6M{t=HqqDYI1Rh+_p-Q5CuEnH;t?ctRt+f&>slX1*&`oQrpT&1-EYd*0L04 z;&1-^A}HSrLZ)nYH@Z2V~ek7!pA{CarWNqQhz~k!y23Ju_LmJW`6h^ z961p!Yk&_3DUDwYEI?hUex#Zbvx+m&5VAIQca7VnIbWHsK5A1sYTJ%$v?LH!{Y2B9 z`75jAZu>SrdL>*G2nfZ1kp(shR+km}4=|eFtbZH3-0#pMwW8i`F3Jlo9&yw4u2-K2 zG#(m@w^u6q?VIZU*f-nxu;dbbT}Q#79a5InsPh&>*evLhi_&qz4y^QZo5nfm!@Smv z+3M0$0<2m^v$9I&i1$0)y zuT-g{C?QWhSDpQl){R&y?`fRtaE_9VN8fD6NW?F!*XPtTr74xOc zt4E|WRn0!STQNLNeF$3vB`w5|H?Cx5a3AE^tx@ku5kE9o%^TO-0GkLBOK!kZf0^0% zIYktpmz?KOKFfUiIUjVr3`QGR8cV09a82n>a`&MZ{YDypCQU)n^QoWulT+JtrDjX8 zX_4^4Ms=wUe}hRqx%FP=(v?R60)TnV9-6|WIaGzOM_`;AH9mQ)M~#0_H1|%yhR5W7 zQ~0Cro2|UQ`{bzPTw-m2x>Mu6?V+vqj7}3bFSNp9$kpJ+*864xdc`GQbhK~Tqzfj) zI%9xK$FAdYzG~ddGR`^W)%@D+@{=At7k|J*ce*yNy$?FKGx#kmRr6Uxy_59V1K>7G`cTV|C+{-ooz1z<3zS#4|KT(eR zq~qlk-~?Dhdh&=|1BxCqEXqm*Cs4AxbU2V@zly_;K#9T3kGXQUel|P$)MIDw?O)C= zK%p|7XY;QfuepSXXzEnOoE9uCF+KIZhC2+E^|a^x5eS^(mDOYz)} z=ak5|kcS-R9v2;ur7iNQ+sTUYkd)p&{Ix=14eF-Or5DTh_(PfxQTbOC+>fKFc_jh4KI>&b3pSvoRNU_8$)0 zl3mwz8eh*FdFyXRzy#@x%7Z7!4bLrAf^)QWnI;PKyO!F-+0RgB0E)h4TYyoMfT(HK zx71=6;PytQ>GWKbIZLN7>#icf&|JB+*hr|a!u5mlFpKSirA>9+7dLa>qd@C`h|(aS zVg}`%>L5Jzpef@BZB0~?8+1cA!A^HhY*Q?GLMR-0nT^JLR9BU0mB>_wnNZh!O4kJny z-dbAJ7)fPR7;13Yr=BN~|0PX0tZ6h&IdXd=tn<4sWBa^n`&tX|G8s|pB(*SY5yFR) zDSaMo0;K34H=XfhfN-iBL}Q_y;)M1p-tm-BQ+#qy{w=FbHzMH_SmqvMt;65NbfeiT zftbJ#lg{!5L#U31wGZWJ%SO<+tgS%#(xzv#NV-O2C%;5f`huSg5Vtg}IAJlrDw%WN zX}T~n5`~XX8v+V&7%`Wz&!UTF+!eF!P9_L{jz)~`z@s+eg-*22AOMm?iMwxL!lAmC zONoB;Pks@XVtl~K_m<0R#y^?3Qty7X!YM4eH|s-w^1XP#+kts{(3dG7R9S+h>Vy8h ztQ%p_7wiarD3HU%h20wdjPcVOmwT9BO$$pA=I2P)K$XlC8dS(Ua%9eFewyj``MK{` zgU;@oSxQNH)Qk$Xug!&2nJt3BY0_Hq zxmcLIE!+L{GX{Pf0;*G!5pL+yidnvTS~^{93}*4J^4a$ug@nHsEjz-C8aI)O71ZB&||qmPB)bs+x;T1NpiYqCoKb+9O5Dby${2Vyo2 zPtCE&t>8SxjeA~m-`qSmP zVHiMqsCyNrml>+}0rYs~%L8z@LZbi?@_0L)X4$%Uy&LkmVM&}6^nz1G@`2~#fnrw$ z`(2)IR8+jrU5kfT^xD=2I3|dkSOb$X{1ro6SS4TC;Ln|ZKSh!U6LKIHmjh`?`jVYA zQOjE!N39~Z?f``$5mC;m;al~cTqjj}O4B|XLO@Hdubd;=mMXXa!I`iZ^O#%I-YQv} zBEL?bN+emtj0%y}U3>HW?M^hMv#_-~wQHC_G-c!?2?5>8DI;qDP(9=*wdQ!{b=To0 zbTSNmFnsxoZ z9Tcs0X9u-tXdGOjc_R?X2h&O7Vo(v=mI~8szX)6#Rh{_Sr}$+(!5-zMS1dtI-F|~f zhnYOCDvK;iooRYD50 z3#5pi6kzKoQppShJ6XOeaT?$PZedXAKs88DaONew^=p7NVuWM|1i48 z8gDsSPrX$#yz*dG!%}6i9t+8h)krnF*P<@r=Y#AI>OBX#0RdFIM;e!9n_%R)a2mC6 z?>lNSMOofUs6TQiZ?SaG-QkYN5xs$V5L*FQsbhT%MiAk9sm$B6kA1=~YadinMW)tG z*^kzk>KTofm^$ND`Si0g+hU^0!?ZtbH`S4D$Dd8%wSt`tH+BF6deJ`L-a*>Zd*j z7rBl!(B+=IKvQLhlK|0jZUk{LKM&}WwU^$}<_&h5;+6fnF^N#Slo06;yOtInsrvI8 zL-kW7X_!-B^9TUI1bMEC3YT_-q++uL*R2Gy7FMD%247Ah-mK#jg(lSof{+)XIy4*% zV26shXfVj@xP}+zSM*r-u$}x-=?;3l+(7VYFvtM~9aPOlhJtC?wkV{PNq0rQN6MU@ zXKhgGs+L41B6b3}s+gRm6|nOnOJ!EA-A#K;Mrkx&42WvhbC25roS{pFo$mYs4oEEJ zaaqmlc&0G_WY5Zt*U&s%RPTdqr99L2X(<~%+3H}420E$4?Y?|FkjWUL&CW2E?#RfQ zibq{l;%E#QcUh=2%MTw`tt>B@iJ*kk@~8Fc_bS^v*o!X{J1Zq#={fg^((4?@(j0^@ zTV04d1VRlstRKK8Af?LlwLnFXmS@>DwORgUwM6}|1P_T0E`USh`**FoPUcR6M&EO*OEKdMiE_y;t+>bOj#FI8tx5J|+{yHxO9{ zPY>Gm3>(Y5To503_j|6E7Xgs|@H(ETKNSRo;Y%iSX+TCcSs6X#_b?+b3EQ9w0lSQpl*}cYjrO z#;&K*?^Qnmg7z#aT7$pHrG6t{+omFZDO4E(hvsgFK=tGY3mvGXp_SVk7TI~Dhk#c0 zO0c%cpltUFpOtrXATTF-ELOL)`ZH}oycCE$tJ%$GJF%ixt*)j-qoyok!f48I$b~Ah z#gBxx+gePGWU-Q7`*O^?MblqC0A5KrL0a7#K@R=XI^7Fu^%mkf~-6FgdrMAFjO~YZ+gj2qeBC zs!?1F)ijurnPLl0@*6(32K7feU6F3AH^5$t-DH^rxbTRuVK zR~cD4U7|LXSId3EF-Ohdcys{U@15w`%KY#-jEvtPkP?Js{{lQpl>_Uwod03B2*dpS z!;as&xJ=<_Pv*Cfx;uVrP$sgP3*DQrKge1j7vz{(R=QS+`Chg$-x`&)1yC@%T%{PmB8n@(bnrdFq`%zGVxFF%-lHFn3 z?#|TaXIcFY2XZCn*}g`d1fuhgusiiNpAs+!j!Nx&-U5_QNLj!D&%hG$+PBV!PfXwd z(ziJ;JovSZuMbIM-2FDMVtA^cB?u%1c`Pzdf{{X&%{?nHF2+S<*uO^RV;S9NLJueS zair+!QDy3_!|qR$q>cnSr?kwr+FHcu#N93>V(FxB0ns3ioL+$&S&4S_Yzsd%<_}ae zD@MjUef#nxqdX797`GgCJ0>7H4-TYsC~9P z!ef&PjF@vPxTFehr!oN<#emsL;$_kJG*B~fEp@`Bxd7q)TUNQzT?`YcdHD(qm&(1l2{cae0@L_EzC-ZnYf?zE8n&Z z>IK+__iuL{hg9;fhBNKw+MCGhtag;!V^TW2MPXqrlC#-bUh5_tpP1aI>V#+3)D}ob zRDk6?n;z!|?MOJlh3>brYP?ys77S*u5pr>V5hU zm4`Xh?6H|h$8nfV<+-2;=nwgx541tRzG7|Aea+F@wuJ@iiFZulGT956wi(!1mq^H-4Uj)_ml zD|2KNT8Z9s>c7v-B@lszDdCosRm5>c5c~4A(jqK0wwB0%G?++WAf+jKW{XNk2uhaa zSlZMaH9U_{br)Xuv~!=MjZ?zR>OuqehaVL}<+akMrq7U$6xxX(Wqpy}3h4#)Dne3D z-Am0eYzsLM*s13(6F)$tw<+P`E*|kK15F?XA|wl>bZUlvwVpap5)3;3+F>`d&-{IC zCn~(ym*OBzW>`Y0-w3E$mynNO=Ju{zOH z3u=>A9h}+1byt(WXjTUgJ@jRyjJ{P^!OPV1v*c1AXBj|%96uzMF43E%kTgmGUT z)X3LL)M;=SzHyJ^lE&c{zm3CF1LAJsD6FDSG&na-2tE1Pl2^;vx2VzRXWW28zIaG= zIW@WHjt+$9r3uD$InO?lfkZ87&ICtl^?46APW!F-bf~3)wzx!mI!&soVU7p?3UF~P zNSz;!q)O49hzV6@^T>G7T4<_9ZnIdH*>*pOVKZ!W;GB9a4CT2+H)vs&A=zRQ-b)}! z1oFvA$>oo9L^yIvNPSO0+D0A*PMeRQ`alU@!3uBouxLR>Vry<#^}AKe6u-EQEw)@| zw4PMj8VEU=YNpK5CEzespwc;3Rz-Xkl`$}O0G=V9^B6s8?XF3|ujaW-67>7Zo|Ucj zK+j{PeQxC3DGkfbb#T4|!_X(R4WzWy-*6XSaxZgde(->8^nY^^xn^ap{sW-DhoeE{~T?T60>B zJFCci1iK75Tj5@PF$+O!fhf4w5rL|ia-I3WCFqa9R}u*jfCir!1OD2`k(6=G^M;Go z-eZmDcN#0R=;#2zg&%qLCg<_nK*Jp58Vj$qM;y56?%2l#(ic@)j)jEy1fH7VWo>kCd6g=_uTwoxO#w>VW?xA|zQGEXEb6!_C z4h6d0)dh;rjAZMUW8q!wFKkqgq*n}s@_?Up->JqJQtt4FdDZg7BrV&`H6S)$L*k1u zKor%wPujlpFv((ZzeESRoqGu8R)F)FhD8siBOW&`-WKtp$Fh%&$zYalJFp&TD+=Ut zQR3^f%)@y?w$ME&HOunl2wqUXHN%3Sq5=AqW1#Isr@;l#J>JGuZd?0!f`-k74R^e} zn*ojnr|+^o@22U=VdEHs%2k9}Lz%`sv-2lD6i1CJ#)#sQxBAtXr?U%`1KelICAllN zCj3OAN0+QionC`D6xqCb>Y`W?lCSG-7Y;+4>B|Ut>=lMcl&AzalcLdX`UPgAJS)O- z=WFVI(EOv=539W%@4Qj-(3dH`>BWW@Q8j(ZJ?ud6YX7QX^_oLVLu3NH5|c>TreaXc zU{h>dvP!Q|Sqa!*X4Q*nD@$flk@2V&R6N%zk9S&*N5gIG%R8asEv3RBGS9V?o0Xk; z4N8QOzW7A8pHa^O;mzXPKR%o`?f-*9`G1o{JjWgk?Klr{&;po|&Qz(ocdB!bN~RL+ zdVYAFyvTo}Czp3Q5s=3KKsNn+Pm*>e!0d$8c*j#lk=SImCsjO&gw@o!j-blT?b>lu z;?rh$L;V7~2HV$2lvMVt+~*Hms9p(}fJF!f6#%*h-1F=k0=uXMr4D)(p$k^1`9NQg z6UNJdS*Ek;AU;~KC6(bbh-UM~@WO1+(4Gy!)N_aGQ>sSU-8bi>tyZH^TU#taI{5mv z3bYaPblGBaBX?rI8s9qbLJAMRj2CzVaI@N?W;z#W3!OIZ>^PCpW43tJsu)tjlJh9y zfDdk3kbYuw5>aWo8kZ{$0459HU6(kwoAxEa!4M zR-HgUg2ksvkcu*JY)-stUOx-vS8%LOD*E}QVIo^U92yq$IFqfwO0yxWK>$gmUrwhP zeXN~Mu7RHBPtzelf@nQ8yFmug+L8Ga3`t8s?13NwU1|&%_q(%gx-ihTq+b}{du*Y$ z2XtvN%9EiB)HaL1R>75nT>i!qRLy}Xi$EK=H{nQJpb`8D8q9=kki?2QoCc{f3^r^a z$l7Y8PlCaYw+bmCIKi-RHC{K8Gubr%XHZoUC5eb0^F|0S#{!V*Uo zU`xFV0W&4=mag@P^>BKk7yAp$p`GR#pqnY2!g+-D&k3ct9tOtl_qQwJdoH-<7x;WF zRw;M4ZVu==KJz5OL`GgczrFDO9Dqbwyyt1Q+J&_u&3_e93CDg8?hVap^D=PS3s~(d zy0w=az4mE zVB~2IJu`c-=f8ilxkSWf?HnjJ)r_b60hR{waQz;d`>B-w+4B+}k32RBpUm4zG#Vj` z?OYRG;$(=_G|*Q9G>r|zBiwf(dBF5u_!ne;%zUUDKiPXtoCEMJt*v&O`{R{|yK9cO zDLpWtb0iz{Jps+WzY1s`+7i18C=HiF(H8W8&~cKy|1FmyGhy}9yU)@EL`HK!B;cAF z7w6tx1wLuNlnx!t5TfKyt9|S^gT$4JZBwb0H>hdL4n%j=-V*!3a=$oIq?pglPA zyFCfbncY1MXyhG0z!nL>q^DVA?<)3H=qd8L_LvgN7|HwC-XNrgCAE5g`e}}3H%hyZ z6KJZu=L*dq?_`#gteQ*6WlD6SKDAVCUEHC#6yDc4=DyCjr!ZW7G_1;e{BwG|=|Ys9 z-#u8I&*5EkE%W#Gos&w;#w91>-n#) zJ|EM|H$B$Ao!8n}-M;KwA-lHEx(u%N%?JDvDjZeADNI)&B4Zd8pz^v1qR#4Rry=yTs+dS@;vvlQeB-Ury-p$_(UD5a&fvxh1RME$!KpTzGn|k zn#FTdFV@&hP;BNG{<{x9G7 zpKlbr!z{&x-rg<5@6x;e{Ra|q{%8u8&zp>h@~^K-_8TdHE505ap>l|lY)byqi2XAW z|J6YKGZFuDEt4&}-9P=aBmOJX@sDZxPZnv{g8pNg{xMDe&dThVn}3}3f3-ONiJEqu z(|`EzPt^2Z`K^D#*Z<0I{bQQ`F-?EBpZ-5TN0=8M03;Qq;}`jb51V5_B2EAww_Z#x z{rtBlbf3H(IRg4v*Y_&7=(H9QlhvC{9{1seAKn1Me9nbK zn7}bxMX{|pmia#C0nM__3#L&OLmm?u>CMp3I-tui;8_U|b_8bQAnu~bXw!+C7+o@LZ_ZnHyVX=;kXxM-4Fk5n}X=*WR-wu{31Nw?V~xIzB+&9;-81`T3wbvkut*vENI z+;g1J;5Pti-_cEL@xAOhS+?b`(_nZ9TRrWZ#@W13DTzl=Yx(%81*CNl-PwG+uY+ENoZJ`(fn&^-Ai# z9(j(O^Y+cWveiWsp%1HGRs%97jpt?so#()&X4&#+&-@~fWG!CNybSZNj?~+-KH7%R#f@+C(ounh2tO zoLl{C@E*&PbZEkKpvy97zzPbU{!Y`^{Yi@E(AgrLZ1fByBmoeIo;8vulK(o9yMqqY z`atEyV$cW4ZxbjvI5Osl!_ugYAuMvw21 zuDCi3m=QUnGz{E}t!IiyfvjWcjR;+%c{`2mb$0|W3B~dKio!@I8=VAk>A88^sQ2xH z+s_YGA2`MhwQiPlm-O)FtZ*?Q2=+{$=P8>r>Sv|V_t+kf0`=|ulBIZn7E&kmcBk>2 z5FJN3cM1>9Ny{gp@3F_s77gbL|9mISK5}Fq^WoZAwB`GV$mB_ZlUipZPTxWH(u9kTqX~Q zDvb6$F0bk6nL5q0O<-DIRvqk0X9@!NbRL94QYn|HRcvD9vGh2PJ5%|K%D6UAoN#Fr zXh~dHRF87(&>q4?-lc5E_*uqUO76-UFUotI$f(Iq+zbB}|s2&o;o*0&ArO_OO4i8@>^`wmRs?i>|SR8)q-xAa$ z*mqSDflzs@c=;oBFb5Np*V=>Zictty+XV`dfE&%mYJ$skcMJlG$0_eUEtOXW5bl?N zVg~fLES}(w?~e8Qa1)dU6vk4qIkWk)Brva^3T}KA^WWr3-+_vw5;K>w@cc;8`%WSX zuV|lAW@6@Od^=v$Y?*!8az_shf$_$&wrO;#v4`$3pdt7x2~Mip z5_0vNgN6e|*b$Ru!`$;rw^~N=xI1n$6|-e$09v>?bEbH8`-j;;eK_uI17Kn^wTNx% zPThBlm|y{v+CGzXEr(W_A)Ex_s|=k1)JAUh1wO%#q^wIXQ3Bvh=^9Xdkq9lLJdB?e zi_wpdNvT$nrL=Skes?KG)SeA^}y9oT z`oQRG=IG616dj02H>*Gr!}g$9F>hmV`z2nO&Ap$OD!oKrWvp=zOJ19e>~ z0NWF~GQFvvT|PrZ{no^DpFJ!wRV#f@v1rc@{)-nkbO76d>uPYs7bTcuH(%_rs+XsN zcmSL_!F#?M;*+`X$aQF5)(9|sITHit7gHs8YH4BCYORPOPn@O!K@_TGi}hP^up2q! zE0fM8)Pi2gZcDn)E0G(*jjm1T8yb{#qszTC-^DsxOA@}o?k^`gxk2u$wj8<3Q z>HM}PbT4Eh3@XCGq!4z;ElAA40G^sZ$lECvo`h}(a_Wd?XaWa-@#wo^1#ElglTquO zo#BY^W&jT+WX-}tpki4Pqz=A|Tp#5e9d(~<7e_lfRsn2yOwJQcJ)U4F*HGNQy!gM4 ziJ{`Jp%6@aecy7RxFL|#=z%tC!H&317%s$QJ~r^!mf31Y066@2Nl?i=4RkA1;&Ye) zLeIfR67kV)3uwVMAv8D}g$BybHH8iczGpL!IAAvZ0lZt%dj?7d|in}hc2a~j}qlibki5CnoXwUdYn>IR}o zxR_kzM88Xp3hJ@WGBgt1XJ?#UGEom?u!(+!9bNB+HmaX$%Sexp0JW4i)secnB@l^? zpMBVm&aOYv#(Hw2Qa9U_PbwOLbp9%yj-RLy>nsTI<8?W*e15i}>Pic`%vcif}w=9~99^)Ci0JF~1mQl;;6dw7`!hXjI0F+#o#PE$ba^0MoyUe~i z^;k2k_7SBVCIPdwb6vb8P}9I&JhybaW-9^Wq$^-uJialt<nS@8pod|#nda2QuV91KqqTioq!*_wv-aY zA%8764!an;HWj+6kc7OqVE;E|M|168mIP|>!NM|agS&M4LXbGLIKN}QmXSeprpU9J zc*G50nvH7XopOpE0g{}ba%w2(O%Bob!W9-x+n{Sfn;4D0OFcGdr8v)yamNXNnqjwq ziD2!Lj=b8XSLak90+pa4fy4!%B&6cx-LUPNS|-ug(v!MR-*yv|90a*iGTkRI843-D z8Gf!_*v5SU!MVQ8*lcSpW00ORy#T6L=*3|Jukq?B2i=2k!p1U3&Js#-U3DEl93(;Q z&#CHs4F%+dxdgki)%p>-r{y>l)^@>KQCbI15OA-D2q~4i`3v$KcY!>Sam@wO8-i>q z%sznjz{*rk2Pk0U6dO(kdnld1nA`xR9p3+Ek*@F1w~3w$x8u3ARD&lMIC8U#puE9? zhM%6w5pQL}cdBk`&17^j# zU_!=LjfLmJ3KnX>A+fy{3L(@pFuKk4Tc#E-tZ&d;>zvV2SQd5amjD#uFuTa9Ti~s+ zf;}>c5(xEn8!X&km{?|?Ut$Z|x8EkYUXPV^JWc0T164!qfOTo{7mshjm-9^0tqQE} zazG*hS1wZ~Zg*QLn)~D(O$nc6vr_ZMPouvo-fB|MT@djhVTMj45qp>+vN%=h+|D`Q z;z?%O$95wHPM{ROt=o$4FP(iQ2~;M^aw}*mRE+^mv@wtME4EWNGU(n5J?HVWtceaD zGJ2k!^04RqPY77xa35^t3lK~6%ZQ&3S7(-$H3`B@U@j3H6Pq)3u)Sx}FsJFVE+ z?>4EN*OMz+`#v=sgQ2pCTrFWI37Ri-LOrNbG@c0WzFpLj1Aq#V8mYqvWY%y~$|Q+v z(z$A(Qur;q+KuT9R=3FQzFw!0a|@0~Qf+WgD^JPWnN8LoQ1o1X~9TCU!oGdpmQMFR41tn1A}@qwQk# z^QlkXrvr;5c%yE*ievS+5SHNvM1`M<36LuqQLs2}hkC^ZVK z#_{4ogBtJ4sV>vt;3=aM0%0K0CS{&-i?@Bkl&7%}WFo+U-wd}9H1q?>H3}$G`quT5 z-s`wXjJHAgIR=QsD@m@K-tn_M&e?0Zf>!Sd>S`uR243qLE4`#{Rx1NMxb5*SPy*ynJBwZa*_i@Z<()d;4|d&|)=RLSQjIh6ACnzu;Qrw!N1=XPo0G zoP;o?&B|Xe4w5`mI#ps8zrm{^Hvgk45A-v@^?9isI1KK<6HLP&+b>d$~0GX>+<% zWva~+VUEqzD28k*!g>j;5vk|IlUUvDn6L$+GJGh_O*FXL-)xKyc@^X46$ z!q__w;GeDmhfq+mU~p2NmF<<&w}-MFt`(#5ZT8%x06B zAo9ukC9i3P1cozUeK=5(Ew^}Oqjg0AX2a;&I8WmV7$t1&;a{wlbAXYaLx(PR=&^$K zUQ1EnII=hj0>OpqOd=jyEb-!}K5#Az@a%wWCvaE%w#3nj#g(){oswYI~cO%J_IzD)d_j;)r?wc=HlRkPbU_U;LZ1W}jA z1Hkmz_7|Js^s+SVDhQ}pBV4#MfkV z(r`+WS6t$5V!!wx4rem0I^Tgn8;^YqIXOKn!SMW{G)LU=OOQBr9PSkLEE1X8jr(-z zN*pUI>-z`E`;fet4B88DjU1eV?PW{B*uvMmM}zn6{fKEE$fd$SWE|U!GFp>gf<`-o z!R-tpR2nR`wi+(*kVsgzcN8fLVmZ)pA&xU;+9#?(A<2xMcuYb;Vmvxk+zoHqs9>>v?Ei*XoVvELA$4-f1^dD094pmLuRHG_M=EU4DSWTcqrcQ5 z>C+5OT7B#BU)Gu5Ov$WVmFefYqk~k<6YCit3U&D`R~Y?Jn1z-8WSuFz^$LaECt2Md zKC~tF%B|=En-*oycQx#CxA66w_uA5w=KSWlPc!yYof&*67sIbz-WFy2RSCk!cS+Kq zboRYf`|S+!^1OO3J$y!>b^_ z|IUA_ALjL2_YhS`l&|k$33^GW$kVz4QGYBZlI!l~iWL^6diq7XXWNoRO`GC! zjf&$$y%{GvZB!j&n+~$bsux}MMftS{R{7JWUCFeU6~{|;+?L*oNT1lhe|xMw@8HZp z<*7vU#5ivn^UP=yY;MseyXRW)^Q%M0SxtIY7|x5O+==VBmU)hrJ1V_<;MC(Z8M7g1 zL`cPNOfzRrer}S+3KwggLJJ?mJhJY7udbd2RSKf(oPyX?HF>W?WE`Skq&VjY)<2I)lY9r7nW+O4pA(rjHP$zl|8y}m5@qpOTFo_p^gkZ zqM7&Dqw!jr8Pg;Dr3d26lbveHUvJ;O?d>*~V&maG)#EMIq+RMp`Q^(U4ZZGEIrf&u zMyks?bH4LU+}Ie!CgxI|FRX}UTcCy3D zH*5uZTjyS#_U|(4MXB1I^NSWwgMXT?eSf05xN7r(;oGCe8l~v-;-+zqMSjl%=D7lv zqTjNsV{~;IVhSg3J~Vp!_-s;NR4Yqx93Rbv2F=X8A@z)c*OoPS|!nhlX6~B4Dri}Bpl8^-6=G9$~gNOziUPEisd9fjlX#_ zb)7hz5XVwHcBT#1k}4f@_cPfpAm0(cKKH)eM+v7+DaO$y#$NyH?)|Vup-YqUTFbI# zi7hxR%9M@A`)Rd8#ACCY1wc7Bi&<&oTJ`8$NV4NaMZCy@tA!?yZ)9ZTO#MxaM{{(f zpQy7J)~bUUQo>);u*hMYZ)oG|6<5_O{maMh zPo7}p-v^q?eimK6_+h@HLgHJK$Oj`^#dCOmwgp{xXYXXANnF@vBMXaHU5$1nMW+R0 zPe5>k1 z;+5;Y0)O2#QmL$@&G108?fUJFVhdOID#>?A@@5(I-lv>qdO>#w-?7nsRaj23GMdNO zg_ppB3~iqH?%Di|f81ql?s6bQi>#AVUiH#UFvn_H=qwY_<%`zrTIhWeL%PaZW8 zIbnKV*J^ppg*4Q!BJ6Wo?Xx=~5e^}cv)Q|?DRdL+v3XCO*$UN0uu6eZSdivEQ zdv)Z5irlN(l&`PZQ6-_`b)PL;`aQ>1>!bww+ZHuE45AQ5z|3iD`+gVAy%L|1ZD6+% z_FOcM(_!q1pj-8dhDALXlYnRY|N5$A?h4q5qH8|&+;W>I_U$7QS09*H{@GP>s*f^G z1KV9Y?;GuNp+q4?;mm&6?K3j_kI_`qmK*u(zi~qKnW~?mA%`Jr(v2T4d}MAgUuM41 z*L1vWQv2gdX-l;I%Uk>HN8<)IJZ9qh=KCyc1~xY;Tk6qfHr-xFTUTa@#Om#F;($Zt z)UDX50rV`9E;<8=q8G+`0B-l=k)_&&~E`Bte1VdDhmU2C0_ z4$(t$m?J~AI9~{H4xs(t*4~x0j@0{}nJPx?)eg>A(5sw7~&ljtDac;4ZNVuc#{RQRc#;xpW#o#QqIp?Xq<$nn>?0Xqs(e6DgWp9&cjTK;i8b< zX{)Sr0T%^>Pf13ZM{?qpHt#U;7kUb8UZoi*jrmS$GZF>Js` zyhi-w9i1rY?ZYogJYdt)UtZ$>vIi-1R<4c6tBK1jEF%O-R#Yf@%yQkkcQ3EOw0TR0 z+oG)lhB!xoIUpQ$`!7pqZ!rxiKb5*jgBi+gv#%l_+F&7y{Bv?`eug?18Vgs@y_~?y zg}PpUw+z%1imF#SndIEx4M@4pr`q;!R9rW7`f@bj(c)+m-$Y)mNpoDWQ~aSyeQ(FI zoU)vxylV>Es0NGn58TfEwz2IwYO=K4I#;EA1A-kVJ9-?;-JBvzXCbE#wNZY?HaTcV zHm}NeZi-H(SZ#ld<~H}J8DCg|AsDn==VmPsm27<_s|yiu^K29U#Ydn=7oRQWQ5VXp zR8KQa5gxtq`D%vx_zh8}d(28g9wV)-X^>v?(xC0uo4q1wcY1)rHm-Em)TN=1!iS&r zGtb{Gro;mjm?J6GW-a*KGh_>dd4iHOCKE<<`W_i{HB=Sa3{DG(7ssZJyqT@WF(!87 zI8C?9`9BE``Uka#^}TK@OHQkox^1u~))TFZ#oN>R`NRk45kZj)xCZwIhxgbQIpx8z z&6SHQlXif7HlAW7?k>rE?t0mTX|=&%Bh36dqqkA^iOTiJ_4MVKbVV;7!=ffRAPxnG zFI29e8$jM>P%=db2qEX-2(LrS!I_7V@*Mdrl5G_!U8>V^EWxyq42iLK$rgjp7~PLz z`}Foq`#9$$CZ%}J6N<|Sx!9MOnb{6$2d#UZNVgw9Zyy}Nb`AuStP8i-ll$JqIB%h1 zB})P1;lq-gY7%QVnZKtcyIb%Px))t-Cu-r8U_i)QH1@ry&z<95qqZr*foZ03tNue)k!Hfblf zvx@)LN`T>*XOm(Mkkav3@tChX4g(F^sP z;Z5x7N3yMHC!{u4rbE4n1eJ~)10HOaM)***zi;={N3OO-gns#5C_fZh2)Au#t>7mw+>;cm+=Ay%+3B?b{g0dl*cP_2ZR8bCR zp26oAJ{7C%{>>+fhB^2yGnc8TkkCu=9hGfXM6Yp}q2 zP5ymGZg4P9B0Ayd?q&8<7~M7;9-Yp6LjQ2~vekfBS1GF!YPOdP4&R)1k`3qKzUEIy zReFl!F9Tdcc_ihGoc|1CJ@zu$801~ZaPs7q zj+vWsE4&qXMdzp*+vRH__s*U@JA`>o=7e7H__!QRDNc`xDNzx$?uSdm)#dHkx326x za4?#J^d1c`@rW!L@~J91`=gvygO*FrVphA#{F(yw+h=T)L-kK%_rCSY#>eGY%6Qv~ zFXpiZ2S**{+o95PPgcpy>?&zf|Eo>w=cT_ENR=JJEJc^H!*TL-g*2hV z#Y|6T$)0TF+OHu|^~UM^Wk>=kB675NdYq<0@>Bif>dwBnYEa=}>#*9(PImvp6hk7x zC?2cI?4BY$zo^G`8bRDLkz|q7J|D3wJ9~_AJX7~N+5bH9HTKi9YgyL>923PA6+fe`>4B~7NBCXVkfPu@?ly*4T7 z-XM?}7P7T|Zg_g7*nn&(v-kNRtvUvaAT;A=$OeKrSoYV_W6=w5_-)_*%1>bZn@pE1 ztL9o>AR49pc?+MYvrl}G-2(OZ4pceTv=`vWPHk7{b_~Em|Cb1|EC1#T?sy(x=ei1H zSEjl+HWdw1rF^!=-E`#b>`F{HrI;^LxJlepcbe|!63EmHcNguwbRv>EyfZi^;yU55 zBzvr&RY<;xyaKU5{wgTUQ%=u4P-&1LL+C%OvtyeUr*WBxp=#)++F2IV6de3 z+x83%>A(yar~np+P_yaYm_lVs{gk8XwfFY!Lfa%>(#R`Y8uwZa5pzs{boNTpefxpe zpU+*daJLSR5y*5~3{e!jX`W*Fqe%O0=&^6f(oC-&(V=dGRl)uVEf6Fj%uTkcK*{R-;1oOIq23&?2>yM@u8?OkY7y_PBny+`A@}#D@QFppQ18btE zF(PevS}2CfQiIRcq_uE;g+VmcJ<)ec=GxV(-&jtq@?uXPbD_IXN2q}@bMbgslpX#? zaX^IgNl`_Ph)49LlfXb60ih<>)nmv0Tq64^h7@pw5^J(oI3bt%`z;-vl+-#fs>egRS9F@-9s-7VrHe0FCU z2bPGU{r)s0%%@qvvM~}4j%dB_LEJ{`B)GW6S@!2+op5T(mdru}KUQ8jTO5GP#))OB zxD?$v7eax2fAM-K9bFyatek(voW*sfTd^#s^F9r3pzeC?w|oVz{74$ir{LU=JuAy> zy0Z!WqnjH8_9FYQ0bp$kpGbk9GT3gBzpygahANo+=xu!WWU$BjLf5*u`-=SI$C+ab zVPTI-Ik~u$w)HoHEPE=XAIDriC4FMC*t+kKcICs+sop{b`EX8dTz$m+3i`0fn(TAX z8+w|SFg^e2eksy28iOfsU~qz5ZjBRK|Kv*89Cyep4ivEHs4H2fzv{ic1>8Oxn_8Os zoasY6+Pd$$MMrLAP7f+J)6!&Gpk#ApHf0rYa*>wvEnRJ;iDtZOO`Y9%HP@7bs_NSd z*Lf?wBOTfvquf^+OUtC}_TQ6NR73~BKAN>K8Yh^V9iw3%qdmNJcVf~BV?QZyHD>X# z6t8a2!hs>0Norf<3^*K_#gxZl6BGFrwhgoQl^TA$9q2a}5To7f(g0L~jNE|$L zrLT>yT9J~GvM%ao`-A-&A#X>VpLLZkLXx2+mSRu9YSu6vi|E{6C8^l4Ta-JYo2w! zP_N;jViYX*UHtkNZYFNdw7mW%{M#YO-IzskC5nEepzYALLM2hCom{^r@GLiTubfg5 zthD@ZL6crX(al)>jSW7G$7U*5^5yMk-=0&``mA+ZZ4Abuo5yN%PcMlax@|MWD&wXW z$!}si3!d(!)U0>>&62k%h>}-~Zh6q$E)Fd>qp7qX$;Y&)%Mn&BdvLn4)oEKbh!@o} zcrszXT}2aL=QLxNUm)%lYLwBcDeJ8j$i)V>WgbPJhFg~XDAobivJ#4m)a)az{4~3L zVc*8h!iFu{JEV+uWyH0Ix$@ zEU)Bhb|}N2dzy)lHSwvNcg#turiOCxTnWNEN(V zsiwvvBq43IRSwkmbJcGdbOz6mX`5q7J^I>8q?MSg&Jff-P5{c_lN`z1 zC!UI`Bt{mev08OT`mhxUYG5LiRQGaX_p5v7dZ01wRPcU_VB!FDhIrObvSI-J4nFf~0-hd1ugOLwpA_V>lZ zgJe-65<(jjvi2{(73+Rx7CNMWFWb>8!+Gxmzs;GMnb{KbA%S$~gGhLmf5d}dcjmUs zUj~Ybm(Cu^U(YS$3SaZLh(ket6L*WY)@)0kfqqBQp8U z1$(K+lwRvPW~ic2LAG%mTz*fB5a1shsU~3pl}bSDp_ZJCi--4y8BHOAm>Ri00pz#P zy09TYq+ZAwftMe;?P}9fAi25xQUM3s3*wuJiewHlU~tpdP1YL-*weNC`8`|ZmXJio z^zaW|(q4CEzCepv!ztS5Ack5ps@OA$+!EnC?CQcf z#V#26E!9r}r^@F}?Q32zUwPH2=T&adm4;faiJeVTbS}4ege2EmmQMHga*ex%%QfmO zV)mtIszR06Cscl>rKKs}VXspPr5#Wv3N_wxQ`+>rbz--)mkDkMr0LZVUBHPhk${5t zcV>T7>U2IJS_m%m@f8~3nKRFb$=l} zWgwBlYG3QW0=*dt9PKG4pOuQsOpDb{M|VK0y8{#&J#@;Ui(L!ZViAj3``!1Pam*E) z!BS9zDDrrhOW!^uh_znP;!(@z0QDS56GqCGUChcp(B!-4WKG1$&EhP?mwZtCnsD81 z7x+9~NRQmXF9EC`vL&xr`mP!oa%3I)Jcc|gFJa>H_TT~(aV2h8U>95HE*D;0hwB#T zw{jWc`Jj@S`eK@1{tXa#`V^T%D%T9P7z3+>3w#kIYA=+rp^^hU7PM@WUr zRMvlhdLP7m%7tGV)02Qv`&5j;HM2b`K8WWN{Mu;p)hRk>DNGnrwzQRmw2834)LyWh z-EbR@QFr{-&o0(OALJE`BiL1M_Ah}=yTN5WaxM@?a07{7e5tR@5Zi$ZW^ufS{+IBVD?dUe3toMx6 zba1=9Sw5beQX1Virkmn~Vr_PCteQ!t5g*nFfta!m0q??f=9joLmDiUWraMPf)IU=! za`EtR`!h!Eu!$x=r^kJ?TWyim`3q%o2Yj|*%eYJS!U$UQj4-|&yFANi+GQkQ-QBhl zKY`&ZPT)0=W6eq1?s~Oqa!Sp8gZ4xIrhy`+JC$}m12y9Ks-7#A1Z1DByb6@KdNd3% z_U_p%0@}e&u4e55*by6&T%A!Kp~LpoO-gr1*1R(G_=A;28=bHi`y|Y{0TzhM`(ef6T3juBbf&Pg<6t^3V!_vzPDo;Fe>tRhn4>hgjnEkY*rAyS zbtcHxeUw4$rma<5%0h}Sf28d0kM<$7zi;)xw{k;?9hjc^YRcK~MFLQ!<=8=dYU9pX zKhhkQ7#AJI6iiN@Kk9&CHUI5mG8XKvju&y&W4#7vdem89gtAfgvx;~ zeS;y{Tr(0d-fXaxMY+ejcP(63fKt>hTh1}N0Xyo~TE2sH`i=^`S1N6uZPFEhTdmYt zKeYd(a=>>EnwdNMtG@CnR=rHkaM$nr2Cc4i!MrlgS?I76r^qh zDGMMkHdp>46t>JKt)G1spiqHdT0a|q*dU|im24LFv7F)5_Gbf%g0~bwpq@on1Ai66 zDu=Y9o|cd7kd0`ypv&Z_qI2tw5Z`KpfbXe!cWq9UU|xM1lY5Zt;iAz5A%7zg_{KYB z%g_(&i(3|8=DobG!QPw__4gv(>DJQf6hg{h%r1QsAY*3*1KSzN!iXGSWzuG56}R@< zV0>y!*|6N!0AAjp$^r9fzoOcEh7q{ZoA?0>fL-tOJO)D29{$EH7sHIG{v=MPNInsf zkO}#Cw^za}DHpnEE9?esc-acKgKB!B4F^?q zSp!gG++*(~b`S|U8CBMR&Zjr`gU&Q&*hHxjJ#}E8I#mOflj2%2xQLdFfl&^Iqb}w!?9*; zbUz3ju}x;0+I(OoDJcY+;Tqpf6GOg0X4yX0PE*OE?A$Cpn5JSS@3?#WkgL#IDyjcHg7Zeo z1GKv@MnRMSpQ7bm^iIQsRE)nj#!nrVO`0<8H$8>l5XM9i_FpUfz)vkf5e9>#G8pPh z6~Z2d1Rp@kS>bAOR5YQeG$EE>Ye+Y&htn^BFLN&}yGMVtQ%0RtY(Le1bj1uCU)R6) z%oM)&t74-e3^8QmD5dRarM04#K-jYhlrD71Zf8}`E$N|dI^TSIR_TZ)AJk&j+ zZ*el@0AA}(z*RmP^E!~(+eYb^I!^dQ1b`;C$7*-JrW*BCe9$g<%2~M}A@|3UXttQi5>s8}%hH{;K6c;AK(C-`O)LUDfnJ zN~k>rD!_`WvA$1T=GDOlx4DgaD9ww?5eqhwU!VBKtv3j6EGE#eOcn$+J6!>8SxV~1 z)>Ld2faH5FL!8o`-eIc#={F8Q!DPJbeNj+GT^R5`1cK6ybHUgA**gyo80;SBGh5+@xq-!bg=@4oYHQqe^YmyNx3TQ zFH*~;x6s1w;dy||-Izh4L&)vPw-)SP%M=efAB5rBsES*bVVhtCmNqxPu`O3VzD}zs z?F$HSS!7#hm9}F{g(CUjQiZ7NjT7Lsa!fp;>@e7K!my9;2Kukn*ID zM>dq?-Vx{IxfHYTF`eoVoe{e4;@BrJw=Ac=X{nk4yshtEa-%8ead1N~rd*8B6@^c| z6F{4$v%9(?^-X|gTaC;CGmAs%Axw-H9EYjxb*j-}?PZ^xN(>Cw!ejM)Qw}Gz2^8D- zB~<>^59-o9&jwT~RdulmhZEUcfBSri80oqzlVRO`<+MVw&D(t|Vdxx?`&B4>lNGB; zxyHrSfk2!NKol%@i<4Y=&%Y>N2=lH-nG3sw1#j9YzhDH#dE2Z!6Hc|`j5`h`- zNZAVSaW@t{% z_K0({4F^BGvvu@A6&gsgMHHU+@c^|33Rp7_w^%q!vF!^51^WQyI#E1_u9Ck9R<)(6 zBMHT>=7bYMZoUDc{TDWL4sA`RP2Tn;_26u-SE~)4&k(is3WC-i-g9qqK?p;V_yyHH zh6S*+d-{ClUlLUHAHlm30uWu<8344?Ur9IItdyj5Om zlHGpil7ni51A;KfvZx*Gx+?ta&FJhH4G>wm+IVmx$Nj=b@u}P|8_(e{4pB+$asyxm ze(LrSR+ldiB}04cfj5jXw8e@S zF1(ze8pQ&jY9O`g{8yI&S)6(w?}Nt+n%7mD=ERu@L*CW-A~KuWu>JRsmt8FJ)7l*1 zeJgZR1})8DE1$SsHbN*2;go1%s@A46TEYlnkizHB#?w^p;I2@(F>Q>)EAW z;4kxjDYxo0fgw=OSi*aKMQ-&sX%8dAEhfGPwnN$^DKAESN>3>dZnNWPcPQ|!aw}X! zEKVC?GUeKmwCcfEBtfpVrb-t5kU!9A9uTB8n$?fcRz`1{VkO=v3BPjo4BVDh%hCJASsJo7#5AWuW zySE^W*Pw*`MOH0Cm(RnF;6w?Qlx3Xg0j;pn>;?T2$CvWu z_gFhLF^IQ&)b??M>U@K)3%8rt4AH{A=#k3J?=f>tiiI8J!S0-z)MB>Z26ghN*v3TR zI0bbesv-hg_4aK<(6;*qovOcx9#i4lJp{wS&H|@uf*8faorzwMkk?jZDR|gz!NuVL zivbmk^F)1z?ybgATyqXinQ)@qPA7U~J%P)ipUxo1g!^n|4<@DIkfo50$e6h#){Upt zT{=$P3lD;JqNAqGlR|G?6Y?0CN@LYAbhK_2XdCZ*9r)P1O-pc)Ux?+3Q*b-r&>_l? z0K;G@>Y*N<@5n_+PAuJHV4kEDhoS+;KOM(tQkE@y*&n)ITx**TS)izPg(>94l|0MY z31)h)6(BZrIKjjkvx!d*s5LeUyzNk5Phpi?1_U(iqN!P5I}y*rw1M&_y%S8_c3mgaCfBQSI!z4R%@v{zG9Mb|c)K-*R8WE>*K3wltv15& zRA|9E05?f@hSM;0wda4Cp$-1GbOoNp?FT$%(otpsAhvGGXG2~i?%CS8M$OVekb4Nj zeH>D^+T|frFIHBXb;0vH8S;<;E406}AMhFP-ePi}9CC=7W49FR6|jG*Z#?(?W$=>k zBURPt6u;!_7?s4uK=t9cM;_TpPWN&iZ^kH=rqmIe$2C%jP{v1|MK==_132ztzn|j;lIu z2J;HkRs}+>{dCv3-2C87{ZE1^d$anww+wdTPc`_;utDd#_s)8aU1gS_w3pgKYjvuI z_x6h9YURfp^;DEszLN`gYk5dLGs{x6)oI&v~X;f5hN_^@KL@C1%v1lao8qHJ*&hUq7VDlRt`;rf%;Uiy19dv`1 z+uqI1bg&=hGpy|_kJ>i8HegcE=Oh=0Y?l~1)G4W1dnArti*WcL_cr!GRu3x%Kf|{MSEzT z%9|s_gngF;$5d%*(2gi(6ez^(crOLfZkxJWqPbZuUFJHBcaU35!TVM%|3bX>J=39) zGu8P5(FLnkw9oNvyAzBo7y3L4-)BXmU!y-L&ZbzT)8NZg^0Qzqj#q=W#B`XcsujrI zyaU4KEqTDLlpcV$1wIq$LL4nbL!He_PjbAc;JNXRG<8~`d(;){yD{ugmJ{K2E*jS-%o?_XUqTbnw{QdmPUFDRO~xPE_WrBPpXmA&3G6pP zs>x)YR!C-j{!4g0EwzUWfUf6jJO7j1Uv{i%H>`LB(Na_*r5bvjzc;S|az~>&hv!mH zk7jzTr;XL9?FLKt?!hrN4?h+fKIX2?G6UW_%EoV~8hs5+y8}mSf8{aD#@*#E^y@+B zS@CFaAdIsiTg)zR>mj;_RB;hZ$e#T%? zK4T^T0l=g@;oz@QM|b0;KpJu->IbBmUVaeQZ_1rhv~GK(Ag?6rr}Y%lD;=HU@4afp2-pYOFuSFy@63*j!^l*P#&sC%wvqE;+G zr;35R7a52=yer4((Yoljim$XAouy7+8mk3nu${Eh3;x3B*uSUIw^ItF{_%jvBun8g zL+iR@%4XZ>eJ!Qh3d!ptBO*q4k6@!5y0(f3q8g(I;`#WFkVm`#aEc`Q8now z)aaX_qXa3);4kp>bY^MOp$(rA#}fk)UOv@Dwp~K8?V3tLe$>wBYgHi}w!G9=J>J-) zRr}G>Q1y^m;b$d|cFoPRf9ePTqvZM#&!~xp1t z@;~Qd(X%Zb#%J?J0dl(5>TR>q@jNB_rw?V4$$!Ns`jzHB*ELWRtLH??iZ^6{GDX15 z7rW%OYG2qq?oJDA7d_-l@xgy!^vXBw)K02iA+OA*Zlh*ee^X$J=oaYVoZlKKx6zHZ zXw{47)rPzevW6~vW%sNKqbOh~+1!5+OtK8H3>-`X%nf){1J1eHqSj&_2&F1Cx=KF% z+72!jz`9id9O*+#lwJUNXPw702{oA#U3!~mula^zZW`N<)NLmx2}ob|7m+EFlTX{+ zKP1*6mxWVf^toO+<*ca?3o(8f`0V6fWnS$Yw%>0N23{e7Le_SP2^CES&hE9eAnW;n z1tsdRVr~Ex|7)dq|1!#9;2Mt2=f|)q-&au^4fP0Bxu;d;xjq)(nFX|SS@s&l$JBy9 zcXgR#WogOmMBB8_+Qcvqtjcxg`IO9^E*~G1DngfqE^#c}lT@9y)k@Vkum`#~ynG6aJT@pAAGb5> zSoAHHZ)_Gj+i7T_7I0Wh-@}$Dp3JgAuN0(8Ak=3&p)?WX?fu}jWx{Y?YjXcc#6IwmnWS znqH6u^M#A8H}-98p!m!WRz-MBZ|X}`h!7B;tFK>0#(jO3en%7xD;O&^q~zvqX;%%4 zX;tH6@2-m*eJgKZ`E!8ngvF2iW}BG{h5~g;X~J!cU^nDp%9EZhby}?jF38&!KA^Uw z#N~TSW^}ba^$JAd>gcbtjPsr@H&j?{+R;$W;ef1`7^=oS6l~#eFEV3lWu+}Vsc-ZO z#(hgmu-TL<)?-uZ36P~_d8s$PviQ^%>b-5e2SBs6stSQ@HPMz=;B|tCjgM_2oF5%k z8(i&i6O;vF6r?e|!SyqrBdPaR|tyoIiOi8st z%N^aVmZx3xcgbLCo#-d>pCfnCDR)$5ag&DPEE^~}?d)L=c+1jnR&noH2!Bx;>&N0y z7s*`RnnR{{sSWU=mmLz!*QX-3h`z<2kbMC=t1)u6KNUi1=0Tex|9=x_ZB;`!Fx~i5mD zV@Dj-#8RsxhpGa_Rn_w10ujh5zLD@G{FIHg&1BSq2}e_5k9<2QTO^`Y5X5wAB*Cy4 z!7SDFrIXRr7o#)MJp-5)juB%(vC<=0_n7fxmv`+K3*l}v1wgo~!flk?v-6F(WoJ@x zFgBjN+eW*XSKP!K79|ordQX)4h0o5+c|&kh;7}>EvLVzXH`HsA%$s@J)6PSVKC5LH zF>lqVH|iqMhE};Q1j)INIS|@3g0>73nI}ta_dF5 z|FuH4*$xbC#)4Ri?_Lu1Pcms@*|ht;zP*QjAu_AJu}zHHWKqVWGJo!Nf1c!NwNJ}r5jMEhrZuz3C$RnzlJjm^wm9@7 zp|K`#V-~JelNW4nSR3or*dMc`63ty0&oDx>UASj80}*nW)^e+K?Bw44oVp)spN?_@ zWE6%d4eE6`ugZk!2KFw74-sp3x|?OfcOg)z&vlH3?In>Gs?nusiXj91Tce1|rBlP` zGN2OUSIn8|uJZKpK^6j}*jf>5YMxKA9}8d55ZfPpH|>kWlm}^)lO%eZZddKM_sZwc z^y#Pi=)3b`#PbgpPD49C0yTB-0!Q>6){E71_3z`n1c7SfW4-Mj_$A@LTI5kyy>c$T zmPf@*o2R>-dsK?S8U2`eKP_tjTay<7u-TBT?E3O!BHwh3yxLjhp&7I&wl_S6y7f&> z`Cw~BQ-qH6N;NYB<)eUr26u9YJK%mPCdrv^gf9n`7MBV5>hX3 zVDBc)8spgTOEtnK=xq-KW?X8%t`Jmsh{|Vxh!{QjB9DJ%CX5@lZo0>p3?8acywJAh z0ib&k_W~*R#hV?yI+JTHm0=$$s>AUi?yTR1ky&&7-fdQHUEf+$Uz?|XJb+UK$zYL7 zZqY#{L&hksUQ5nc3zS~4RS%u!`lKRwS3u$h{YHjljYcqkUsqF+F?>bTI_J7DxHDPC ztx2AmZLzCpg5>SQ$6Vaw&caSjK2V@gSL*3)=5ktFc8YS(wlRE2-bc#~@lgfyUbt*B3jupnzM~Yu}(Xj<*?0>a(osNSej**w(@KS>FMv zuJ2G4sLXB%dc6l7Qn1R{EMsAraJ5gabQ9c%y-SF5tJ=4-tQoin_=s~Cn+oNJg0-@n z=eyP8IMXZ1Of@TJLx3DONy;@UM8GbtaH>T3PsSkcLosd60Y22@v-mE~m+9z#f1#_? zrs-BZO{3(9wnk6t9h_?L?6N)Ymq6xzEd|hvZ2rgQp3cn1<;!)E^6>8 z(s`f{|vDVrP%(=x}#gF_}QLaGVdf3-v6C-$SpB)^c zhbbX+FF5LSU6HI?O&J8bK+2xmoiy6jBeGP?LG3M?qGv#5Cd;5(YHu-t-D2#u;?74F zfb9n`v3xI&$W#KvSV{gbW@P}1_JTGc(MTSk0_xiI=kNxqmN)5Sy&s&jd}}6NQxeo4 zM7s*+Q&)0gJ%haRzE zSTBBLZ5LCqIQYRzC&JB2?~!|ofJRndPqk@$-G%tVM6qUVHDR5u?_@(`gqP)awwr~z zZET81dXxbyBTHJ{l95iiwcyh5N$TUl5&kvfCm0&QSC!vNdfGkr^rx}WRUrj6O;-L> zK}=`p-YUxzCU8H5r)Wj~eu z;Lm0CmeN1*Tn6>6=e}J>t2v9Y^{0$Hz17 zuYrxY9&QsflPI*UwYOa*={gKub-x3=wpx>_^24xL zgeeK=(~Ymxf6gI*YyM7$T(+Ao)yBIni75jVWPnSm4RoY3rn@(TIbX@!Q!E38_5Nb? zjXjl1s`+W_NzH}a^}ma^P6oiR)k2)^{GJ8TvTAM+hy5X}GeRf9{c+=Fe#=aDH0{Ij zprNDCQSmvm2KAKtW*sMglA~l9e2I} z-W(_e1Kp}JwV(J-L?ytM`vA7&b4l_J%ob%2bUJ_B%^~(=LZQA9auB51s1;_cHsbT= z8wT5=$e2Oz?kP*Rl!6gCYy?d9BBt{?AGY|Q>nK*5RN#R7Ls@>cMf4edv^#cAK3~mi zw6V1RY5{o8n2>6`vcSg` zEcd{i-SH@XRcyqHVcwJhP)5`Eal|!gTwBkJ>D?(>?fP>jo>swX zLf$(g<3Bh0Vtc;RpyLL8MSk=g)`avVO+kCqK0OJeQLQv$Y)jnBcUc_aAFckF^=OD% z+$a*LYe`(dcGmvDI!kKegv`%caT13kuR=9VWU(fV-kNo1k$|rkJVLH6KU!$3DT&L? z=&yC9X1THHkg*i3Zt|QjC6KBRmMSG$veQ!gAw&658i7tf9(Xt4bul+$XUIRP28Z5} zn{4f)X=*-Zb`V{HBT4sVW#{V!7jjCQdTy(FF6LU17Cp53 z73SS>epvtNsFQKmOkMKERG2Vn|3Y|tPqwO11BmO)O?TnAqx0}is78NeOe&r!^YUF=A)=!JEsr%xsN89q; zkRzJ}lsBz&3%H`CpgFw!EHMv*t@u(^g`&IK){^j9I-SIe+$r8(m>5n=`^FU}_pcx3 zIqiXFaBxdo;Ki2}y8}!orfu}sQK+RS#m0Rc_YiyeXs#1Yn}9dGu4m-w`;C9zF-gkK zsw!p};3pKx5fTL*YH`Uo4J(Y8MQu35M_p>8ZkXH|xjsC@eCuF7eWBF1kw&ttnaOFT z9DM!u?WxpQA-KAML43_d3(LleyPWd+QY!^e)JlD_|E`X+!*IJuku#kDp=sYxT=Ufg!@qJF7Ow%Vf)lw_G^ zeb3#bcEf_YmDKc~GY01;U#wBLoCS(KN+IAAmi(3m;ES9=rloT`F`PKjz+noP7deZR zO_Wjvq_Wu@fBNpb!~!ud6R?Z))czub?GvFYprhd=6`tk3LYrAGnOQU9vD2-2?fMj< z`))~pg)vBIBA;PntgX+jZ{l3~fE)k+Y)hXWFwmP58=U!LA`fhhUBJ9H_O1u7TLi$O$*e zuMt2@bHnNUpIk*gWuX|sa{(LjwSueknk0VCaTDvXdQ9;L%wwa3_)OwCQVR1EYE%F*D=qad2*BpQ z$9V4MIxZYP;Qbz0{P*!{_}~29 znDw)$!T$Ks=ceP2_8Qi|Cvp44vjKbh1Z+U4%hThqluqy{k@@-9bWZm83!gtY8r;A_ z`v}F!2mBzm&VKev96A5zQ~8U(x9K^`?AS^HlAG$$6O5L85-%N(7x<}38Hl%)qzaB% zwr?4aR(LYA*g55R5?`+#t?=@e5id<#YLjQBQ znO_6)t*fjjYT7@5o;TodtRqn;RSpJzUlVR#!o&>ecxbnQjDtUmja&TKo{kPGP_i6w z9XMeR{zmji7Y#~^o%=*K2FyYTxOihe(JURC^`zp_f_W?~jd1_@F8Sr(IfHaMO=(AS&|j8XKB37VUv$J9jIm7$qd$?q0?{iI@IP9WgI$m3wf?(- zy=KdGmHyA3ak%{sf0M@Al8$3QV)#XI+<2X}8ggPJ@*KiPMrDzODB=Gz7a&vPINDN? zErp`ff1VF42AwkZIBy1sLp10*JYRXo(xeBE34L{=b0PW&W>WAgXW-~@LJi%!HFz*OX) z4Zhzl1vj$s80Ni=y7@$TW9G#`hlI!S$dx|}Bp)t+=PVLXV-{Qzvx~hF7?HWyo%!1Q z^T`m!-}<+IFgV~s1)j9YmjWejI5GV)zx<4AbFq{&?;kq(XGkzk>>MBJ$tN7iq#(Fk zW=jkho&o4x06o5+JbVsMtnMiiPtBu6zccs}W_@x|-un8FdTUyABg=P`_@V^46jgQJ z0RIdiUar!e*vk~62*VCb0Ckp>L40n6ZoYv&{w!~uZ2h%A(**3`_x%9HJ}II-@w;ax zpN^*x#F}FYrNPl6g>N--p7~4kkN5v)27r1*k(9yLG_p*mpBL75=V4YSM!E6(j`OV8 zbecG^{Ty@$BzRtsA{F;zK;0qZ8D%PT0J1T1ltmn^;Vb&Ljq(OIi?V}Np4rQ2bypD- z?e2+X=MemTh+_BoP{)1Zz!`dZ<6pfK?>Xj2d{1h^b3e!YSW9|2z*uGR@4z_N$R_#2 zXKB+}b?U03L2i}8X z=wiSU-91?WKdD}D`?n(rb+ND~J^pUs7~Fk^P1e@p0VmiERtrzBa9x{@^gW@puMnQuvUB$-&;eRurniNkQ#aHtEN3N;Wpwmq7-^D(19vqBh zBA+Y%tC=%1+2?3;@^3Z0mygJGN__s^Dv*-v@z*q-dvyGK@0U-kiu~5mwqNwEjo>?x zCI0K5jy=_Xe)7NbTaPPwxytA`W<7aUPwq0X^uPajKjpVKLh-?_oE+vKcle(#`FB;D zB9A=nO!LQ9#s9kZ|KpeZvwHu3V*gpp|G#5@tnkP{{;#Gu{^eT>M6a1B$Rd>a_@O_^ zo=ohUH)nWEi$doGSDGkYRz&Y>_Gr%hvK?-E$bA`NuAUs+vD4F8HVyQ{$NL$|12}$k zaM7KE*!@-qXY=n%n4dGX`D0n_hUTm6ROWs0t`Sk6Zve_LF^f8U024*AG|c<$RXc$F zyHD%cYu{J6$*Q@KLm4~}(D#2d@9CPOGbD-5mpHywi3coPfyCX_lcV9PPNC+*4vCd( zlKJaAO!kc}iS&-08KbV?X{eT36O8o1!Y47ik(+>0MnqK9-#j{{9zXQC(DiH`J_V)LR#Wk}1O-U|Xdz>e0l0T7Jsi+O5gWOrSacbgPq>C2s!%(qYYC z-k|e9T6rcttYty#{`UG7p*y!T)#GcLW|d=VPMxj*QC8)Dobk67zf%qv#M$BGJi{Bw zjCL0^D!cO(g<;dLXM=}AwC7L&w1H_X^opugyW)Rh`*@iLnok{vtSC zF0MR%bF?tlj%M5MP4#MM9gn_Dk)I$SW43(2yqIXOZ^@UjATEFKL_*ztWZcv@*eyQQ z$JM%Pye^^7`@HPg&68&N+b-lyeh21)Skofb|CoglU={%5d20t9xBJOwz3+TC=LQ?g z7@EGj3wXDJuYer>Faaph{uDsTH*`nyHU;u`ewqrC{x#gMYCS)f^iIoy=o~g<3f;bv zBW-kxc~Pd$aRBhv242MZ*>?b9oN~=Wu1hOIG7o-I&P)Rx%bx)L(}0Bm6R2$OIY%&kDRxA&|v^wOlH(@z_uraBm-QCFIHb`9*(V?N)upUcW$#uK4-h0kt z_x7-eJ~z(=IGQ3EI4NUcod6NVbF>+^*TK#Z7PaKM6e-{q70m^gNCj)WyV*R;6E zrD}y7u2yW-(%T7071fn3xui0SIP~8)NJeQ(xw2SShKPjk04+0dQ@*@_q>HFddQmJz zF@ihfqG0)Hsd5{$kDi}A*_eCdHUQ0&mC%%$O&f;XR>R70^6jwlITr}I%$;A_zlLwb znz+;@I=j87960EcO>N9IE~_4KeIV@sQv*7g-_^*?ywKmn*f?BLbk#a2V@{a_9~`zi zc*xqP?%W2)nvC4*0C@!&Ufv*T-ntBsZme$!D)Mj1mgg?OW{0*t&z?0HISonNOHdJW zDUB&|+=92iIUMuBlE#TcK2am*)x2tWb$FZ0xi0HesPJGU zBt0=8u$2_dw&ld~# z-U`>f3a?nX&KaN!=r2T|#uBdqk~r9V9*U|O%RiL1Gl9me8ahokjGn^t+I{LWR9<7B z`*rOe_s4|vPU#V0+VT|L03U~qMw39%(JbxeNwGJ>vq&nE*Pei6faI*<4lWGg5q+&S zh6lXg`EJLU#6MEnxMO6Gf&?E8%vMc*Bvm_g13D&JJFW7 z3D(L-GwI86^c~=S31bQOW#{6i*MTAJ*a_`i{q#H){F;`2t!1H%3Bm;XXwS)F#U%rM z5p(bJ|F{f@e|-M*C@H(NIyS<5(& zVXs)*LQNi^+1$PFQWz6ZX$Xt0NWmdh(XLcZM%1A{v~uh~qi%opEYPc|m*2I}^=9Y_ zb%yHxvuYK>GD|ndJ6*D#Zz_&Gr^14Q4pGzS*;Q$Wh!?6|9p$UO>=g|C0;b$nZKu?8nTk@O~d*E^Oy2 z<22=%Zh#wh)H#1W&s=Y2y7nya2o162?rhRAdcwB#QxS=%y{R^|#i1=`U!3Z5KQ_xS zR+@x&4@Q>*pBuL_PP>150i9n)?QDVd!=bQiU)VI;wDCRiOYfue&0}-Zbh34~OZrZc z+F$$8wgJ&?0a(1$OPOXZ2di~DTYgZ0@4RnfJ1?RQ|5hW;n1F3Wn|Mz7(wiLgA#OYy zBKXa}S4Qx}$rP~}^2HLVxs1PhE$~^sJ4M6855X_;+jW#S9j3CpU03FPE8SOy_-Sca z=y$62!M*Nx4?=7e*gYTN_19CV_lgePqYdpK#vJ^@=$Kcew@&0g|E4BCa*o2P+e76r z{*%GVTQZ{g2`qn!4hxbU=ozb!yWG{LT`JY1ZH(Mz&Whiv=N7wp!RX0KWGCX&JFTo? zoT!~E(0p;d{Y~q|n@?|c*6hYpzX7C=LPxssUVtEnEgRcjR8oJ7fkCcvSZ-^I=&-{; z)u8SdX4#BbYVkWFlMl6`ZKJ7kKpO3$g%!dpJ;fsh=UGNt^S@*@yc!#JePulN+Rj^b zz<%KB3q=A|Z3V!LS7&B}6y#P#+hH)qS`(@Y5(cov1wyb|E1PDwS2}}eE&7$o7*3ASv3}J@&UcBlw*L#pl$kHQQwaS>uRKT3<_=g z6Fql~a9*xLck6^I(qi`I_Le;in;!@8vN}lLx>i8Gbm-3jf6>LxsO%i#3ZXu&lkWrt z0=qWt)cv-6JFFbN$eqD6G{!w^L-gulWo3PNY~Ylyx*i4_SRun1mG-SegWKxG+knQ| z9oVyoomwLAPP^xUWqT4gMs)*O!x%3qyI zWkYQ9p2dZ3IX$0zv`U?fsQ;!F=QL)-Be6;ij(hENb%=P(_g+wnH@fOC+U<(ISr=u^ zLRnOU_M;wmV{CUxwr*OF*@NcQ0EhAQZeX6}xrSBa)m}xD zo?BrwAM{(!|K&a=X*D#%?so{IQ1UU$7Im4Ty-}zSSF1bRKl@NwMT9eI)=lE>s4liU zb%$*k)hAsMB)^47v>m@6z`arg|4vnCea^ghs&g33?m3_h5x$!Ph=s*wr$G7ys6_94 zk!zbS=9r}ovtC>Q6D#Tb_Lmq(R(%S-R{E@VBC@OFTQJ+^_nZ2F0ML-~QNNj+B5KO3{M8JTQ5NbjQ3HKvD0&DMe&U5blb${$XK9R4@ImSCjpJU3{ z$ZvO~l5Yp9okg8Mr!>>eG*GWeHt2Zlof9U#iwP`&#aGK33TPWVGWWNeVRxtOFq@l2um3eK||XH1@=`hn-e^F_dm()y?vn?>1GcK=%0~$hQpr% zwlQ5CbzZ;&yG78;1B0j&5P^R zn5||Pt1z4!=@;|mnz4rJ>c>vHhD?F>QR@D9X|++ZIkVhIm~$qvnjY4Bx^CO(c~vRy z?HHlN%iz^%^-TwaJlCr4C#oxA)Z?Q8t@t^OG;DY45CoQ%{lu-B$`2;(bJj8??pu$~ zijOzCs(;2rGxFg2&kI-L#}dm{1x=MuV2u~CIZThnqVB&QbP?nTVLYtK#C!AlWP0F7 z8)y0SE~fy=uZ21f9x zWc*fAA|$ z@8;!*S=n=;C-y+321Z1*G{wB}xfbOTWx5KfhAh@>PF+Ag5YZgWEqZ^=_$1rgNLRUv z`RZX};(dbyJc2)ujmJ=lnEKNNcYx`J-|+ z8MPVyv)_ue;ueI9H+Vu;i^#z@{Dq256H9nC*-OC$im%nZ2)HnVO2x^(6hRre3nc~p zy*CfIb(ofSjKA1VY%c)YxN1B!&K3C<@ia4~RyL~}rm)x!%{EM?E;NKz$wt6dy43_& zn@$cyAsvdFnftAk%MX~1k&>VC8_JI@Q<`Qz`krsD8gu~;Yk#2MmL(%>a)KQfFm}5n zG-P0znr0;_1{I30AuTB9;gW2fDm#<2%ild;;yGWTC){LmV2#W0y3!D{RnM`+@i%Ym z#c;Wsrv`5V_bxTg@hF@|Dr zU;W25T>RGVZL(+QYx=oFofGkL?decr`pt~t5ohB8@$gA5#v7dj&#_xf@!hHsmUB22nu5M5%9Tpka;i2Hulpd(JQcw=(~i_GgRZ;(Q?5!FY;SoIP` zP1#L{>zDgGo{hy%YwCP7pZ%bKR9nm{4@LEbMMFuj`(hO(Jb z#S@ybOq;Jt-mp_9tEvU^eI5e^R|+a?3!^2WL!qh#S5zq@x+`nBmGL+AIxVw~$ca3b z?JF<5!>&8|-h52qu{zsWuxcZ=v%D!wjl5bVBLZg~QkP1Kyz9h>>cCDj*~!^WP`LUI zI)ZpGT+&lft2g^e1C>Ar4OaeCQrM5e8^V7Am$V!4WdeyEt`+J$j>V|LJPty$&2vd& z8wwK`X3G%?UN0%SI+@8EwjQ29wfhTKYs_dHk9E#vh9}GMtdE9<=|Cn(q6Kp?_a_Rt zOOp?UBW_oh3ul^_#S^Rc6Senq%*hYE*36OKI2I->DaGr)=>$*IS5*-_>VliRv--2c zui5xWp6psW3Nu$jRQ*hi#3mGc3}}%l^R_Xbl*B|4`klDTvrR3mrPD+rV5a8X1xz`@!5IoU1O^ejU@bp_(mHF2drXT(KHG%ZS-RA`?OXw!kQ zGAF(~OX^M*@7M6t^O*lgnVGn_MtSp^mOnU<;qrQOMZK z#~O|x*U0vX^FX`*TbMUgPJ^esF!OICKc=0t@7f9JEn}!{>N;4P+e7E$+(s-|@_5Nr zVK+?-+?q}z1aKNwgV*BMB<=OtFzXo(jqCVGd=a(avlO7#z9IUmuyuv~3gWuH5wM8{ z@p`+>F~WN8_3^4VSFGwwmt?J0hEeNWHUG)*>-2M}Rb!lySN1ae#03V>uzURtE9b5) zwert7Kk$Q@|Z5Qp^@%C#sHE`L1?A zq0u0oT-R>{NtS|{)Dqp54!7xyV4M6m#wNXy#YUZC)j=3YHoyFW4m@l))6&0C?3r=a zvZw3#ixdU|=d^87Ha{Bm*m@F&b}#OAG*A%rDtn@VX|?RD-4r-M zF%z=HPQGE=7|<@7(K48Qc9;`AMx(Jpz9Ir!0*k-lmI)3fX5jG_b2J(WPf=T6%6YtoMv5F3^9~jx0Ca?fhCIO$(rKbbf&B2;>|Xl zKKtjU-8MO9?fy-(68m+b-q*w_+BF`{rR~<`Z%yHQL+Cn)ii}Kf|VMSh#Qzy&VhLEdgfTOIt(z%}obhNc@q)5WQl$=xDsD(^5 z5=VWZu=#B5<^uSKD;JRW$=t{w4 ztWu7Ti(5A7A*;H9P)3MBc;-~Wq{?`&Juaed>SJDF_Z?BqV%_c(*EbKe+OkT2j-rTyH$GRFy-P;2q~^a~|X*l3@enxDE$r~7E|(37^^Nf@5ltu#GQ-x^m1I%eKca9KB#M7wOIJ;H zTHf47PQ0>*0cTtZI=LmEiEFoPsVdC!-Qwr(DA3@^G-tEAU0*J%KwB9sTC8zk!s%wa2;tIgHsy4D`FhoONc(~3VA6PAk&ZoHn)+=3?ujCe-DfJ4Yd z3=DDiZy3LRxAkY3X!%T-Y1agcO;*7(L#7VSP+8T! z)}}WE!gIf63)&nX$hZ*!6THWH?M7E=(`S>X>gqG|Bky>$kJidRfoGb&nM)P)lN)xg zN;E7{0qez_GX58buE~=ST(x`}^B){-N$P;@RtP&ujlOSI@z=Th6NVI1HBC3ibjK=M z8?55n)>YP#s>|QccgG29*$3m*hpN85khAc@PrTF*Z>@vRWic*?IcNC&W#|7^;o^g9 z&a~wT;V0ry(hxTzN-&gDpsCQvfBpsI4^vDe{Ihd3=_x;0uq%m*-L@n6%^!V!^Wc`r zaWP3Y9i>Z@EX_rzjQ}41_T#uZZA~vcT+f3$vA?5}{h^nR;pW^-yGUX+F?bTA=_0&w z8rk0ru3Z-AHi1VGz@Y?a%}7uu!PrDEI^P=ycZm|dPUsf-+~N~L^vrd&aoZ2ljCV^+ zG}BY|LYRhkO&HeejKU6~tb9kIRjvsL8orv0ukC&dAO14iH%|#NAT~$e9muTJ$I_;J z$RV4;3!J92Z>(&CpA)*g%9{kdFoDR-s+`4_xY6L0^|D5O?GuQM6#eH-H}iGwEO|mt zYP;dRbT`M^NTFlFQ?5O%+WDG0 z2HJ?-#ZlsQ8rYM4?X>l2Ep$91?dCTT2GF;At4j};?-@;ZXQBisge+5G>x-=7nvY>C zlJHBc4vC_3HvV{VOCx;yrWM=w_3qlF&WBfTfZXqyd5C^wt;k35Sxt3&V!URid&4nq;DFr!Q^!P*Ocdv>(ZoX@6Vs#SS;Mk4AH zx4CvYAQ5@AqjD_tZg63{n8xuCjtVgBOu9x zQEJ!X-PX1!1`AtGPC?h@^rsfzUa=4Z469(*Atv#K#x?^ob)wGPj%wJjh$>k=0xEI7 zU5&3D6-!&muSRkUB}46FI^4kc8rw)@Q2(@j&^fA7N#&`zij1JIA3#|gkK&&+Z(TO) zT6(bARLD`Y!eZ@YOqNJ(jpj?p3YmJ`aq9Vz=o`YTCgGP@=0avY-Yb^R17g|gm`(QM zV8J?LF*dae4D2^bMQESy0mQ^$x0XyewCm~>&apQ80m;Ua2Xe(Iv$9rWmZ+1Af5lH# zA)j)l7x9c;;Ia=3bBQcAtoRGzP~5sMmh>}lRXu6hFRO*N9{s*c*f}Hn>7@=lZtWAx zn5a0$Yh1?|z_9l{6F^(}B_<%OPQSB2sKAb=1JLET-IPM}UQLlolt{vQA7G3+;;6+_ zX&A28v^7};I-J{V5pwtPhm?tG6}i~WAvJPuYKs)ESVwdCyt;+F$2*!*i&H|j<{9w~ z_78Q1-Tl2NlXFmoGVgm8OZ99?inBe`o5&%s%vj$o<>H*oAWVJYJ;Ql1Yt8sMK&y5j z0bekk4H-_8Jg={AI`=Lp#{_tvpv78kMCw2)3>65|bD90SqdD`v4E{0ax>Gb6`G+)?Kiq&!E~ zJJutK`-#-+Rw3>CS_F)#(LD|(p6RILm#YC9NwXqaq)M6dWW$M--jA#umFGJUAaSxj zsLOv+@rkqPdBbk_Bo2#pk(AWe2U(kpi}IV(#G?sY!p>Rdrx|gRk!!8{zWsv6@raKp zN0gElseL(4iJ7pTF2PbplirMiVGN$k0H z;8v22L&YkUQ1-%HL4-G}13kj5ge#PxoP3}sB|BX$Kk~xR*h)>kfH&rd=~Lb?E83sp z%y}(-FQhzvy!zaUXv7v7`3^`H^QL;j@mYuV71agk?W-G=OP4ELG#QarbF>;{T5Tft zLqxmS{`{>VH5qq(i{h)9CY0hyV z#j~em@^kd{+Sdo3Ze`hpQDY7f1mLXJo;8;r##^k8KNNdKoWt6ozuUI0$IRTbhfH>@ zzUSxn1U3kEKR?&{o;MI{PY(afdKENtj?+-t193OuHoRZO%cj=CVWU;F3|{oXw*_99 zR5MzW4(MF5Znp*LE1~jt(1F(m-&#y4CY^fcq9%T~p26`znM22bMXcf`l}>=?geHebnn?DIgW?6Fp+CH~3Y#7RPCrYutIJaQN%nJ{NF{93N?vL0`enJq z>6?jjEjoH`+}IC=Z%<(d3X(unkLNmRLRo4>C>#kmM_fnFuNhw*d{H=!G#d^$B8K($sL&oj{Lf#@ zv7!fNi|>lfGXC=`|9x(<65B?l+2mCV(tm_y{&A3n9CVrMdOB+3^55O3f20zShln}4 z?Tz=XAL|eM_Z-DP&*Z`z#5V*IvZk`YWt)oXl=&*Z(KY!3@5xpuzLs)3zj;(J=$#x} z%EjAP(iFTM!pm8BmGWYFm229=Mj!nnwI9=M3@MJ#d1;@Uf@`; z5Mk~}r(|}LHH{kt51uaVfMbKuT{9C=lDa?#Kb?GtA&o)+0fDRQT6|&dTq^5nO=0OC zH9Ck5oMocp+hZ=J@5O7!vRD)r<2P6R`|U(+eb?Aan_sQ`qs`DGLKmQB%sfJSW3)Nq z2WeD-5c;`Lc3M`@M7I7|4FnNxxj458`?%aGTMsdl8T0A%n7RKjTyCf|N&{1)j*(Jb z{*p_kv71|{jZ!JYLds_QBS7pI7*S@H!TEl3;_`ZP=XebNNm@nB9N)Iq(#!V!xU<)6 z`RX3gNPx@Z>q+6_4P7mqnaOgacP2S_m8)1Wfr$NR-oUX$tke7ZEvPXt{za0NPdjWP zvJ={!sSIu7qgZ3MN_5N~cB_bo5gO;d&P&vX^D;5z^?lGKKHH<>ervyC8@f^2@w9MZ z4<(F{4CT$l5G%J#g8Z3v%s|q0Zm-pcu=fl{^MDMJh^>EL9!N6k;URnfVADs9X4YYu zGOJzkE1sDvotHtw9yJmT7Ua$4PRW(EA*b|Gl+)w)tH2oav%$25>)ooTDYI`MrEru&G zE0|c{3pLD!{Wu;41z`Cq(7eAbmN)%c9ABnaAP}SRCyc4uLsm*_Q9bfwdejZ^mmGFM zuX`&T+d330E;)SuB6IuWI&68X^hLSWaLj;x0(>c^yv-E|%LURDJxA(JhCR;@r5-+U z{?2sFmto~Q0}Fjs&TtxWn2=YC4HgowSf2o81y6M^d|UPY^n@9J?xySP0OSQw0-$+Q zah^EjoSkoO7c35*8bVcehO7GHF|vpNU7FrZIM9gaM#yB$>+QmpBFGjEL>vO^t@-eW zuHO!!u5AG;OsOD0+3wQXY@b{4bTp5mNb~Y+30c`v5bU+mEsgwB(RqDw95nIyIk|c& z#WD7foiW$`mYAo`1ds!f&mlF8IAjbp$lNYOSPWijNk&aXv3|MoYQ-GGT`uEa{&PTA zvN>a7DA|_imMC>BPo?Im?*9mp8aD=TyW1ZCCXwDY?ThtC-XTo=mr3x$W1 zR3X~ng=#N2U*Gp`KEII28TBYvH!a@appBVuFtoLeI)#ct8wQL@H*a=`lIxe8t4+5g z3HE?@h|Z}Be<9I4zuW=07!p28$_!aPobY&-i)Xd(+9XBuC*fx{e==X_q9HSj`j7AX z(E^P8J!b~l86S0hFDciDW=jr7a_a z0^9g}O)$5g;?Fml>mr}OA3v@uZe73dkabf)ylVAkB7Rxf>Mkx3Ra!e@G$bFs`KT9C zvDG}+NN5mGkM(~X3VAegD08iIbsDiL%R0s`1muu1s|R$R@`l`dxOAGr9aqaVni+%= zW-n3pY^=Z3OvgM6p86B+D=~ z(QG3C7w_|~5H;w6%W5QOi;5v^^4F$^*1`i@Ov%Jr_*&OV0jRLJ<{xF=+C@c^fXpp| zW~NFstPhX{m>GaR-s!{zy%YfuyW{}OpngY26iBZW7_P)<=IxLMlm)dv}9&ZM?y>lBFC3ftOVCLfX z$RL&2=atrA-k?IJZ4ri)d9cRa#-c=~zRVY<-J(e#Rp%A)+M-7%xeZGjK0HY;aLx*@ zsq+iLDh=hZ1riaA7zc?dMsI3PP<>-A8_sMIH--0V;p!mh>gOld`|$6iJ8TZUt< z&}F!IYbyBnpSHE$t+az3?74!AE2yJLy%pJsN1c_$w}kE_7DV1Ht?t)m!#pn%_i7;b z>kNu6Nc|YYLNz(@+5A>4OzhJODW;Q=!t!2qO9dy5r8qj_l=;M1#f@j7TrHyI4Gliw z6_7@Lk95Nqr-#+aOWnb~K)||%%=QNbv1NU3t$l$?B|s!gNmPGh#WQ9+oTTSPe|a_H zyW2m4*sO*F(o3t<48A-Jkg9g6_>+nh4NfT@^qj3KqO{0D-hFs~(m3MUTK%%D7kmi= zbLDsvg)4$)U+4COS>h_$1StqpvuAp3EM1byak+Z#DNXt#0(4@~EjzmayG6^|%Xc|Mywozu?e(XANjZ76<6NA=W{=-{T0%jmJI^r@#dV?yS< zEDndY$V3m=glXcGDk@h8l1dK1JnP9DD)&v*a`Gc!KUWS;X9I`W%$cc$Rcc@)yVazr zKc5c&X!}dUz0@CWf4EC?aKVsuESbaRUPLHFk6bszVQpSU`c5Sk+)c7}arbtt&9NZaxGO2ANX8<6o+A^$K2WH6qpKqEFs_pJL`;-8axa zJYlH!iK~wgd9Kwrdd{IKuLkN4s>d&(fi2z)-v`9Sh2VyI0D$_aZ&_HZV>%NNDTfvGYKK(^LHi|v9{&LJy z^+SFsEys;Bh}M4X4po&(nZSIxHPXASRZwP1h_7P(?goq7hZ#q#`9FpwRxAx}9$o+l$ zmuDSs#LSl|d$#jCbX51fH9IQpNCSK31;)>CV)b3rev*FidGmSo)puvn{sY() zuOv}0J0FZU_c_r~L}bBbRa~$1@^I7orZKtqt^HQ3 z{0d+pDB)Kx&wPxMXdjjzx|8eIt~s6Dm{gt}v|KcU(uJg#YkgUGa}?P%&^hTbof)VN z%??@qF&)nSGK$x@AzV+L3mxAo7@s7)zE=$WR{k2?^pI=yQoOJ7-#DO`Q)pz$L+$S| zH-5^(8`;GXW=CrjMQ__}{M^QxG+-O?zS`w>w%83oW16K!9 zlM!mKYOuFae$mpR@%<(}Z-4%!c&5MCTUt6EI8m$;2=~L+h{H2mX0|0L6BCvw;lEgs z1$ANtw@P_>KIm&uCdwM|iBCoXA!BfY8aUrE zR!z`ea;tt`J{fw#K;@j52%@$qrdHu~C^e;9x?s({$;KDIHnVv4e2ghzDl7f7sr)OY zSaZsGVQ+Xl0>n{Ap0Y+qF!Ea|N)|w(i~dZvI&YAX5+2+g4C*bsL0$lQtSOWNs)qTB zBW~6i=QculDgYv>65G?KQk@r8dlA`R2A~|ril>1VwakECP0;5g4`TTYt-Y#j7dRob z6--o-ZnDJ8PsdnYb31?kd@2}gD^yz1>I%wo7eS5re!Wp7!^!w+Kd9yKjdnci)dgKh zXW3TIr#KUlMs`X$-)7_LsDHnN+zJw;I2|MZq@ZtL(=&XmVJ=*rdT-bRl?BG9d$k4q zL_-blS|ORz0AEE^^IWAxcpy0+L|ubtmnWAbcr-0N5&q~Nle}F`A)d5sQf$oanN)~vw;)w0CtKes_$9ZJ9Z7Mf-YgXSru#dX16pt52yiYCD_OjY#9#^I$$iI zli8A~*f_t`qJAra5giAq)T&6O(Q2QfuN)OmQ3EQ|Y{FXzCK!J3s$>yXFv_IH5%;zV zc^#n?i0X}0AG~#Iqw6l`G-aEfz~1^%1VWXSnkeO1{6(w6y#F3;S`Z7wY2oMTHH_8>Jo z%4+sCwef>pDna`4SfBLO&nLFN#wo77I)RQ0Of>;{xK4^2)ZzMv(fb(rUS@NTw+rz> z{>8e9V;;(WH|Doeibl}ZfHQ8+l*TXpzY(i?2^x>Q1RoiTf#>0FO3Tl#8rOP`Mi#8D zW3#_}x_*OAH0ig-N~CJ`T;S@ra*Od>Gewj2I_QITuL6*9Dm^CfvwUOF|3~woTEb70Eh< zOz$bn7N>LZ#5Q%RqAeKD91I4$G2=(I4FULV3-6icCp9o3H9Y+5iz3cFcq)Yb>0S3F|0!GphkCCFhy@R8on%JiL{+ zb~FRNlIew`bdtPWBL@|J0*<@xe#pD)xRA#ACdWu&-6-6fC`hJ(D*mg3^x-_y3vYK2 zy5~pF6MA67Lt$hja&Ke|eg2q0Ro{S(5PRag$SQfvy@$OB$kyt-FEStC(D)n0ttMic zC>rBNl|1Q(_m|JxcFlag`gDe!WwzO(%rujp@gLE@a5-do;CNo@_JJ9`-;Ow_L((kmiyFPmxy9$bw}1;B#prQ5sf{KOXt5Z1$4Q z;{v@z?a8OE(p|lO?94?xgP|%_4-=ehD{8D}Fmr@0w&CZ4m753db4kXO+>;&SpC0p{ zE(H~xOMW|_W~EUGbkw@RTWXlCmRKYp>SAA-5xgM`YU8afm)W9`NO{dfGU#q&)A51r z*o#Tpc9+A9@YWo^508^gh_cm{ORd~a1nP)RUt@p9i2)B4e-~Ku#7DJqujSw~A#=`n`^WMFU8)b@SIEZ+|06vuRA zr+YM9Zf z<;{y9{Y*O|k@(QKk#;B9Z~1!LG$~TVs*zA(2&Yw-izo2a5wZ?ZMdS(sMqWSVO)YDr zwQepJPO$eib?DYZwjC)e$C$p3Mj>ki5UE3Ffeq8bFKw_-f0jN;dUir^Fz_dm#Xzds zbrMHoxCK0X}g zF=?F-5S?@APF1OhKx4|-T7z4e>pi@Wi&y~QO?DOmVJ_y_=P}=MwV=|BRKcqH*Eb`| z6)qH9Ql0vF7H#9(WhsNp26PVYp?&BK&TnK%2$wh!Ni2L7&><|8H~#4oKt(ThV{ z)bDQ*>)$buo}^!^T5)V7YA-a==Z@V@H@6QHr;-qa0v2B7AM9NmwlGM(Qh%?6n)k$K z8TUa7XplmHdX6^aADkkjhmaOjtI_kw16+)#$efYw=sVE1H_`m~+;FWIN6+lwTXPdZ z%KD@sQ148UD^%;BzdqDms3Pb0Gkv@Ivu}c`?*ZykG;W-N&Bwvv0HtSgNkwo+kN_W>1C>o--8|LxDepLBY#t-&#Rr_3b&u7tKX<&-uz-`Kk)XP3Sa zsb}fYCf{pGC42J-_ca=iuWzm((Iw^ZB=v30gc?B5ssq+S`JU`Py>}!|(ewdCpT1tU zXD`S<-%BTn#^|s50&4Of|I1x_FG*k9UZfta(f=|R*y9K8z2)!5P0qr>?fq`EG~GXb z!|Z>5F5>hrayVXlS@N5*f8*bOyvB$`=a>K1xj+8*SO2Ef`)GPKNxIb8cGLg;)xY0Y z2&Ts_8n%xAu_qq*A0zpFI}oC31=0eC^SV-A{1Ev&LH?(QdYkF?-zenpAOE*$Uv#7w ztT=tu_F?~LApiSNXYJ?`b^&qVk3G{aRE>~qjWx_>!c4V<=0Jb+SQ`7O4yrYd3mxz*W<04J;Dp5WGb<{+7&4K2A()O{K-*o>GXNM%}X)d$^tPwRL!)D z_ULZsMJ0?W0kEoT2&OL z1eM5CE*N^$6V3LU0}%mYJ!62MQ4)0l!|B)x9Y2fEwht%YP4il?3$BJaAPj%s3B1!) zi_VaMYb9BGR=!a(1Fpm623x72nec1t0fVBePg(qD#$WHyXI3`{I545bnpZvCVdF>D zx8Mu<`LHW3yPJ6;F!TgmNhw=N?OtXizUOpogPLR4&p@V_a=V70TC-!Ny0)i-EPf9v zVuPcwR>P_Z?{mT9x#qOKZKGc?;qv#Hoo_SsrqG!a!)!TvZWr%4SqH{KNa$7a;x|i8 zSU1^ERkh)0ZXcRLdb=|K;SvtHN{Q30K*3?SnuA_it~m+zg&}Mf_5SK^l)ccDzS69C z8#nZKmx_im=LK`EbOeE?$ULsBV8(r#FfzH5*3*+PDvy9kN=L@2^QCU{x#*=Fxvpmy zojGa0cp4l!%e{xE{$h(Cw9cX^{LILb+%9!2Pr*#lWX1PyzbCsUw*B6qY0X3!d1@ii zT(4}}`}@%Es|T2RU(!h-9%CN1mlUxFp1`R$xTIX&(*nz~K;3GpDEF!^Gc7~HjooMU zju%dAU_KwVFJM(aof_iQ_mU#1k}R;tan^{Ti;%uAMt%Cf*#iuIR{wkcz|;JtNudHw zjtuFwpJVxBeAty;{Cqh$s~FGm2LYlW=s(*lAg-EI&h~$LZGAGfi$7Qc5qxvHn|BVs zq$;^Xs|X;O>hagYyZM_(PqFPV6rjMfUtsvtbaYRJan9KGKKYmXr*wJs1}weG_lz#| z+_tWp>fD2ze!3WQ_4qow`@MY({({FMU@W{&y1Ei__L(XbZM*NkSik*I%#YkFM|TG} z%Rw&?Twp5>+&jKfjT-_UGcA<<(g?=gIzajutp5*VI1_IsB#Cj{A+C%l-KLoTqatBP zFln&UV|J$F?|RSe;S*Edzv7)v?uv44;B3q@U8FsjEy?!%?} zk|W$z8@hY$%VYw!%KU$3sfpKPSRgh`ax@5CI%B^T0%WQ?O2{QZp~5*-Exh^)CLmoL z&2aQ9VQqJ)DYt)FlkOMmkL|)$jxM0xa$ir$?M{{HSc+VP>)UwZFxDofRQ#@%|P5wQJO8#Clx_{KPEtghCPbJwoBs7fC?S~@&qmxi~@epxn=-qTrs8+x&ZEU@3S z!$lR`odtv{*g&P#W?q$BfmrE(Wr7zTgFZidG4p;uvFoavK40OBU347%H5UaFo@+ad z%5nWwjO%o9mT8A*z>f}wzT?{5QVxG%d`fsLZYQ2jzz}UkaEIt=+W}-!zk~i1pv|H@t zQ2i3FuKF)31#4LJvR_b~ac3|xLOmQ2FiQ5uMdsj*Pda~;*3&-2nF^V0!n0swM^^Ok zJu_pH@p7Y&B=(4>E;@-Yp*{5id#Pb1Xe177M+91?NIiuXnQDn3z?wq$(Dp)hmkS~S%Wrr$1aIQF+h~f*LLHl77`14*k3jM(A z-bqBUjQV{`wUPo_fk25*ce$niOKA1p@3Y)1w6t=p7(gYZaL?FqY`n6S3e`!EP)~c` zwYul%%mOGQceGx)}ZJMJ4< z?1{3QAn1yAE$*i3t~}PrkvQmNdIrA$ev;>lY`)L}OPBVU8LDztT6`adzQ)ax@gmt@ z{P#E_0wgY;-48OS;xc8{Uk9SLVGwqR=yfTY1MSVyAyU|4l7%~0Fr}hWa=*V9mc^#i z81$t_#%KN!j1WRab4cIYFo=LHTfZ~dU8Zusbhl&PEN}$I4&?lWE|xHW=2%B$j^@T> z2#*18^7_Injl)Rj{C>1Y?Vythu#w)W4ZErn>o*~%D|cE<)ZEaz$t&*U*5_r+yBlQn z3blL@7xDV=4E61jG+3l!)^7~mfBzOZ0uLxLTgx?K-Q&xg>3Q`2?Gd1~VWT0~Ya4mz zL;5xfQvFB!NncWT##epj;#mgJ*;YMm<*cncc5CiXSxz10^5&j9adrnf-h^Pr)Aj8R zi=YD=B(z5C6~O0uG5daUpGItg{BU zt{p%bd=bf2eQBy4H6wRcufMmFY`OJyznk%q^cKa$9xD!oM(R5+dH>Yast=NR(5Ebh zCC((J+eb*Q%b$g1j^yd@yC%Iu_6U(*7SP0ak=xEp0Sm1P_^>J>47tNKBPKnsGx#C^ zfmaz3DQ}jC%1Jg7Yj|{iogc1B;e5f*raN(7K>ncfiu(;)k3KOQGZW=uN~QD4j52Zz zlnMg`rbruy=qEMabYjD5YST;1t61S!k9MermF_E^-Gz|T@Joif{WZ(HGfLnG98i7I zCwBI84XC);%<#WJQhie#qR4EbEy6zhYdlm<&l$TG0=Fwm z3+T@*hf=a=?=%O}5rG3TL0jx;P0qU9z?Mi6oWd>)`{;oLGu7N1hPz(_j2+QW_w;=jUq^wB9C)s_4`__Y-ZiX zv|2PHlKWL48IId(GGgOc%9sWwc3L&@N!VCT1gwO%Y{0eIqf8fQeT+bLVw?8bt6g@` zgtkQ$5%KL-%np=+AEy5@!biZcG-3x(*g?WMaC<6T#MjJqcg=1inM~8-4}Lc^=`_{d zNT6M9n3p%tBVo7Bh&QjkoJq-L)zuZNSU>5dc>CiczwyV(1D#QdFVv)O}Q8{~jg*mS|RTzmtaY%K$nmCf_v<2$#AY*=8cq z|A3txWp)3@v0cWQp5LaD+1;x*1NSoS;`N*~U?cN23La-J8)V7`1lenCxnPO%PX1@` zsm@utV0@THy>9UO+!)xiOC;Ohv&YW;PrgvwhV_@&lj&sVN2qR<$-F}zxS0M7-=51) zp+GVlxqKJ(fpJU5qiT(V852nluIkH;%CWYydn}O~J0;s62HxMIzV!#yb03BAMT%DD(NO$-YhCyAAQQdBmGO3p5 z+>=aiDu<%?1?RjCHJa!5o1P2CRS7@tk1SF;`z~N@pJ+kWs8W*Tw_^VYm|2D5t{d@Q zjGZpf^Y{03?Rv>T{^MMPE6|~4ywV2?CT6IP%Kzy0F@Crt6#rLw?K9fcx zM+#d6><i#j>&AV2&#{Ku^41GM>$`fCJ&Gf9QsPDG=9wMEVyxQQE zu3A)F4aNJRn$|IVB-S?Vai^0TFfWzG_t_}#w(OhkQ`zbp#T;=>Ku96UQd3^&y7oIwToUIZW}Npur@Oa*0Jp# zK6@*G&`ipIk$Wv))(kiYwRTjl$gyn-YM0jU3&{8QGWf>E>f%|5ZZjD9LT=3ER^$;- zmpFges&~V3u^TGEP%YCm$XZ3y$g?Ov$z|b{T<{L|tM-o?Y)dGYKn7`Gx4HsO#O0~y zrJQynD;`pB4-!2`h>7i!xkXz5J*N5on2Xu^>lA*z(GHmoHBl{HQbbpZ$IFRZ#qP$5 zjCkqO?~^*d_F%6rh&fQK7#~1Vy@~=n8rPml$5=%b55POy7F(`Nd5ILq%-^@?$Q^L< zJ0qUez@szllMe?$t2qr+8)diDm0aG+I(&U3vo7fcwaz}3L`XY*8&>yD!^$yucvl$} z+ta<74Xq-+y|IAgZSW1>O;$yVmc#qMH;dK(I6l)M8a@h08i9DT{$2a8=jOH<9RelC$ZzvW+?AnPwzhTPkr{ZGUf~%sQ4~r#k5NBR`A*0n9K+;$HWOwDw zR~x!TpQ`-PW{1k#CTl4WZE-u7f!}ht6lMsC&*D>Ra&aa4l4;E- zVA-c1D!XV{)zR#vF!z0G2t%$)`AfM;@gfQ!$pw- z)#VB3Of^X>pUtt=oWYe%V{WL_*eVpxXSoJb11-U;IH6xx4I^Nw2J?q@x$8vV0E_vP z-$X+Dx7EFEvYZw;6EAo6r0q_do}B)Jm`m|yF=h;)zIC(JU6HJ@LPuy<+%fPjg#d{h z1=w{?Y)!*EpfO1V4!e7{879`)%V4@@=eH+46(LMd3+M;?4enZoz$h#){B{vyPD%L` zs01Uks-To7BZ|gl_%}O~z#G#M8W!trsQG&iJz2k;;gxlw`_7Gko%?Rv@E;9B#``VQ zb9OHpSv~s3qH+%b`}SnN+j{9wrQae(!}?c&*IJ6N`fp+$CLO-g``bW2UH^H4VTu3!iBg(8qBo${OCL3kl2eO-l|p3B;e_EG79r0VQ% z^VfGK2nbknV3hb-|BzF^XBc7jt0>avr^2q){9cUSqBZ^QLuAY@Yk>Zm8GygztF#;a z>HXE2syW&pxs#Rc38ymwgLEPOYiELhT_d`k-(6Eu{qy$>HAH^}rxg7%c7s#5lISsz zuF4P7t$Ut6=3)RuZWVbcJCm9HwJ+YTwPAY4X?IblGXd``13vzHg22}>i5dq`N`5Kg z;`M`}_}O}uogn}P(!a8mNlOzuX_|cuee{k-X3UdD{5#(Req2li0^Z`l@tJy6yX-8~ z`bB*nQda5?4r}N$a|IumQ~f<#;2Pd62RP;Zr@Z0pNWEiYm;vkVw6~cGge9h0pN8$u zy7&ftEpWBvtL=oifDfN(Ufp;n6TbNw_T_rysH$~b59fog{IhAkP(N6+qvA(>w(mFL?j z6~5FE;?J}VNfq<6r_*;|&ty_Ux45cf^{G42AONr32i4YH{tDU39WSyT=mycqQ`*~^ zFJHE}oegeAaSUrb+T7Akp&Ox}Q)I9s&HoR3?;X`t+Wn7?)KLTr3IfuUj(}37qlnT1 zN|ml6B_JTZgn-ykQF@0ElwJbTYd~ZW>5$MNp!CopEdfHvJuvT#neY33=f1zS?!9Z> zwdTJNa?W|qes=ln^6ZTQQkR9TL%5`${MVm(czY0&C5%E8(@6}0S9}5kw%(msr-vOT zu}sds2eNuAP5_l#9{d#A`~c7e@lmI z&s@$U^^e6JnjbTvlTGD4p%GdcHzPo{U&3{O3bxc2NOxz7`z%eTg=qa@QT{Y7KR=`k{H}sLzAZ}sse%T)FGT&>3xMMJ zKcDk2y*6+dN-=?E7)1Qr|0r0PLJMjg@=WsiY6XhS@}GkB?;q5*4)wh8WN!b(zgx-A zr#bzO3zJO-S zyg^Bge|UqE8vpPHB{lxx4N7YK!yA;;_=h(rsqqhQP*UR`-k_w$KfFOnjsNd?!)ox3 z|K`G#o!JDNOryN$XlXF2!v|63(9;Gqw#WoVE=LQ1k~@4j_1^v`NA7?4b-W+MSe(jA>z7cP@!@GcO)3C<)a9C~oDh9%5Ra=gF4^{M^ z!{*d;$`n?5&g=l#VIR2!%HH514qj{SPfV{-xt$$BI| z`NM2yz3MAaX+bA{p?rW<+%l3~#<@enqH;U+-t^0XXkK-?GS`9p0fWZ-%)+DF+NSKYBTGFl$U_eP@2-;ba3zCF7#=;3bs^phuW_Ta02=tdM(| zw3Aoy8F8at2Z$wCXOfg@n)6y{xjs4syvlC>vQl=-!y z`BawF{V&_jJz`VXJUdbetpm3GP5@z9yyeYV##y62t}-7?02ZCocr6>>i(#L)V&orTKt}LCMrg>BLB-7go}&-tYB! zB`-}^F&jNPrUg-;bz1^Zq|ot#fwg|xW4@ao1Y2~r2qFO;-qRKlLoZ^54Yfn@F3`c6 z6Zln(DDEw!2kICksGnx3;N$3!{~jrW=NzeWYpk*o&GcT}{s7FS?kr^3JkKGUE8$kJ zf>Qiqebs&Hd1u;2QYXCecBSi>fTGWGO=R>G}OYQo`Df37u1CGoL4CRP}o394gK z8Iw_pSBCgthw}=0b^(5BLlv{Orzt~bp}N8>pm6saGl5AmI0?43ZGMgGvGYChlTan%{U~Sh3nD1Q*PMfo!hV=y{!Rt*fXH zTwnW5=)JVJe^JXuAE#60K%tpc5N6%tZHP2te=xU=dL3x5`J11fZ|G6nJ7(oZOao~Z zQiIzMT`|5Q-Y8>VzJSc;{cqL8N#K+gmhNu+gos-VrZ0p|bka#97g2 z)A3V2c$MTunEmhB6*xbpc`;G|x{FUJakCkXg{`Kez8Pk{Ih%Fkb;|5`&4velnGK7o zu`M_BSu6=Ak*Z>aAt?}c9D%#hCH{=CfnUT>p_!=nlH5Ai(o?!z0mZnsaTcHgW|uML zmEH=t>U6hPoOuPpZ*9usNAI;HS(lfaD{{RPEtiV-?$;bxZL=V|ZA~_n2M=SR(!&D_ z6Lbcdny32aH``|PHALaGPCh&?D^x{HUHt7_?H{YvaKUIx=AR! zNc<^EZT!Ef&_BNWRY;9TEQ%gQMcd$&S?)AqS?j&>kPehCtmv(dHQ=|KqQ_}x>n3#u z;Uf~Wm;0gI(88ok`vI?^iMp`$lJTH1#6<1T&4{Qb^_Tt;-uJgf)n}XNS2qS*WFlEE z70LupoG<>I2q}5r{IcWgoeWIqoG;E=c_t|bF4^I0gkZCC0x=eJ!3jwZyZ7K|Jf~vj zpcR3pFcTObIa-0^ixJdctFdlnTFG=tVGSHy8LhBb?05Ob?1BFHZMQ--`N?F}WRM_1 z`NylCE9{XRq|pMErAn7cE<2II#esb7k_Q@4{PdCkTEB$=_~*cCEwP%nLqY5*S03ZX z<##+=;lQA84>m;~%XD{M2G-7)3ojUwT$-rBK9AeUd?iOSX%*b+DiK-g#L5XQyPW^+ z2J-zEguAS=g~UEV8rC7TQN`(rIBO(v$MWLs1s&gBkq0e06H{ewaUyYcs8D9zbA?7p z>ndZLO|kldS}(>jOrD{^SG^VV$aA%6o~wpw91Oc|@sq(AK0txLEp5Nzi7vxRTJ6OJ9tijf8f7Mp$-YiBC_Zy7-C+v(rmdX)d|(UP2i{%I=ORwtuk z0dCzNusL+Y%|}#VU|MJVgO-lrPx7dZE~rR z#BGGrS@=@*iM@hatXHZ|qqR_q9Ql%r^MJeWMi5b7ebM#m<8SG)LbDvMXct!=7xF%} zL8+I#uP@H`5iyJYEp)>>&w}s(-i|T9B=q`nn37@S+DiSY*v>R%Rdd zf}t@wyK8^GY~|h1E$wEyE$9JD<1NGHGjt8Ho*{RYhHIvMk4lT#zkfGHDsAcb3mLKRZGqYL*Fd$w9h^4;uDx*tsj`-Q71_s^SxXQgY2?Y4Di> z(#X+2gz^7&&kiwL7li*`f;yw@!%B59TO0(lmbx1T%$Nh_ASXDaRIST*CCc5@dbYcj z=?mXq$164%505Y2#~%Uq2)qDlc5?@_Yg*KJ#7RH$g7<)>@8%q-QxhAGOyPj`ckQLM{P`e;Q zwB%IqiPGZM$5&#X>M@#^d|pvm8mAwt!bK|id(@ra*LZU#``E}JVk{HIIe^?+{ah;} z$`9bSRdpP}t&t>doR7f*bRBQNZExt;Ag}j>)ny*CumM$`5P1%`mapE(*zhZ9lntA>gR6&s(@_nxQtdN2pi@= zB*YOSvd(ix%$ge}3JlY&NPgc*;|^=P_-S@c$WEN8-ERdMf!&G^fBfRV+!qS4@#eRg zwitu-dnH13*#2yVmb_p{o&z@dF2k%o8~u22%){5 z+q6S4MwRida5v+xU%sC{|K_KIp{7Z7fTXW$1d@-0kzcRRwOyR;n7nXcx7y>yrW@sF zS^*G|J+1bipj5~WaW$TIYUXbxLOM7#Ej9-p_}62BYG}VwGeds@@~FyE&{*jmV9eZX znI89VfN5FSHRoNyxZ6_eb(HyU^mwfI3m0><6(LR5XY2Zuf&gqJ>CkOi_K57~-07HS zIPa>JES;CC3^5T1x~f%6Sg^xQiPfD&d1an!ri{uoJRGpIGvf_v|N`|-Vb zJ=8F(%k>4r+1UO(!;Ywnw{A3cmRSrIn(>>JX5vMXuC86gj#q^CC?IIwpXGI=kOE6^ z$S@6RSq0?hmfBy)R^e2F)PIx!OzkvzL;Ax(`s?N%?D~)2W!v`#jh|NyHQ1p$HEN2# zqrESqmCBMdl^@DgZ)5H6ulZ@^K+V<#0bWU#)!3lQQ0gA`44Cjh5bo`b%M-Jm3}`MS zI;{<@4^QjwKJw*u^e&6$*Zx|&wUhxZ0^kPB9j9G9K^iwqoHW1YIx#--K)-31&;Ugh zj-X5JR}|n-Ox_DBV_S5u4LJx2#ly+7RQ~IE4$#4YL!f_o!h!Py#amRLrrHmYCgGlP zxK=k=nv<`6=`<_L(7i?;_#lyayXmR>DpyGPRb~&W|Gf1gzi+)d*@GTcPHk1!$j2-Y zc&=Q68@k zuzU|pQ80{EBI>|ac-yIwRZz>XTam5!&m(2?57F762m5!l*HR9Y4&EL<3-HC}t_4h_ zrOp=@bw=1wQ%~?xg4BG=r_`RdJub(AnaLos`u->}VWus`!ehSuARMqZ78XjuUH`*D zyODip-mZj?i=NUX;_Gm;4Mc9HVOB;PQh88?6!Kx|ldgh;S#;q*>jd{DZA)Tk3_Ja}Z@|M<|JIQ;ifv4=`6eF{jSjG3+=NV)n zllMBDWF7Ec!hUGbg!mSRY|YGkj`47VxwH)`M`s=uO6eyR#j5FsNLO)-SyWsZKy8*- zH4S5m;+_ZwU2WSN8MVr36gAElBFNO3a#fR6AQfie!jZCoys}+&%zZT0fSJEb3gz9M z{B<|NVsGpq5M?{>dS~}N5llP1icv@jK0Y0MKH@(^+*f>uUdw~?#ikb`v*T#nI;Fy}vielSLo1w0$cC65PtYC6Zp7a{QN#x&xO=pg+R6+^(C z?w(KVhAC(+u|B2G+}|a-2^->N;kME|vwFPPvhS1hB>Lm=SKPwim4Zk6^>3(KHkqg2 z9*T#{9Uz%bUgyE0nA)w?E&06$fp-sQ3W~Q2(e&(ZQxsfk>&g2!`lhL55FdK83?cBm zr&KHRMQEPkRZJa!jTGnYwDFoi5w2JfLlx~`aaCd*{Kol4tKTPZs{6wt(_b0|foTOz z77h}Q#^okr7GKF}P6A-Gb>J%A$Jc*7$M6F*$gU&aJ^zMubasTQ$dIMyJIJ|43I?g3 zq5^Op(5A)m7>oGo7Qz|{nL%91=$eibHPvdqNj6sPfUCmCgKcb?x098LQgGFc#trtpWu`tWqx_+%?O?4KfwQFR!lp&3*K(K!1WUna`;lqgX4@*sEFG;cZ`oFi?fr*} zFb4aT+A2#G(Vs^LL<0wRRC^_AD{o0~ zP~aqemQW>7Jph{jdwg~xbO83W(}xrapoO%Bw3|<9QOll#`Nn7?L7xHv=YiP(Ms|pC z^FCgN+=h8 z{a1hQ8D|v|`i(7IclT4la5hK9Q_GFHo(_WQ_RF5d3Bxg?8$aZaP+Bg{Ou%xLC!Tx5 zB6a~DENd7osPF1iQ6Nm8&rZS+R5fFWTO7Hqp70!p;A6kq0sOPCq7aP!`8Vj%PUmi~kK->v=cZ^qN~ z>p_Gf{vMs@Ri!ATo_BfatO(8W8#?rX?r+sUpCHj_dG0ZML@MV?fJpBX!F&7^vVBzZ zn*kMA!5cax&dCpSn7OG|5O-G8`V0DQ`40wR%iMIp1wAl=2fikP=+wt*ko&C#3iu2A zJM-Ma0cCE#fC|o!xd74jiRL$FT@&;LgCBA^XUQUp<|fM}Ee1s5G;-Jn@;jyflj#Qd z)#`~Fdq}w^ck}%ravE~Cy?PC2<#62w5#zFDgl@~Wc8JWQt39zuG$ zaeYp5n z>>s00BVe?H_K>Uc)1bbGswWUne{_%8X5KCNfOn$wG&MI5z)szVAIUP#S+1m;X?RD z1ql6l7qO_Ut;&+WgacV=KQLrsx&Cm8TPt>3aeNk)k0z!UWmfU~=T)3$9)nTa)@~`{ zm#lW*DQ$k8wukK}1)}wx58%q2d%9Y(>&G52{Y>XI-o0TUg5|Y{vNA!KyMzyFKQfPc z_wuLX@IOAOWga__2bMfrxv5R!m4k5DzZ{&+dw2k=I@QDQctta-Wr> z0`$Hu1C|uo+K~_}3MkuL!qwi-9K{i_fR!XZI>w@jhQ*6nh@Vi|OYGU-KamDBLB(R0 z9t=ofWXT=0>obNuySTZHYQR%iU&}li4I~cWTS|YU_oIJLQD&}b+fdkdHJ(#PQ?I&T zcNOs}BfM3GE9z*+3#|fPe63HgmVoYdFI0$OuIDUl7v-Xp5Oh)9hD*G_1mRSxcBNdQ8La$K*Dd)!Aik9Qo(yQ9*B8tKSDbJ zy>+(YfS>{Jzjhab>?0n|(W*G3JcFG_e-~|x5;&C3%y(wHVSh5pf$Tl!`xs0eDcv0YH_$~ur+`T#E5uYLZIAS z+;KKZn(>G@N=EyOO#gc0!=alHb=4IsMPWkz^96@)#`E`wSKYsQ348j#zv`c7QPS!k z8d6f@|Hr&>68R~~bAEQFP0C}jUtZpGt}wOn@wHTP9|c}k^~Od2^@q`t zb_QB;A~k&a$$ZxX^yU7duz+*0KxXX&2lpd&3iWz~=CiiiGsj!usnOGddZEUR3&$zR z_nQ@u%i@`6aj5oFuzSwTaSHjhG(Nmx(c&*NQxsqGJW+c@8_uaJ7P>G0-T1oBiqUP& zB*`Q`{dl8j0q=Iv-oLE=15G!qj>n-p%~OOM9>=Ul`_RQ)UTnG|kKZNv%&9HQg-evH z*%Lg_XQROxA^d+qSvnX488?ZCDb*Q zA0Nt&-t2}G!IbMh>HoU{oyg5D5}qk7*uYc|%0CU130!=Cq@ z9$%R~N|7r)dHWM%7IqUhQlul%79()9np^ZQTdMSX@lH>aRx!n!0>exJ@$SB z_W^Ldor|54hT&E!;Rv~RW+?7F0bF6?TWbkFIZb~%LRcT7jc)~>`z@scMs9jVMY zU2rzHI?=V_Itp6J{lXDyl)MyjgZJ_3IPDIEd}qV5%ppVD{6jTXN$byhgwR|(v`0_b zI+afS`7Q8d&AU{$!eOToZ`8cYpL^T*%Tmz)H3T4%5m ze0q6f<~0TJBZ0%IKyi|eqiyp1v%hTGjeCTN;F<9qhR*aAQzZoj?{(ywS@2gh3&irda&$tv&pAmJj zmCsXP-$4HTyDMoYsMdIY%&#`jNzz9*A>Bdss~Y1{d3 z0z&_qFVd$;SoHDYCRpBc_id&gOgoxihs9?ay7##TFGA$JAtLG5qF;ZxHLVm z+^e5b`E?8z^sx5F4-(^S<$6}Jy>GQFz?P2(Xna;CMAdKAgNtm4-T4N@A}3RXL{z}{ z$2*;v8s~`PL3VFb0rVkadP(BM2(pGRUj6tBXXbTZdoaTCW5<7=u_<+}j_9R(au^QW~iB{mAmTnCCrSWa`$Q?UGFRY?V%M}Yu<8Lyq;>~<3xKn+y&sdSsJs#@e%hA)jk4)y#ha8se4rU+f$RQn2Jckg0FSj%8{mS-O6WzXQZ)0%(idvkv!6 zJoJ~4@{afI@)QcVx*lM-(|$ZFPdD_*ias1df_iCZ7~dP`-|l9}sc_kfJyS1iQ+RWD z2MBi$ts+awpLlCjASP`-R)cq6jEK)xAIKzIj(L+zx2gjOreNF~#Hr{ro;2zS-}9Ww zP4d~?T^`axWwMez)@JeyJ@&`_b3SVuXaO~BzTxO@{~m?;A>oULS=v~{WEsKDvuLT* zK7M(mG+=(s=T*yR0KU%v9B!|_QiZp{4CoN^1}3PC1JSl#Z&1|qCsI`G+ERr_!A27N zkv`k-i+~j(Y9J&X+P^7PEddTHS?L4Be6*M|c-5ofqauHe>sMYjDQgbQ>X9ngRd>|6 zlfunb>cVA+X|xIg!?kLJn}h*kQ5>~fwMyN? zwrJt@yD9;jiOXKA@bJk%f6vz4T_D--9zJIKX^5_MdxeVxXMuv=fU+5Y zYS4MN6IGxJWjdEtiGEfpOZ9a7D9>fpZ+jZS9yQ`R_HB#x*;5(VC7&wKMm$b+p`Kvr zV4bte9tJ}1FDfL8YycIy2-wDV)h$bDOd(Bx&s$G5xFVlDpW77`VFL7Lzm6V+EPX+^Fr2liDRbzh`?>xzdGfSmb@&^I;Fm5+UPR zC{xN>9)TxRN_I>68ZJ0Dr2HNUP56$1;FAeL(4Mwv`3&Nw?H*K^U~c2KyPqreVk0ee zd9tTSJ#;?`5w2fb4xY)Tl1p9*nYifn=n)2=V>mKjUc-t-@0bMkZlugl)dy#3#h9;O zwVgn|l+W9`SP8FrA6{^=o4A1ItmAvpP(1z^iH-2~hqnNSw-Z|{U-vMPRjy72u98>k z#Rn`Wb2iHqYlrMU5;+(B`Uy0oM_*?G#TWf_(=M5%yOuH?p_ww{0qUp5d{*V|m-p*k z{$6_t3!tyqXukO1v{&;v&Dh@spzM?Xe9v#K;jrk&6X&Ct^-h|pgZ(}2YdTG5HxKP~ zf(6hFW|n1ckJ5TK0%AkMrAeF}QhhkHG~M+z&${A+kq;G^L>D0$(Gf2$PKHc1Io^t+ zlb`S>+iql)lEdX##rX7^bk}4_dj+~)fimar z%WWad5YgyjMcdgAAtB<*p~E?^O3w=&uX!+_kaUF@CNwnk45&q%+C+u`^{+&=NUr%{ zxBc-73zd|ruM8&_RoEYc_cv_?F2BD|E%Uhbjq6Z0u{>b)DD$h@>bXWZyI-P=Z^$L{ z`ti3&a^)+3mvJ*>^tf@^8|3Jv*4D)1TcfTHL3e9RvO5!|bsY*vhJwqO}nM<@|v7e$Ejn#|8&- z37*Gy#zZ6%ry4=r&O#31o^V!$I9`&?^e%frKGp(NMey3zXa&4Le93to4Tfv5aks&q+-aNA$iiNHm!Vs{Ku#XR z(d?doRyY1fF97?_B<|VscG{Rr5lX$69W}u@%uk5-P|||u>&9{{*i`~%nqGP!m~XO6 z?t#h>*&FQ6K}}rS1PL&TPqL{dd~^(?{#%6dxTb4oOo#PK+4**4==Y?$WILkr^&F)j!ZUphn;3R&&y*l0Id7FvnXmYb_({9Zw+u7t zLnmTYi^~Hm!Le63&PO8zJWKl1+VE!e2nRIAht)n_gcWa3L!xGO$=XYZAV zy9wY-)gJ}Q4}3l)WgDs=Wxv^xpy)%+6_`-yd3`9AMafU-(3Pvh4%fj$c6vRVFw+&i z$M*p{#uEgf*OrKj4%dD*V{ZYZJ zX>kwVCoxKTX79rTY8>X;Tt8Q=`Pg-a8IrEQ>Nh5*akaF@wu}om$_q=-`8*1gcO82J`cM7sz z1Qf5RB{!r=->?r&T~W@Sq%#31C_Q@!xSWoi zmk%(g#Hpyol^6IkA9@8RfmSl8siV8+KK6LUfypjxXa$ z8lLD|$zNS&b?DD~AnEHDK~;D6;|=uUaujbAFo3smY4v8`yNvlJPw$B$UIbWr*@Tb9 zSxWOghU`dYuSc7xnv>D?W^2<5aEYx9hD>nImQFBYH|rW3Z1>SxH11*Zm$3U+F{>{L zUh>)Y!QWR_3yj|%W9^h+ld@dWU5UH4j!7Kb)GrvQX}VfbzcMKKp(#Fs!*^{~r+`ZA9K|Ko85yZ}Nvp*}=*v-h>a{I-(K$!BVGV{UbQtL$bCtH; zC9v8PUfkNv0lrpy4=_7Jzoi82bQuMEMhv8<(cwQho5L2XR4Y@gz9=?v!Pr3-OY!;v zh9Bm9vPo#QDA~F^^NYBFhSoSC-09v^AfTV6}$Rk z^D+jX@=zIuHm>94Ess2#1vpcKmZ0t_oU(o135OzsSk6S})k4v49B13(&mbilNhMu* zT-CDLc9K9c?xjLSK)kFs!svbdxMg|zd3le{x6>6%a!D@iXZmhO=pk5BvUxL^Fm!%U zG$A3H|BV8=z}_?4Ls`hPal5@BIV)|^Nv@76-r53gij8i$QP75U{#ta|7@uNuk;BzSidD>(Sj&o;L*i$$xz zx!{k?DjvBX%-+TO!6jYE7^cqH0nb8kgo@=rI(*-8kgj)}D^ls!t}2LeL*> zvTCAxB7&aX^v9vu8$^S3wC0i05lK`g1#Gp!EPc-Sh4IlGj}K&rPg&uu`q|z1>v6mD z#}JbFhV-^D5Qa2&|`p()~t{zHznm~8R-^6kf+%7bJ=m1<%1>zM46fwQjO`DYc-0;8bTw+(XOdzv`x z*ZatN_bhavQ(~LT{*m)mZj<^*H}iK_fRfue`NrWaxEu?q*(soqE-GLXI#Muh*T~v3 zD|2pac63$Gq`2DC}= z*8$|q{mRLU(nkBy%$3@4B3V^oFH64YCoU^98DR{mQx!lZvWQ=E46oO91#$Tpqi(kj zDB_@xuEPU@5Y`K-FR~{Hc~UBJ#WE|Q_*)jhhC@aTNM*0+Zm;ynGO9&*h&0#mYA}lV z29>;!FW!H(((oOg)c(I^kOJ#Y+Igr_xNZYZ6C}W`gT# zzA?Hl($gOX&u(OY(zozQ3TN%s=Mj^{@gNV<%i;hWv*n{Oafc!3(~o&T)ch7zB=F5F zt9Lg{heKjRkcvQDufb+}>^&oFt^~uN-|FNQ8jzZ%bRYyF+6C9Zb+`!y1592eb1pVE z#+(EKUZou1S7z^BDKfsmaL47h1$X-jlf*urn~#!7FRJMJq$62?-#*-Jsgs4xtqKUf zI+Z(O^JxtIgciugOQ)|W5TtTY_t4*hU>SknB94{3U%dn55GQj$&Bxfydk523VS1YB z`DWn}+(35R>x~H#Hwx6@fpun?bty`E^BY;GYzyu@OR^yWBBC$rOjo+8&-3ux1$81-+kZ3R15`v zSW%iHt4Nb$T$6ki#~PB{053G(h#A?OnI_0zYv#~>@!OSduV{)v*KE3b&7wt{QUWq35Jz(OIKP2tM!Dht%upFBIr1 zz{9$&>0`_HKAIT!Ysc(^B8G&OWlkc*`qh$6Y?g?qushi<1D;MNO>BXTD+<3TirbhW=3V zj|9(sY)*C!enw&fGTq?U73Lpg83mo?R7vg{|oonShgaQgtnMN{f); z4GFyTeBaUu&(8&Iupc5obh4-(@XAHqy3Zcy?&o|!i5@Qol*RyrIqeT(k~^y#<3Gb( z7mN=|#27O&a;toYUam`fK9s2Rpw@SFf7MN~{zFKe-b!*^N?<;B3n8&TjHa%V z^Y&4ea~_J|(2IZxr?cEt8r?){OxjY(RH5QsmxjuaQgPN_)atBI3NZUkG#2iUUI5=U zQ7;=ECuVjeoPO0uS}F0%YwE0Spi_rV)~6O*$s8S&{&k@B*mI=H)Pn^BLY0lD&yNAJ zrIj`NrCZ@#Qr9jj7A_P;U@NlGE8>82F7I*>Ug9;bDt7h0#CWj=`gRFfNew;-Rj^Al z3Joatr0T=EhM#DUGQf z5ax+1o6|n9@7IBtZ2U=_NYBxbA7^^mcq(z@q7eLQ0;yZ|gJQsDb*j%GSSL!UCQ~QD zy!2r^&yYjU1%D5FxnRN5X+3;O5DgwNB^(3t`cEg7=O9mcR60_&Cr?C{IGO)Iq2;{= zV+ZGPbJACshuGZ~VZ;SsV%2gsZwQs15W=YKfgXPzDq0rg1SvCP+PX?)uv2_I^OEYp zF`?o2#XvD(NOpLCINbfZp9`7s`;KY!>vcZFSv>26IrL`4mK(l5GKA_We&45pPw^hh zrAT{y_uTnD9<`5idhfuKp5BnHtu=cQb>daVtB${>TaKJIK;?PGUIH6HJPYGjp4{f~ zRXlD_pGE~6FKXB@NEqz4nb_8gU|UEW9_Oe#;bX^140QcPwD(+p4i9%RWsZ;n29nx04D#7Vrqc&JL0NaB zp5pC3ScNY+-`3}92kdd+ij#NlyOiL#ciqxo8uxZX0r+j?m2XdWM?g=oXqL6UU3HMF zdXPy@t3n;J}zD-u<(v;UZFxV1>uNP#55*W|X`L+TfOL;=3Ph9aZ9qKx#>8=9jjBXNSdDxw>KIdycFEJK&l@~V# zYtNwFXN(wC1S+JUM5GiH*UFlM8&GX_{B-4RSwZaxVPOAwb^luK5bARM%PEpYH%C#z zRLe1~mND0(?9l|(mq4EOWG$e|dRMLEKYl8Z{V0JRSptXkTw_ zFQXb>Bvp2kpJa8IUPa#%X9^HU1g%#~RoEFcel!qj1LB4_Qe}=r z7_hO+VWh;*s{695wnPTpJz&sD9X=6ku$4F^#~RO~uR6!YHA{HkOx7e!GzCn+lb#N-_iQ84kOJFd zneRMA>PX8*e(1q6XO6Zsu>#*h^5^ZNF|(}$OI?dV1meoT?jB(+_c3KBH*Vn(6WJBK5p$>p*o(S8ryxz8B zeqiH+cO%Q;Wz`c)n!jdZnVGyT!9XCgdmz#^JsX{=GW*<+0TbIZ2B<813soSJW`vxU z#hoL+z?l}tALRx~72s;>YWopZ&6ir|q||(mOLKJ{P37KINK|o71B(68R^Yu%FP|OFG?BH3#7+^tM2i1?SEFRq#jITm+ZX~(7mNfdX)dd@#H60T842U zAd&?~wp%pBP6I{C6X%E_doxDZJ{BuS@Dg6tZunJIXV7;*4%O}1y|5z{6XqtQ$A^ z5N8uiTtZ+D06A&M)5Vn3a)yabGVtxA$&wCB@mlwL1VP#R&jIPq(T7Lj zt%#7OON{2RJ|gr^x#BLP<=tdMo#g&JWUp=@9cs$M1&SUbe(2(|sZ6PRq|fF^j~b86 zUCl9MqD%Q=+8X1ECeL@p=#)MT_iyhW@npTqJ6wzrPy7Vb+RI%fn@c~-bQh6a+ze)5 z5!;wx9#4fBLa#qI@ zK!moIdFP=Z1lZ3wC%&HdmMl=i3(I?xBmiRfw_T=jJBHZ?>Kv$WQve-P#?-yuiSx_@I0w=wD;2f!BcS_AO+eOI4WmJV~~ZB<$hCPMt8qA402qO_?rWdnE24(v4;r7P1$R;Ky~}qPZKacmj31g0{O%EzKQe(%*P`=xW)=xuP8oQuy#yKf(dGzw1b7R!k~*uG+m58UzS zGbl4%smp(D5)tN7ms;GEI3f3J>q`Gn5#8%iUn~wb$oRltbl>V@!Q(HcJRp4x;6fX^ z-<}lAD0sD#x4~62>|fl^;sgZeU_n!T0(0j>f)+O4E4<5X(A(U&V_}K&&ZI@{Spk-8 z5sxjevHohN9?ot*aDWypi28DilM;&6`^$zAn!*mrV3(4e`!875;M7S*(X87hPIYu{&Ple4g1> zK(af|%z@nN!dc7sqrofK{~qB9aiq1n!{;&h_GGumO5>1M)mX^0^Ft0XuACOM$2AsX z!NvO)GU7V%x~QtwuvOs?B+it}*K>hm)$y(+%$@!CVfA;JpIz)SHd~5*FvEd!tJaVo zqHbTqRee+T=jyIhEu6{4J6nnxGY0H1GM{mW$8u_xHNzQ~FtbKo3`%En!o^_wcT!Al zg$e%%*xdx@Tpw&HId8SySJVsi2C#=#exkX(88GW6%-_XTr_Y*EE)SQ8HFgd<4Mi#w z`)R z9E{1F8tfX@1H|Ozd-t%nvVQB*81L|F^bW*xUH+URBG<2GzG#$}Y14y0GT9SEf~GjW zP;=SYn7vYb3IKM<@aJmgxzmfUm`#S_QF)(|fRg~g8Pwi4DL@&CWWlD)V6g-JfyZQT zu>`pl>_9%wh8oL}?qDAUA{chK9%c6ALBfgOS@z&u_b7^4P;b%RknM6WF@cjOA`ew4 ze@Yby{T&=|<1KlCxyC+6!q;)9lIgT0vb0$UJ7o^T-tkNTJ3l>W)spTis81JCApW>_ zM=`30HIM^$Uz+e5JGnBLXBMIj7Js#sqL%!k=>mm{J2*ig76R~B^uX{MchYxLAhnX6 zf5*%A%J6=S3XH!azW8z|U5ZFY+90U$?w~{>;8RLGq(8N%u8;Q$*vOAx{r5*wAZN( z*zPsE8jDT}oRH3QfPa3j7a$MyQjfo4Y*2P09CVHsaQdOD)W-d&$d-U~|na zixF;n<{({Cg;jz~7_*R=0N@DOXNUEd98_M&X6e6>MqJNst?Obcs9BQkN4fQCx~q$@ z@2zp;RvYkcRU&cW!HlN6p?o<#`=513uw1tEsO5WMuEERq1%>pn!lNy-5i@)KEh}MWlm-5_&|M)X)Qj zkh9@_o?Cp+_}*`v|L310viI6+t-0o!<(k)gv}nFT$?!uxM$A%;GS4#*ROZ#ROs=t7 z1-CQl4J`G3UhbDSpH{$KnbQ4FuE|H#3<0)ngLEy@4B}p+C;c^-3sR;ZM!#s%T<|l< zU|PwFU?4=e7YW&A01ADfTx`~Zfqll|JilkxqFNnp~I(n8+DXO$|wR~7?Msbey)Ql@{9o4q6yqy_#S7{OK*{YrW-ci!y3XA zOy`-;GbR8f_MIQwX%2+V`&zTjnYn1BYIhsOK0!1KJZ-kQdDu)(ixca6P!E;1sG_+ng^kYbruOLtX$j1Eocd=MH8FkjD3unIBX+ zH+2zyaq&e*OOAQIsF$4(9+=)52E5pP=w|1gR^Pa04+t?g^9^ffqp;-%my0=|pR?Vr z%wgw#!$H>-u$oh^_S9`{V4Jfwdb2=M2Hxih82OQ++HyM#5*-vo+t2w93n}W>8Fv&T z+o`2X;>@cLR@04^S>8iVJ#G@=`}O8Vsd~ncP9JJPZsN()GM6l`XHCI?QB4E8lB+I9 zE*5!|K_^4fKA^SnK%Nr_L5dAAyf!LV%`@)&{pLoXXW=xV*7tR)h)=nS`jqV1ncz9i z-8YI`j9-i#zFq(<{T*fztFOwdRoiCqyoOx`R3Bxl4;pnF!LKejz16_2Q{!y6S#g0; zOq0St-NmMLVr<9Cqv{@C4p`+$PMWPXGuF&Htw1?MYVX^`se2Er9{!tIY?E2ow>ONI zOXsFhHR9t>D~VxNX}v%3p&pQ@PbTd=sDCHbIrExo*sTzQfWi zTa0z-1^ZTg2if9+y?RPyKb2$pb_q=a+9DsDa)@JTG(+61r&=>}r*}ba$D`Z`+vxTo zM{%_$d!N5FPi_tc?_SK=YeFyKb3)Egi0VF|W|Xj+q#g$uPH22%jn19_(Oc$bttz68 zeenTvILyYSSF)Mj}gfjp1*btV1lweocCWq zRv-CNzpwU>0yR~jAC8}+(G4$)&tZVVTCI(l#z%+ab*%*+wT}+LhiX~sXZpp0UG@Qj ztLKEvDZQsA_@1z+6a5GJ$VTeEJcfPLU*9plOMLJ1xTs=bzK~%Y?cTtjA1X{J579^L zFlH60`|SpWXw}Jz;%))8uRo6}Bu#H8Rv{SFI+8ZeB}r||*{dG#txh5p4@KS9nFRpI zL+`-|rm=$pCfk>Ty5Bm%It{a;&P5?y#5^#6Hq&jR&l@yB(eix zGX7#k05V8xP;Qs)FnoZ)l$tHBCsaVzv(D!DCuJqLDZRoZ0HDaG7KulHynoW;a%JEm zw38rg=%nby-*_+sHPD?YD~g)H)RyQVrorx!?b`EgXpPTY^||J!q=_cl^PN+vlTMk( zL|d9A+5nPoug)J&;KUl$f9fw0bTSxwlQ!zP%1|97uu>HG1@=X(CON!>Vt^!=49GSw zh{8Jzn{H({Tzc|pbFrSCxd}sN{&7oaDPiS~LesSR)NjW%;~z4*oi7@=SE5=Hfz3U z+rS16w7gV5bD^^lx!Yn4_;g#(TD|sun-Z}{GbrH zz|Xu#Vvg%Kl=?S87Ycem>m%1PN;aLvbeFqCH@g=BAC+EVz{RsH*HQ$w6*mR&34qDA z%@k!>cm`ad)0VsWUJdunufievIwb~XOdgz;^|}&A%X^Fd;%=`bjvM3Nv+0k$NdWpU6w9&n0Y^q&nk0*oP2T-`sP9hvf_YCx zXd|xYy6Dbu2S>f(?gTXo^4S89xk3*X`~GIe?HN$L8<5T!1n=_GqkobnYF`3J?i9Y& z;9p(AL6xW7bDp)3U%r_z*+Ys#(L56eO1dHnq$g9#G;il2{-f5KW5m zzs`LEJsqtM0EPenP;wK0G(@a;>wA{;%gfi3_h!+o8$G*G4IDR3&FM*sOqaatdUOc) zp0G3-uOJoN$KO7k?hY#qo;I$CL2v*Hd4!zMVd-n~=QV=Al~mx0p4hZt z#?!S1(W1=mpQh2j#jPV)NXVrhM1~eU1E$#BIq_Q%eH{yDuN`D@wZ;baK+aJG$uYk zlVV;#UHV<#=wa$VEr`0|2vH-ZRj7~WDow&$5+ioTSLw%>sI<53feKHdRNWGj8>RFE z0DvmGJtNT4tAEkK2-=N7(F^b21o)ZQvii%;g)|-nkQz@mSQn*nVzIPE+73hH^80Do zQ)-lHp#BArXMjb2!A5T4lGh+%91JTP7|?M-EvjcG>$xXeiL@_m zZWgBoVc|*bP2EAG zb&x3Om%nXh_kxgwys}P)!->1jDFxZvhPx?&iq*o}<%_OH-5O)T^BG+FX5bHyn&{4; z(@@#76m7;>4YloJPqhVHaY~G!L1>@EQd|+b<7G1%M!O2n##`WciQT4%`@cLhb#NYoXjnYrm<%am^``dWVD;24w@>r zaY2Vk%6W^$Pa2DfG0PPxqqx?`V7M{)Y!I`MMHX2PSo&+7g%w(^j5 zS(-s8?9kd>RQsk<-uA^jdB4;qXUX}wX6jc2EIpKNfj2ruCo&3=rqtp)v`s&jg5*!Zeohb!P?2^y_uVO6k?}pO5bYzqapF z5>ZD#F?V9{>E3xBsZcx!cxLAxvcMSv+D86l^OvBOvM3>5Vr|r@X zgG0{I3HX2d^4erhsXc@dpplk$TKHzGSb9{L1vhB0{XJWL z9>MkrpN`T{S}!sAL$3uKlajPPGKl|S^C?p{4aJXg$;8}Eo|W{AS^gO5>%je87l^Y4 zb8q9iMyrTQCF6Cs_iyH*<38BHT3h|X!6pk{bsBjE87Uicn>34lY%zGWeP3_Rp%a(w z*Edj=_zQ^rXLskxs!9VB93Buk8*`GhjO1P}2qHBIlVL5$JTKnrJJGRce{n?TLfC%H z5l!q_SqKgKCH@hVYWR#6@WbF)I~s){JL#72JR&j^GG|!j`<_w48XtjSI$>7bi z9|b<#_Y0nR*x#xz#a8F*=^G?~R{SYh=l2703LZ$1-a+VL`E>dNeG|z+4_|auBO35M zwlt&aCDC&=Zu6U^{bydmFb;=)GDQ69Zxvc3Dx@;a(kz%J<#?DDKd!6BTZ=oSPUb`L2QAv|W%QC=o-oAF+M?W=NcR z@WzwrJHzg1B9(FD0bhY_k1n^;wmuU3q+i@=yte(oYv~%t^FyzfSLV!`LB6ogZk^xI zZfO=S!>q?5p~C@RJ;`=Vgq=s8WrRi&WrMX2y}}QZ+$QQh0a;9{j@gq~gqVi_4YJXa z%PAL!AE5mDnwz&Nx7E(@emQ*Jo4R5s*9}QBuLZ@0rwv7pmKb z{J7bzLa1!nc1*U}g`}+b;|O!OpT0MK5M4zNcj+@V==%17;^{EGwn6E6s+%!_{bn>u z;lD4JpDaywy>(oiW^(ZxoL9E!#}6k7$*h_HxLydlrAp7;ATdX!>M<-NoQBz7no z<9Kmw`q>SLO-G@7f?LoJY%bN`{YWR68uUj^0-%(Xl>T#P4c9z323G3jXlZ_+R37D} z`p48X85_WD%O%9U-*THBq!?S9Yf4Oc*AWkSwQvKm+QpE)xTpM!+vVViw##x>ivzv0 zv6^}9C8mg+9I_=1!j>F@$KbxQuDcA|aH@ zN3W+C5@Jf_0W*UYUc4dnH6(ADYEE&YKCkVLB(s_zWxf;oN36!Cu=@}rLo&+K7dCo9!h7`xP6861qoBODBX&OeTndNIcmnI0b5iWm2W#44>HslGJkWPC*PE&S zHL)(r*D+DzaQ76$NB8qf1`YTU4OC8hol{%@;O(rfQoUZ9_-j9eTicp=0)+L-qseT+#kQQ7DBny>3GvQCa=q* zOf`W`e`uv2kq2)OsUwF4vZeb4CaR@wy%SFhKu+%%&vbC{#$Dqv9>Z-frt$Jos_!KL zZ58uG9wj>8uA^Jw*TQ_Z@$Czq&#SFal3L=Ry14nCA{k1n;*Ph{yROa`Cu5XI9Wem} z;&MJ`bn3Sk`$)eTUlsDOgXH|G(bJ~52(7!HJO-H=R(5(Yv*g3}8Ei5*197F&|X<_HNxUZ(o)4TLx3YD3|eN1ys?( zi<_=2B%+2Edl;_Sk$FY$8UvV}b%9}aGNZeP{D?KD|G`10bH(q3JKEExVAqEr%UlQO zt>_8B7PiK*w`~J)mfPgtR9PG+4@z5tQ+lL|9)-P(BG%bnvYRP#_MW;&6fzB5f|M%1 zpDy$(Vh`9VI3mIIV|K9o`I24hO{f|DVPV6AeFzwR&SpsUas)Yhw2;Rz7ypapu^n$p z5t-fbU!FA=G6Us4}lOXCa2#fn5$iG*gU^;fZtCzFFDrx=4_OjB9;U+YEG*?vf7&Q zO5c24`us{Svl;3q%BDXTuQ|>7(LT5!18(_7cP&uA^we--2_PSE|cS-qq%SJMs8608jPw0hX zW0BvOmBP0wndW$)qur7ii%fwUo`=o0zK=*zT9Vg}>JHwJxOaJ^seVl?>DN_qpTNt3 zf-K=KoH-!r^2BQGGggvJzT9k?0+8z~yY#K?0DZ9hYbV1#U<-r!=TFdSuv7z?FQ5_u z{McH{S?oz@BmbyIT-*?cO47nj>=LR^V>)gq(Ba4vV)NfhQcFpffN2?BOGv&y+VZ9k zb^DpI&{16ZJ=3*>qjGA-Yj0a+lFgFOSvu9Pi;2(v!cVj3UI<R)a;IT8XR0-Xmw3UW^PMHNLu0v1OK53RaAE;})ncMvKPoq~{6TgUX~02{z(mRE z%xm3zK%;@ev4S*#-OTQ@v5`{sF_i8LVzA;|+9CMakUo#aK5=o(ysllp3>wN~tYo%H z9gwS;!GUc|F!52x1KehvLf>*}J3I;>Q{FzxR2h+##3b2i=TXDlwRjM`sWQo{`8c;F zo|SHo-r1SWg@+9?Nlu8o&YNz{+vvrtG!&s)e0960fVKlJmKH(?G(0G35L^u~e$cb( z5cmz?l{=kRg2P4cZ8nupELK%JdDazN(~}Dn!bu&zR_5qgpw8hjt?vq%-;$x+o`7H` z+!}n$j2zYFpNFoeuDlf@!GW$D@YS?^Lz3RD4nTemeO z_Tb`bVxA3s>Dqa4!q4WYhWVVqU9-RiA8}~aD&zZb>2I?d`M3Ifw>4s)u^ISO6v!ID zM$3iZ1sSyH61#xl37fcrQzDkXS~+BcgM#3;;}br&eJF8eS=-yv+JJMC-0OQ6M_XG; zk-jGfax#4p+P7tNA?K{rsSfcpuvk-*1C4qlYoHGv3D)oq*e7YV z%vN0EC`t|)6^3mabr-wOkS3YwNi*jB$Y+0eo?z$J!b%sW_aqxge(aM#U&grAUJL^gQZsj|4P!F zQoHZhY(jeMvz8dH?1he`7lkcOlD;D=-D=R%Kuy3_b)T=mZnsvxHrtW~5%AmBCR(e2 z(8LbsQzWh@@v3g4M~2H85VnyJq671t!EGwWO2@I|+4Q6PUyjE{N!w}GS+!@l1>hsW zh8e9X&lQvHn&OuI2$@s0#$w=|$=2J^J2eIT<8z}_W*J5tJ<vDLVdQWL`qT^_8@b*Cqo85ah}SI|8uqN2L_H$E z#%+->;f@wg>mEoI2G{nKpqT;ssJL(=lLcgkFwWh%P!Hm*?DdIq&&r^eFk7!!17~Q z&Yt`<0k!SsbD9kZWLgZ&fI9_P(N|G2918YsDDcVrrp}RHO8+%;tZR?Om+0Q!W+T~U ztXh>q@di&t-#ZCNnsd{cynnIu`f3Ar^Nn1tc|yUaLzb z^=%mWfzBIbPy!lw1n3d`RN9y758g!Pr}Qyn(uy>L{|(XdL+V5ZVW)T#wuoHaKDSx1 z4La5v3klCJE9nFQZj+j4IIOy!C9~)8&9meGA+%p-zZ4ZDKpD9Je|flLTgr~)pbAYX z2=5V@7I1dg(uzqP6REQ^tg_RcO>-^v8$%ggzrQAGEUAj~SyF#Em{*Vw?PgY5a>K2l z4nwNJ0Y9nf)KD@;dB)Bkr8Ku{5VqG>SRbm}yt~q(&6pL}4}S%u+}d)d?m>(JX9+M$ zd=Z5Je|c^UdS!CXfE36*DyIdaFhU22r@RloNH`kB*$)&oFIO}@`zXC@EzEQ{Mg5}% zke%6x5pX@%iqzWSgpVK2M@1@)zq^sr)6~hFXwNlW*#FY5*6I6J)CwEHc`~<~cUxAQ zzR+%@qE6qm3(^1?k@PafjeI04NUv<#NAKb=Te;@jp$YVYcK3QIRhak=8x^B`R6~#g zs1o0;DJQqRSsurhYT!NPOK_4=hU^eLb$MsM6j6)GXNwFm-V%|r^Wxx5|EoIEklMMP z^f_HS_W-9+xSFfG2=r>j}M=5c;Q7{uIeOPGG;`7LT$6*@pT1 zNKN2pi!Om*H0OeitLzGZ@M^tL?V6wQpz3P@aq#L#$FXWZZJWiQOcGGDdR*nhE{}*W z$0*wZZAnYKidJCT(8|X+|Ns@0GM-E_BT_~+0X1tr$5V3GC85Kv7(uKo{L`;6v?1aP7JfVibsi)ArS#-(l{-yR5R_X*{%9WUjoiR~+hY zp1HGr9(B;~6*4NVw**i#tHcCeQZfljy{goocU}1&kJ(pS-w9HbPS6RmI+>m0{vJGj z?+r?>{n=mu@S(uMbOz)#G4j-@{z08qqTi)H03)=!cIU?0mIYe94gDkt{^3qYTS49c znQtlu+gYbA&42~WT*j{-O;W>d7Q-CZ06{1@uYRFqYNUIab@vSD@QH5zlSw-BuITir zyXP~WT~=D!^oH!s^!F}THHf*{hJl3B`nn9=p~kowkUSv>9)REJ43`T5uA;!7V9I@Z zfTR|W4)X?@h*Q)zB}-W64sB`bFQy|>3I*3>hz69jN`A%q)P0|ySO75x=ep_%b#PV4 zDZz^(3)z}b=cXBuuAHbdrqMLnG!b|hvfpP5EH^LlYVD!@wz>9CIMhj+xCK474@{dr zG${D;eb^5HeC(M@rgp*}&eKu=U}#^N*32D!ko%mc5(v(9UCV`#x;4sZBvteibAVt& zi}rQ((lnW5B3Z==rgWK|OULKMFG8o}1Pu^=Ua5Y~jrq=m zXNbm;N}H%8{)(5suVRhTI;x7Pa*((~QlGhz8FEKzDVHdd{@ggkRV;vR8{lB83MSw1 z77s07TeN>}^{s7YL60z)dk`8@7(JKqLRZd)PQc!Q5JtzxCQnZHVGP@V2Gd+uau2|c z#NHJ%3p`l2Nx~137?wYSj@{jNkWSu>oDn~00Ctr^52m5{yEGaMD~R5akqL%B8Eli) z1zZGHpngq{v7yp^ix$P`ba!<%QOT^ijt&wGR|=3ji{jrfjG8$dZ#=wjgl&y!+8nPh z&i@GXo{=OoyDYua>1_T(4Kx%X(DN5V(uK$OqGJK^1hL~KhO~{U8}0>1h71b4$>GTk zf{Rv4$KH7OqB9$rzSXn7pFicMwL*i$$%VdO<8*z0^P#LpzE4995ArNvUQEAS z)Lq-`v%j}--HB;7ku&pFpclxusllJo_@JYNUzj(~d7g)GWHxeLqIBmwqR{Ty>y>86 zK_*4^1+M|Cr`@zlE%~Ci54iA9v#Vps&APJ?T0vlqib@xL2Dg20BIfEy&DnarU7o1X z>=6~-8wn)`=)sxIcGvUdQAkBT?BPM&2Jj;H!CsQyqSMlp`yjuq536o_)^wc!6IKqW zQgyk0^o7Ji7# z+msrQfHb)zG}k3W?EdFatRm|OCTnV3*>(4gepYu;L4iSkHQatF11E8(JGjSd5UpR2?ECYdkCDa$8l-JkZtSsKz zv|*Y6Hza)z7%uxV*J~)BB`Mz(2{33rR1rG~;_p1>PU@`q^8KGW_5Xs^f|N+z+*rDq zMJQ6iZnK4hZi9ou-a0qPa`y6^wnBd%C3A@k_(Iz_UPp7a3=T==)#sdC1_l4+0!T;^ z5Y^wuE%Eql%#;I0>Zs>Zx4BZ}rL>+WuN8$&Ag~(syzc`X{8eX*n653!i~{}YW;%ve z8f4C(OxmxL7(!$OU;%H-2yVcZ0-~%+b1LjJ^?3Rau^hOY zH_0eAV<=jAcmu4>4LJ56q=+xNlZU0YTQQK*k3wkh+NAxOT5FIHq-=Rzin_Cfhj(kI ze?e@_6jEfX^khs`?z}3}H%}SPJN2e^OX3j3afXY;X?U%)E`dQFkD5C&A)Lg+))Z@T zSKgPJspKEq4^trz56E3 zbrl9taLm}%4c({$vu&kl$(hI-!#}B^dx&>=_mj=&f&_^DmM2=T1ug#*8U^^NO-}Lw zU$~npqd}GPK48=F2LBcdMg1N1Dp3<8|t^5ovBk1!C3yd*hAC%u~A8)%3Ypp(z^zz0~3 zKBSTU*wD%szm<?ABK-V# zZLbyc8(Ao zBs7FVF!fUW)4Fn?(ncX8sRx$cun_R1&-p%ZeF5{E?z6 zdTnP_{?vj24ol|I0e0M8tP*-MTPSc=$^i0-Q!hwBGE`3tu!?xhycdr=rPEn6b`D0O zi*v@5Ed8P-kx;Y8-xT?+#+|M*kxB*}z42ohXA+v&f zYgU>s0>?e3x7qwXDkxtq)B}eUp0P6KWsm`6KNiPy)SF*qFqd4Nr_Sk4Cd5e$uYAzK zFOgHOEnJNiqdJP`%w-ro#hkaN_H5ELs*%$AzzT>*IIo1cM{>7?dPY%XD+LFn`}V8!|fr3=_^iemwsf*Z5U((@_R1QP3|2~9NNrM=PXF|)#C9~ zUZUfEeTP}=fJM`Pm_;aFDqj$!`$WMWF}LrQ32*h?F2g)<3g9*a?l{>GQoxFhgT$Y6 z=vIa#m27r(rIb93M<>$;TvqBNx9&O7ED~T%Jnn_L@-|EOL_7j`UV&u&iqfWL>vit& zEgj+`e#>80e&}fo16Q0n^dUsN(o!2=ZB$jb(Nl{?s?)11jX8g^{nRN)nI*X^Lzg7# z9vR_>4?y^i8)whdE)FhN=y5V^?;9Wv7TYr2I@;OmH8zZhFw#)pkHoL;KP?A>fV{W47w2+{q03vsMWhGzo^AM>+oO@L~hI? zRG~p5Z*_niT%wf>{)F>2NB7JfoSmI4k#xvN!!F)E^5>V#v7T$2%@WKLKZbRf`=(d@ zep(`=?nme1e~Wmx57%{g)@!8baUgK%;>h{<2EDtm`4aqY>mmXh5ntGGdyK}amUw-{1yf-ZUQ zNiM;rm0*hSQjN{!aTKOx7)qeaV7@*K#Rc}J-_>SytZk4E%&O6#6X4FL?dP>~g_>f1 zcKPzpwAg4Z(-ioHy>9lWX-C>7eAquHrA@qAJZcWl@RSsSKeN|$=aJS*}9M72bSN4aM15+KU^s4Q@6km-S`fi9w+yGjf z_}?=*$&tJ853_sECCigZtqUw`m$*ADtyQlE z;?OCx_&FDi^^7Pst?bduEz&7?mOFCJ449^|6`*&u3U$cDrOwox_k;ZWd|JHQragug z>b?H#3s|{|*C;{f=2^pXpqrcaWryr4F7w9Jv@D@Er$_qG*%IAhA;(e1t=cWUYrG}~ zjjVjXKECu8HPiFjz<}u5a#s;H5Q)q3@UU8;8*R=;ajq_9bd>7X)lQsK#X9; zBD&S0=Y!x5oB6d*PMp6Zl0H&Y!Q z(&TOY$(_4+F$)l^3*<%rHSPcx^{xBydj0Z$>*jOfHerd*KPrIPZV&as0A{UIQTo}C zA6vF*&o-LH`w>E$5n|^rM z()u8m>IzMva{CqeX3@J-xLeWjYjUSf{d-!1902$vki!>ZtTy34;oDuf`$|UP3 zdCxCqM>$Rfnqxaf@=oTvs;{JF(XEP41oKGKl4NZVpJdbW9FCTEA;tJ5Q{bKCV@%`!daDNC} zqc0q9HS1TAd8WS%83uAIf#_;br^ZMb2ys=w@{L_w=Mz>QhRD;rN4D=T)w>nwnxP0lF7Lf)4Y7Ffvs@pi|}Y z)I|w=)T{P*%3*S^X=Z3|?4KT9q8b4IvbY!9$o-0tzWm7eX{HCl00e^UsPyX*vqa4w z#{X#8v5C+*bS5!e@xR9#IDA2=T$jRSMjHdpTXjntFAt=N>W7IR6Z2lU3Y-L}8*3Nb z+lNGWo$2^yd_Mm6@8|y_EWPwrH3+c1#@_=J#A9BoA99fRZ&!b0 z9)p=?WKQ$EOp-P?<1nf{)$cL)dA^eeNQC@4Vi+5@=}r4X8Ea+!k0puyJ=^iu1}IW| z;|C5~X07On<#H=Kf=3;=)CvCkV-O?Pu~H7C1)S zR~Jt7KnW@aG${}fwO3@cImuTHa9;!E>(|(>B2MD7UIU9f`!lo?_UFeLgX1Z zl(GLg%0Z0Wz|NnSHgWp%BTMUXpNjbB=Y@q&1PB2I1aK}I?F0sz0Di!~imV(6XkDX_ z-#@7v?Eev+(aWtP{~hRf$e{bce*}}YIQ@D2!i)tlUD4esH~T+7is~Kb#TdnF>mL03 zslXfBCV|;j;5MfhPweg6U|?1T_fY3ge3aoon>Z9H((~60F1+C=^PSKW^-#)@t;@1x z`f~D1Sfcw$1)}4*659G`!{*_}(}5>GzODQpB|iM6`~9E20+jg9H3LLo3Zsa(Qb#=R zZJ&+Arl739{y>(DQN%?_$YK1JkK24q*lalK0Mfnk&txxH9g*q+^V-~9NHU&T%?*;~2e zm;Z7xa8o`pCd+rNljQ!DjN+PG}6#5zX z3>!XO<^9Mvb+Oj+wEUcL`m#UO1mkQo4Rfzs2>`M|%p*sY}hkuyyGY}ko)l3}@Z7OpiK?}%90N+bXD z1%9v>71N+Ndn+|Q`p&DAKdounR!Qh($7+Z#@3OAoUfGHP>9%J&3Z1LH@k@U+l9I#m zAXo4-pC|rW_3A6bUOzuMVAAgb``E3A?ru4O2R}+`2UE<&-j?4~os_8S$0SLfID0ZI zPR9x*eC$hm@X2|fBFQ8bNUUyEn~nYGA#-$t0|v$hXI`*a$Vn~Da!H!Rh>WLZ?}IS* zY3_zA6Nd#S3(e#3jQQrcfA!c=4(#~T`S}Ay{z`zH{E|PX^WT519Y-HG&z+$-xo!W( zHckw1;x`$Ee`1zxyHf@ygy8=&l+5SjBy2asMS%V3WVY>pANdB*iWaz$?o5aN!+QOH z8|6P!1Mtf9K?2VA%l(WRj*9)v69addY$?7dL`0V7o-(u zN&bHMf233duovFT&@-R=OKO1w8ecqOSqgJYdZqO;T2n2fe*lYCEp-id^tO9}*?czY z1zs%fSH-lWRfRhD*c0OBokUp|Rf(&;JgB}c=t_6Vb`E&<8Tf`xCyO|4IUzhfkxN{S z1!hx}jM{1FXlLMGpHIBOW%ZjKqS6v`*6LYrWy8ak#Uz`VbXn6BuMdW0KX4NmD^!jB zY^o8|dab)JieO;EnGyRx41@n16hI*y1I2o6XH@>0X3(i1Z7lw4$->A!Dadd2!D(Zk zl*>W5CLaQkyYeNo|pwi>h ze9`gpv~gG3MT*X_)Lb;YN0H$8E_^MVDB85!r{!ZaX;)XEOuOLm)a`9oljQhp)8Pm! zu5l-OM#vpZ)r2getM9a%cPSMv!iihtE;TsrdTrFW`ZhQ^f~*SNticqt`(c9*d)p*~ z>#Mtj)^VCF-K8I{cdqYB`me{jTX*M5K4Sj7nQLdQO``&Uoc@P$li4{|d_4H~MkUuz znhaMI0F!i1aIhF4H#x<-#_1}&y}tQ+3Y z>%SYSW)6SkAzF6RkuxIzRrK_y9X6n}=2~Zt^Ux^HD_JGhD={qg7%X*is7q~u$3kP> z^t6-qudD6r1pqNu?T8NKh~}%A5$E(8c0$BZ4F^!n_R{P;sLy7~>(`3si0{?wAopAw zGQ}?s#EF^CK?Y^dLWNd_xmd|(AD;rcGhf}0-QH$7x@_rHQ1muazwf2M| zkhUWQ?gmuseg|!4>KTN%_wQ&2;pbJhnb{~t@u1d~5kDEV^#|`fiWS_Y+}~AnN0_F` z@{O-w_C`)MMr}31jYht&_(9d4ZjOjcfTwS5L2-C<6JrsKWjT2cp;AzpJf*;!B6PQL z04sho!)No&AyrRTuX1s#W6tw_={ZkshvE3U&~6dRxy!4#f+o!x#vW{(0fZXijyFd{ z?kjuHYrq`9&!D#t)xmXI1+U!pl4!MIXj1|qw!ky;#|%owO{~i2G)->z2ky6qJkluz&t{==z=n01ptw(8-gUFR9fTY(^W$*u zE2dp^6K=D4yKBupLlt$u)2dVZa+Nx>vyIvMON_c(_eg6SXfV95>a_y^`C(U}>C9E05(sxRmj37tF6@lNqM0q0i&b=5L7&Gd~I^|(G{VJ(~m@_*E# zxkqed4G7L6%E@V3ye&@D4eOO%W(TDM576R;oi{kD18j0T8m4ElEA^Vpj(4Hz7Cp?T zlE#|Kw{GByxPoOP(Ja9oH|bb{#YGneJ?|4k?g<|H4dw6DsDCz=(=m9S&n9 zC;xS0#A>W!uh3N6%#sV?v3p}Faro}*?txrL@yJv_dL)PG6DNSu6Arq1KtHi}P)fIz z&NJ3!v$Sq+-`--QvnC|y>z#WOeP#^(0ivGou-rwPrTxjSzZ_Nnh_#NmG0>}D!)I2f zzK0Opb8g=o+EN=1kO14jGBZ8&i}T-H;h_aDdlM+ z?f3RdVf=xU^hvl@1+2JihH5sAN+;zDUy}f~!}uG(mGj;h*<&l^eu#w-dR7TLrQp;> zoQ)<%VBmv)#$wejo)U*sQD_R?ZkQ4xAYnoLgo$g)n*h+%Us02wq9Zk zDmQs}i@mq1$n?}>OzKnQ8*YKjDhtPNX?aO6bvT@3^;i)dyCL;-6Xi8z;JW*|c?pfN zr3nr@kvP6_FA!y2!ASX`Zb5w0gI2IWfGuKXi+p3=Xm(dDAH#hrXsy< zx)9{^Ya6oJnn%LzhOAO-`6QG8kI~mC~iHxyy(8P4-5|2E=$|N^?A0Xu=VUp ztInPPw;G?-w60BR2VQvgREaAtW5F?UPMjMBK!_^yG1=0|Ka%VLuSLaJ=)4s@|?(%kk& zmqsqRKuWE){Dw`vL`wTe+sA8n&W~g*u%|9PXFh2V9GmBD^#6E_FLGS3{q>(LOgW_0u)>)Lff-3D`+1avFmF^T8M*#ePz3MqwJqak?S61tlaJV$@`_l9-`4*AlW83pz)Np+W0a$=Li+=Wj~3~f3DJYn!%Gn* z=t4Im$;GZ|)lolsK>{D&+7NWs6}A4gaB^x&BHLmrhfmEKi8t4zN(Hgze_r&)HSA}1 z9n6}qk3FVW8neh1Z5V%3FrfIFmAXdi(PB!6tQ@Rw6jOehvli$SzU(4S=sbA%e301}K>1~fVjgY!*zNwf$gqn#H9%35Zg7EhlCEi;dEKjNW`|yiav=frNw}|w4@+9ljAl{h$Zy_^ z{~(h*i8!ZQDoDFwr^m@Dwzu|RuClH}qH^fW{Mdu+N5xKa;+jq3o??Rq7+B3|Q%Suu zA*IRl3$MPc;_uy$zD7MQG}>$O6W0`Ip6;Am&TUi3z6h^@s>z6;u-a7=%fhJ`t{ViV zq0Nx7+mtZ?-e95b_6qy>(sSv*B=Xpx_+Q19OgK6>Gr#8!q|64zfil|9Jv$Jm30Vtm z5cGpiNIA>UaD0@mla11NotIfqsd0~0UCrV%rapz^X5L}hq{hwPvU>Fs%wRX&ii6gL z3TctGHC^_$s(HrPXLM<7o6V(YQdoN2v({#3kNOs>(7flVgIEa;vwJ?Hh(|Q>ZPy=m zXP)~4H~Oe|#jlW{ymJp(`j9ErDIqkG{FxKE2HmMX%9~wReZ^*>P45pJ>XMv1l1#U| zAF4b4(7-f^+r+`{dBMpFJ@5Bt?2o-UYrhQlsPEBz=RRh-rYh%G>Zu_L%^zbQE&_n6 zz4jGJRN8rro{pHH*Qim_Sokwzi$vB`o0*bM^IPiOJ*!EK-^h!#a%tbw?<86_`_juc z?70NjC;`+^+>3%y*h!hfB#^0TzhAx64`HFV(7_ymHK^l6yd>&iy$)>1mANf_5V1nO zDfjvrOl@0C|3Mc}-81Je&5e1MOH@ne)#V~hetPc~MwPSDS9{ zPuR3AwB95e-oJQvi zWMWJ+d1oJzq*9qfHj^_*#Uyrjn@KG_*?p~>eQeRWo@h;ItOzP@9UH0$x(`zmz!iM2 zF2Z)}qzY3iQ_*%q>fZ?i+{!P1YcTKFCUQQRp*C39@-=GVLFVdu_wdtJ!I3VV92{Q* z`p(?~uq%|^AaCBX?*DkA;O#sl{YaSQKHIUd0QlnPrUpOE&#I>%Z6@dXkGX4qAfR}*+3FuC@PNU6!?uO?)IHT@!Z|s;;<5ve6 zy&^+9)`lf|{pyr)+*1pdl_sW|8+%=QO~j@Lw0Aa>KD*rI82~&Pj1r`@7K`w{kOQSv z2>c5m_BsG6eLm1%RAFF~JWBF0+HgF2X* z+{Rub!A$F~yY@T*#AZERB%>D+Wfbt=`5wCh&-cB|%NRTK(Czg5&!^r?TkMo4Rcq(n z831GLrQ0Lq8J4$-4^^BG3C(0Vb>*;ta|}fgdPSh8$e1|WCGRXU(t5k6Mvv55pOpzU zlitHhGJXO+$+jntV7|FbvKQdF@iA%N>@~N|AUBV?y39)L{lct;2PJ0#F%a@{3>X`X z?|h{rXGc5`2G^sny`Ue>>-K<;de}{3)muKpUkM(0UTKXF*EZ>jY)a6Vm(%&(905$H z{Ql8hWK<@TBkeG>9Wy;MM^VW6v@lm2#{2)U_nuKrrCt1}f}j*ZMT#KBiV&(arCUL1 z3PL3GA`l?-4gpaC2c#$hQiDp7-a>B*0!k-zLNOp9y@U`#DEENlOdOf_?_KMDxa;2e zGK=x#oU{Ah&)&c1IXcxEF}?hPSF3k+$Xq)8$W zsib=-4ql}==Dlu}f%L)Xc)pU8KHe9)T}fkePk4V?sPdiZw>iCyZ^xL>x%FRS)sEts zHwEl^KdfxOz1$|l9~!PBm^tk{zD`B^u!Ma}43lqG8J>E3=xXuWd;J(zvP zK;%r=YTekRVze>gaY7r#W69VfA7STdfvt!rl*dhh#G?Sdek@i_wm~^O`mC#1jzDqo zyYpL9k_Tf9?>RDrIq<)bj~VG{SXioC6X0IKfJ9?Ar@hA(3tolxhtcWs4*Nt(5{^`eMN6&(?{ z3>Be*C@M2bt7|PU-<*-#ZqjFYau$^*Vxck`EcroQf`--&Icl>?$yVB3l7IKarYE$s-8QBgmL`ttMq#8Wfw=GBx zop*g%J^C8*(-(rjd%XE~WJAGCQP;mG`#?wP^6l>)UwZpCzBXj1U)EA z3&g#QR$Y4G!T3@0ljL}x@x}E75A__K<>QD2S6i+IFyCnO0h)(yY%P!EXh-Rj3Qv^C zZ{3g86;?_G!L(B2(mrZ^^7p3x+B8Nnd+|(|c>Q2oT6Z8(uv5SmU1-n>H%-ywu&cf0 zuyleE*eFa6J)`oV^mR&2Tx?ONN^jbj>4*2{U-UjZ(|ejKiCwglF=6$+lczX28a}G9@j)*UqNQ;pA54CqKBOV zqbEdjU%aFlKR|Qp=5jMG?!!FKncfKslyYu-|gsp3mdQSu&`cgBHcDlzDuZm%0v0fIijI$z6Es#!}qjJ+YF2q6wLjZM_;*yD6)Z zGvY>MOWe4d?P7(caNN&xUtKD*ZcOQuRg7N_mtzkk*%HKk60N zm+tdN-pzdgg+#5Ys8f2o#G2=Ho&r{?4fA8bF@Wb|u>Go!Hrf;06-F{6fH9jW>_h$4 zu-Zrd#ZGeg%b{n(CQ{UuGa!SEo0I)eH9*TZ07VWw26k{bz_QCA<&GiG1F|Krs6BsE zn!5ut{;oie*8+ylpQjkVrmb=(m$=~TqlbLl50~am<+(V&TX?(eF=+NxBud|oZ(yNw zWj%OOejrB0bJq3S;b2fXCTtov&eLSN)-}F7=GdYRGoc`jwYy`ne}xlc4(Q%FHz+@V zpA+=SOp{PlTM1hNeB+TDB#M3x&DNE3F<8yD?6my`!TJ}vu6O*iG)z`*|ipy^S^l}}=LrL)r-key^&ODLT zVGoDf-7g~sP6H=rioW6$xNlPXh*P%f4)4ngUxva3Hu5|IDr|Y*Ol1vvY9B5~49`%6 zwk)M2cbnT?8FDC6M@uqX_57M;keN60X}3&cb%L0tnDN6>ZdJ}#n4B$sEaOGSoItGw zZPt6d-A(b_SopzY!$@{`z&1W;Zi|ZHTY1d^;zkQ6D)4Mr3j7JN*?Ghe|MIz2IcyD| z|0PtV2+~tdFW#=j6qn2VB2GfD?~xjdUF~`#IK2Rx*YO zndld$ZsVsQAouB)JlwK$>;!#Su4DiKXhY!`;{QL&r;up*f}?&7}VKRUc4%H zZ{NqcM$J2~b_7CMdA}TJM_&wX$5Ogg$K#AgjW0?sS7|HTY zdj_tuPxqNW#p*c3ez^?+_QrN@I`N`xz&$S|C!7iEdKYVyGtxRQTGC|lG6HZdQw^%w zqayt2Rm_(+7Y*)fvw=U*ruYx#_*-0?H-a>m+La^ z+G=J5YP(i$w&;pPJRfr$q*WjlcjmsE65bVoRpd>ANr*?S5*tHg=B{0Xs;CK=Z+ukc zPj6F(72aS~q`^m9jqGNE6kl!pWfZmX92+Zb&tF!pwS*utO)Fr47wil%QE0o>8|~Z4|cS~ldb~fiYWfZhV=v<$+VQecW0AwltO^|fyWzuB}Fp3rVC+xo29 zOCkE~eMx>m&-C_yo`JYGs4n6+CDwL60I>o$l&U?j!Ni&Yv>7n6jxq-CJOft;dSZoO zRt%TAgx*+fEu4uDxevMzsJFvA;K5BUl^pkB+t{xm;E)4mL+}#t;q>5zj&@by*`DOx zkf2jp5A@ilC>oF>7FBAUGZI*<)nfO>%!ms2iA&~)Dz%sPqtCZ^Cjx8V9J%|*24 z-r-J5V@^4bBA;+QRnVm{%gKj~z?{{hR-B*`k(YB&{BR%dXo?1HTx;jtC8I6Ysm<1$ zW7BIbQmZ>lzq$FXG@MgiE-=OVcETt19V)r=k*t%Z%EGJnKysI;zjv3-B&BjN7nTE@ z`vfcmLYTD*n_hbZn{8QhJsc-)+d}TRDvyOXDvr#k-exSLnLOcqvD4QZmO=q@_n?>> z**e?%Ah4I?E%WD>oG&tRRpy2+bg#seVQtMI;4Io?Sffes^~cu+P>u;pSW5TF49)z- zHhv!IHsQ_|ORlqajn~jq7*0tWAK}h-^Ky2Is+UrpzPxCZ#~EcCK___rAWBw3A2QcA za$06&c=O3a^gCUL@?M0Vblx5JT#=8n2{EK-2wm|cG?`z701Z&q9RI{*f=4NvtprHt?3MXlt z)ynu|tUAXcqwknYh~RQ*T&E?o9`zDqATF69i0T0?>XYcgDw}-%n1$SVGhH>YvGrL7 zrO%6KHAg)^ug%tH9kBrdNVGXlMlCQF%6_e|KWICmxCL1=!Z$P<%mx=QkG}(%zv!!q zC)hPKtnW14XR_}aoFOzP<2M)9gI9>6mEN7i$`?KOMRWo9);7I2^QPC#%M4!)s&XsU z8Q_d1h@|yTh%=zvh=zA9=evW@@BW9poKkG<2kMWr|WN-c$&#NjEnRsyh(-fl8R zrMyMd+b`)IRpv(xbgtMfahnk7v2x0dNY`m! zWWA}nvj}=A4gk!HGC7L#Hky-N7ruw#cXO|+0&oe=yqZ3RpYH&tQRV<2y`KTUDGOQuOnG8bw)@f$y#Jr8ZQ$^f@1^=0d%W(6pG!db8XDj$Kj(M@{exp-(w$jp zJE?DSI@w+rS2_!p?=<`Zu7-(56f*Vm`b;8pwGzt5UtUihtvdSjk9~;JPbb9gtY)P> z0|Vp0%Xz5hX-TzH&_b#T)eSS4KN$=Y7XbgMfY@33b78;ZT{rI5pZMp+r|JMe;dY5@ zi|EtM`t5mO+K@8Ery-5lsPYIXR?T=DTt=i#(@1_*96|xWz*Qf%>6+T0T^FMC%~prDi{5-1KLh)6 z20HTL9$Ut%G&6%z>`G#%d&)pGBd~Kb5@0&_Ro~91Xnuxd9r<@)+sD}Vtx4qhPAU$# z9LWZzaOqOVI`p|M?%slh_g4s3n*!QpE&1p1e^mXGlz&i0^1ocZyRujMf@#b82m2)T-!FI)zVBVV zakn>uzwk}+^xcNQU;k0ufhq$#OWf8RXMSlD|ML}pAy|$m?cQa4IpNz+TQL4NkH_xs zE<_J-Yz<2OY~6o7c#k)J1gs5MzTOYvUMJZg{TBm!bLM-1X;<*R0dmD5|Lf^L3-mvA zkyy@u>LRg5`TuWt*VAw4j2~wK{NjTDc^XOl`Y$k&hRy#1<9~ti=T!NlSor@)VEiu_ z{#q>mU0VGY4F3y;|59=P|E@~hwq0l)`^rbXvA?(Zz^5C>6t7;Yg(EPB0uBaTI6W+o zF;m8yA$MF`SMc}~P2K%V?-_KNjVSc$Oc-r%e57HlJ#nLkJ=^ZUv5+vS=+8ORbMBtQ z^HZOdFUo``%ui~j%w!c0dt@YdOZmX%G!Gm)!X^K3-+r=x{^9FEeJF`4sT&JNG5>mX zuYcj^;|e<;)>D&HoyM^DGyied9kuRw{`7x1<;s1QsyVPBpWJb8*M}JGO?KNa%z*(gH8|$&am%4w4aoq78 znldJdNrJ!i`vZ{s@?0uhS$+mS8r;99yM$eua9)U&8^0%58k!vgEL@zio&Fsb4jk&z z*rh39A-w9}tomnZSQzaZAd~l|O8oEX?*AdD5K^b$@N&>DSuOIz)RzX;3=))TYw9wt zf_oL?gY6kuJbYJIkDL!3xiBjYv%ch(`UmC)(T1Z4A!+uFbCzl^X&~cvZKSDk<-GFW z;(h;#QSk~=DLbCo+kWQJb1AAb-0fUs4Q;QE4KKZc)jEAZQW9>`KK_+=dB;OL!WV0Z zwPqrDooMBI&4P&lY<3J=S&!)EJ(aNcxl~CJovq$2s+ew()Wc{InWw)#ZJ+PNcblJ= z7@Q?hjRm#uHld}$uA`e?qE1)&k^C9zIG4c{JCrb5bhQ21AA3FN==mLw7O&CQu08j+ z;U#t-@IC^*DTP1ir~@0AP%`YJkX@DpB_Eb5J9z9@pRu^QtN8O?St=wi@ijZ@w)pu0 zrjWUn&dR#8pU)u8T{Kr-VXz8ITtFO6Q9Cj8{;jC!UJk;lw`+PGBX`HnkWl4EA?r0R zgNZ6&2I5K@1BlWK7g9xL&*i+nP&)-Yo%myn5b zY8J2ExEH!7Dcavj8P^l1CnZJs%S)xnC)#*vv}wUbcCuhWyFMF++NhBt@ECp9p}j(y z#lO%acp0CP`=wNq>(CJvGv71@aXK)=Nk~~*dX_Z>R32h+QotYtCgpgeQ!BgeifQ9bnj!4&j=^u{++|%Opeo&HFM--Iz zj4E*NNB9Fuk|6NI0uo>E63sg8C(1%f)>%Lt3;TT!b903iVP<8bfBgP0ZXe2ve2)gT zp4N1v(I6UV(uc!er--}(o_w>b_dzbn)gQdE0we*M0;7MMoHWY=;mY;ldw+%_ifFsl zguTc;@m~gyK@}c~| z)Acgi$iJ`tc)k1%GeDpoRD#Nr3jc^AmhMQO9l#A+>u~rUZXo)2H(`iWG)$0)K|UOK zoLE1zrR160fF)gr>rpEGZ3jPIpSZ)!0Tkj_ylZ5skuW#RBh75Wbug-ep2lqP! z0VjWv9}ox9-++Gs-jtM_KP|8Y&;Vcyv4TzN#rq{pB(u2Mn|+bQNkJ-Cnfy!5IwgG41*V#>B<;t9 z;EjEDYxA)I9c-@1n%?qO$GBoc?Ms*nxu^wVzqY~?Sn4w#1c>ClKZN~mHzQ_vbH|Zd zgyCbFXHVn@*bvp4ZbV_U|E;l`-7B{p*NC-key+L~x%mvbH4B1olLcRBf98vvnczFb zylre#VlwO~_E`#udm#FL-Zt1&Q0;qnLWD1UH*58QoSPI4?aw-#wX?ntqR zkh*t;+r99_k@TXqo$pQhBseC^^9l28Y5&7G;PW`_!yC!ynrk#s^zYzj#LLz*AJ=?U zk!baI>8xz?ch#3nJsJR2c0OiNBtH=4?O{-|GH{SGsh}xxtmfQ;WbQ^4{kN3!wr9h7 zz8d6Ck^1JYp8e%_31?-D$L5J89$2Gv#NQkmUXB}%h?|$ z!O324qh5*|nQj%sbT!Q%k{HHY*TK(>e=Q4bp&h#!H6c2Qsl%u+4~eV$+r-VBYFG9} zwr#Er+YxLzGw&!?w~@QX9Ip@MV4RSyxFCJJIEjyAtl=5;h#UTcQ7Vh7;}gJz`AH1+ zPm{b4-t}8&xH*!v27Vt#BWlSt=PvwoHJL>b#NqP_>vU;M#}#bdR653FQq!y2&#laY zE{LCelblg|m$N+2ZRRNtO;YfyoOA(lSfu>GP$(ZAx3`&=-{;Q_^G8&@r$QLf4g&X) zr{k6*`Z4njOi}3hqVBcDN_q~6tnK(Cc?igdIPuGR<-Xi5eK=3YLDG`j_tbHVF8Kj5 zbIy~+%jkE~*ivkipU>Lt?6P}a?$W!}#c=wTLmJ#Ki^`OHTM6@(m<9>CXfd=IR;6ZD zquz8pH8PXhRW|=Dh!ffQWbwu3`2ew{*%t)RR<^q&t&Ne!bJ!R{cAIoPR_Wiv@f)o~F?kl;4P(VA? zUR(8x#Rr)qhC+sXg6uFlczy&k4K$**SkK9^1hIYdvCWWP*^+x-*Tasl4jCEu*+WL!1c%EVoWUi8Ve^_=nn?e1Aj#UE z*kC$O6~vLEnJxUgKJf?&RQipdBFuN&UHP6LN2Er7S|IxCB_1V*b{gkSGjqzmv(EF< z1iMYSO9b3#(u$f%r%{+M)Lt9ZS-k+>KIfk_%ve0H+;EP2f$^~sLxIEeSSDzJ3gI)u z@%qfUl(Nvyt;vwZ)N+qUnv<1Ay>^59HH;0<*>+${7fUrU@dlNZZHC=5W~wxt9=H%~ zmh{Q&1a<15_^oQ!D3Hq^zQqewuG`D*Syx%{cPH;oiUy7&m!=1(=I%-aq&Ot(P>PyO^p#a}ZgAPxFX`J*k_d7iqg zGZy=a_DrAIL@(u&7t>Bw7`4gzOd1ezC14raos}`{bn9%hR!f3dfMyaX2NX;vIY&ZuCCj3R%{J6P@5Ib zrzvpF#iq_NuRhC&z`5$W%vIRgcLzRr91Ru@TfI*EX?)?TY{*To-q=%NtF_hAtg`Fz z>T4p}+vc>;%IWrm5!-o#P4_7=`X_`ozP5Bc+S}Nzt~skwMPRFL(C!wkBhEGHP9MQ` zp!}rQ&iVaL^~l90ok@JZ3S@3UVw>Zbe=~G$7{<7Rw8Z%(9w*IvMgWY;*VOq^`jd3k;b`%?(7Cx-zv}mX*M(L zJHRTOgzXN;(;ckK62OiP8I+4`EVZU$JDs=qC{ckDsf&$cZJD%h$0EJAy$SJ{Y?fnE zQ}19k&;~U@2_=|~kDGnb_{1}I?k8E|Guj;&U`vF2wZUWRu};sLQOk z&J(?24$j9ZZBOKe^Ky;5^G2~KDNWr|{64e#Xc#N_)*v4rq)c+-Yf1yJmXZ{qkG&?1 zdluNq*H-7c`cbVdu$rKLUqJ5_M{%FD>Su|CaD>0r_Ud)F zkzN}RB9;GYCsPW~Ll?L%jz4Q7l9TvxPAUh;`{SBD2T%?t5Wg0&Qc=0vlxF4rLQ(iU8E0CX;Q1*-hAMFNzNuXIt1A=xg?TeI{tONC}%^a**np^ym~sf zr_I*=V%%oDXTd4~Vf>DlqIuZqu3GLnTWonK$FcLz*fqUdd7@gWBnFAr-j{V=^JjHM za?2Q zJL8;s01qvGy=}9w*X0eNfDKb{f(*Jq92hY^H1ql5qzdA)r1i_lQ@U+uV9o>rVkl}T zzNo%p`dO{u@sN5@QSiS1r@cmS^?PzZ0%`^$zKe_<_HF$)bGzV z;#>Ie_@#y66I%=G3XPMtvKMW**QXojuB%m=x-dOc3P!PPyKOx`MKKxq(MKfY(wOVG zXK}prd9Q_)YXw&B8@c{`i|^Xl~Uh(QtDt?9Xp&fzT+ zT9M@Lmh@0Wy=HsSygmBP* zC+8Z+LdF5_6Y%MkHL5OQ)s;j|TYpYr`Idoez6TBkl!S^4edeft60BhL^(~;E?PUU6 z?Fa{7)>jGVntDtxr{{;nPo1`@8B#tm-l|isn(z(mqz$c)&%2f8$%V_8b-kANYllzE z576Laj#aH}dw2`F%WW@ZT?UFi*~s{iP|)!$9?C}4^WoStts8po6v&|>R?aHN^=515 z%FHWxgkO-BKUm)me!r(ueZYLA%=VJyNE$|=fa5SH!KH0AxqAH@wibCyCWChZUNKf} zbJ%A}pC^muDT88@pBHI~|2?qM-rKGJ6BhzqNIj25-1qqVoi?*GV#+@8L7;PkoWwo+JB>QlTZKs5T}Q3gJ1k(ejsss8cBC)sW`{Yl4{tc@Bq41NNk+ zl#w&u03H@TbF!*of&i^X*p{zN*mYKJ9+b zll{}WzK?=cI82K+>|7XL-`;#}GcL6kozgclKnATQemiAU(}$XVFteOH)>eJF*~jGp zi(J_m-PKljO}4#Gi|o?qo=fi7~^4K2CaX?D=23PO!uv~1HA82d6BxGIKe|~&YcdLA0e|E6sz_kH0 zK^Qv=uuN&{l|HHEnoSi|ZH34kS(UjGhlGEr4COxzC4Nec%A{5k)Mp%KEk-wkLm>$H zfzq6ja}|8qRgs+FjjfK{^YA~!LR#L`bt-`$fW2Ls!ZB5Z%Hq|`sw@^o;wplJ9=>V{Ix4->fO#8OMswN*Flll)#5a?}WNj zB{4b&1Y_2J68-%jxC7NC;G5-X#(iS?@GzZWhtt4XiZ}H_TVxAXHRer7lRm zqvIV%RP!9K3vBBaeqL&<31%t2rJ&_g^FhZSS(qaap$PwJ39#FS^4-7N%su=?tmDa# zhTe{^*MfF@{J4B6(9vl;l40Bj@=Hhv^v$jci63J^j0EYxCmKdfSms)oM(AZ6U<$&S9BW&H| zMxIxjm6;8DDPr#v7(aNFQ2Xn}`VR39f&^w~HdBq6~ z1toQHz9-zn7lYSk+vm6!_}nu~tEQM?QP;a}v(bzMSpVd=lKeqVId6-nL029$=m{(1)r5CS z6sjc6JM=T3(E?SM2b~r~#?3kM8YVE+!yVX!NI@rNS*N-YP|??ojp}*kkYQKL`z#{_ z6IlP^fIZCr|QiG*Wu zOF_Oor0}I9siMC7$kuKiT=!Ja{i(B;yW81Ij6eS*r^;l3Iy83PQ#=l6Sp*y>YYK%K z3r(Y3XEl!ME9pF_T6` zYMBV+-Ucd>6#vj_qo|7VSrLkK4j+#juY_Fg)wzUEjW$%d8mx7wsF}{CgXxq^DuBs? zHWxR=r23Z>w=U`=_+}S;Eb#VNP|MDe8R+arJ}HKeuV%_-onNiQa~=^7JXNxxn1M*v z{5pEt+6c{K(g+Gmp4sUryR|X8PN?**Yge+HTgH(+RMK+t=MlaTrRAO>8|aI4G^kc` z>-W`YQhD(~CRE@LOnkCY0Dt`xc&aUgZZ7#IH=M8lRHCv`g`7KzZJcFGTI|kPpl9B6 zu&FEPltPe!W39WM`(-UhG%VkoT2Ee(6gpXgO{(CHTOKL)mmBFXxM&1Po~7_qrfaJo z!KmP6*dyy*^W1hy@}e)&xEKA5CW>uJp!j6X{`ps64+E@l#rU_mTB3eG*0!D>FTAN!#d<;q!6ps3|MYdoFWm9}j7- z=>~ihn!U8w3{wLfaD9{#Wbn-IxS4jYg{He$F~k=cU9L=PK=AQov~6nSIquqZSt4=< zKjPh4qK=k@%YtlQk=f^LZx~#I%)z)6JZTSYep?}L%*g02n_LZG4yYWvZBDpLo0J^( z1&Hnjb<{TQ<)h{v3j*uo*DzMqo=NxFDMf%xM%{SW!GTan@87n$GQ3~Lv*}jslWp1Y z_bm5L>U79bQ~_IgLF;|S;#nm{y)LnlVC@W7F8;&kv$EGx+D2IBJxuNE`qI@xqzoaK z7F0az>?|JK!2)IQ>5A=Tbb2gaQjYjhrsfX?YmIDXMUch?Qi=V!G%^P}I5$8`E(yXm#&#U>y}*uG(yKD+8W92O>%h zFV|$%R&x}n^oiOOYQvMb`U!GzY}w^+9g^R63BaZZe&MT!VnY}DU4X9>cQ>_GEYI7m zgIxG>9Y4G`HbMvfXnlIJ36LV5IC80qrMQ0h9@ecJl z-)6L-Vj1MFaYxSAA3?>H40LU(@y%pFbJkzSfpY?2iGgOcN#ief*2KkDdM799?6e{F z)~V33nqm8q@YN04q{g z>f_oOH5XlZDE;#N5o%FKV7}S!r1DE#lYb~*yfc%J;Ut9~9N586WMQg~kz1Yu2J1}g z`6>~lW&8IRy+883sQ+Mii69gc#(ERz8$c82-h z6r}fA>>vmHiMMIr`2pn@o6Pb@!|s=f*&+}@6OCBgj ze!$S&IH#d|S%qluE&!*qqWL^YjU(?!Rq=H&w&u~KmRN66vp?|Br&p3jV|F<0gTW7< zvz{h>;SVzo-fgt>JY7f@CLKX>#W_sH3C$#!-`a)y12ilq` zuRMG&M68i+Wyk+r_~D%|wcud}Z(vNp(Axa+kZ8*LCNpKK$tt7X`jc^YNd@pj z`Q=~X1o>#!jzATY6N*1L22u&bAzeoB zZK;Ly($`I^@hXe3n5%COAsb+lZQj8V9jxO-AvzKcewfm~V5Lrz(aVcO4vH&{8h%0&rdSAMJg;2lU^KPC zj?8`l0L6bN^Jiy2mlG7>61qnQJ%{`}CP6Kw#>PfB3^jJ^sEQ4kqv-Gt)T!P>1`x_&;ZxQ@3$36Z~`0qp|CV$`Duzt{Rc@G|cXo%!em)b7d-nQWhdtCj?K>q&20=gU9Be(Xy z0=^tW@}$3iLYgoDT5-GD%NRi?k=pzJc-w!f_#eU{x%8hZ{_~1|j|C6^UmKvPeUaJO z*}3CLe#p9?ko*53h}iXOuiX0)Su%6pk6{sq=H}*JzcsmMVMUWScvKFZ zU)E)=prCN07nTR}v}V4#nz{^`P9!SAyT&YZO4A)xvO;JqNO>^zuH(uv`Rj z#K*_?L#YwT#IggZKB}K2sGiSWT19xqcr+vdnlBIP9dkhV%cRydMhdx(2}Jsi8Qx(3LCyp6^J-;M@nt)N?oSxS|z3J3IU9$}E0lLt9awf{v%Bh0^3w zfm_o0Y8RJPx8u1&eva-smFSEC4EpcBW*LBYtX(|FDF;%7iegkF-4-+)PhG?z(gFXT9uU0_?S*sm>vt z#Yo4+pU*V%k=a!B#;0o*Q__M_wUcZO7LO=?1j zj&tNA3xfH!FS1BKJ~bDz^iEb#Unj}|-KZHa1I@3AuM5*o&z5bQ0pL4UWj#-_#q_k* zv;kMdvRt1D#PPf;no1d~=@T}|pV``roxP0p{rdxv0y<0yo;J6b6s>GSL2r`{AsYr9 zib{w&L+v(dXauHU1!-IknIvbsyP$=mPpa!isUP8IcfZe1(Xrf(LM3tA%BJBJyMFhL z@(3~-gva?NqhulNMx$|1(l{pnD5IiML8ksWeww)C_4$2}Tc;^dx6y7)6%5VYy)k8Dilm&87Vq_>en-StK@=wdYyy_VtAJ(Dai_Lt{kAn zW6mc7CiVz&d+4*vAd&l{W?Pj>HlP2;{Iif8o6f?b)sk3K%%_>qW&c=BXKqhCW*dO`IR1cTIl7BPeq6O2Oh z{H8}6ejyuY(b2kqh>%jeoX>*gMNImsSMha6Wk0~=-M3k|&>hh_*3ELU34Bw@+5Ivu zJgQ)QzPm#mF4-nalkt{uCZkDvY+jB~SyzVR>E#cL2zl4?c;>MU6f$w>8B2V&p(&`eELByr0v zZxz?r)4GS=_mZ;EakAtu_p2bzbJ&GzRI4kvO(;yJ zN)FR@1>%6sTy)5MXJ#DAEMjt~yI&#Uy3&V2z9_AVcYEyo+^fj+Eu%>)0Yg(;?l6GQfvCvXH-&|v!7SyH2^Hj?ctgY${h$5o%E;|I&J<)a{IMoQCESJ$J z-)m*O4X}{$)mMe&7BZVjIvLljc-$kGp>=Op2BlwWxfizWMI7+u*bNUYFfJ?vrJv|tJl-}cGv1hf zbvPy6qf)ik$`84cRCo|&T*Bw~xlH{yU+CkAtEL2an(W96k(?&Eg6NOL0$GpL=KQAd zT!@Eini;=Oxz0WB%;ZX?-*n}7$1l{?8|y7xeNa1J;1I?a52pCE%%;wgDWeC{Z6h}( znA^v;-2+?3(4S6dfXNrgF00ZY+&Ky681>SUBCGM6RX5{a zI$=&5G_K>sRCbG=M|df~|tsAbvZw&~c6 zg{-QCR$^JP7J6%%5~$PSbF@1dw`VqA89(KtPfjkXd)re{W&D^F76Q zAEbN2KE#8Ns zTaB-00)pR~UWC}Ybi;yr*9Djpw9EVOS=s-dJ4iEPyE++TM}CzWrD=ZA7qIiE%;V>k zhL|`9m~Nw;wPdrkKJoi#ZE3qJjQ7hA+#AkYEdY8WD2{0R=g8T2bb*?P)SG}Vv@@F| zdA8GLi~D4))cfWOyp)D${Juhlh&`wNhYgZkV$(`wSx?_q%pdN}U)FAs*JizmNstze z^kGua){8>)P8Yiw=(nOLCm(NSYH($7n?_RJqYYtfs{6n+gLT-_wg%IdYxXd=l|8m{ z=M~UDb_TS5;rEPC=p`9rUePN`Hbt(?9C3F=zHQ|(fyf~2g&w@7Kv9kW^Fmrxk?iCq zfV)dAd~6&Mnqi|MEf|R{Ur*1_lxr6@h0`~sLkWC)Y(Cgi0f}etScxI4tk+A?njaLL`RmijuAx!Sti zSu5Mq3R3^qkQWl-E_50WEMW0s+;YYB=&y|Ix0}~rh~jGhx;-hX^mye0o&RUnhtGfh z_3C`)-0<4_x6ZYj02_jH*iU~tf9haK{?^FIneV#3i)w8Sh+LR7w>h(QpH^3^U2yHy z%zInu+X9FAhMVHVt3ua&&RN}@VOSS7G5NK1&osHKzkgQF(D|>!w<0X| zV^y47#_m0T9qe99dAt@?c`fIt*%Kyew0cKa_KK~y!?&Di%G~=nNi=a=m-HO0A&Xhf z1Irg+oA%T`?}MA~HEv2;z3))QO5e2?BJS1YUhn$*J#<}ZeS9u^l>Gu=;j-o%SNdN0 z&D+XiV`KN`zgYf$>(}s$k$1yO(g?>C#) zSFg&K$k_er_b==9)e39ZhhF;BShDo#=`5YZZQmZ;WC-&;E-R;K+w%Jw=^4!DWCe)Y@d zWo!GTM?A0Pj9%Y+xB2_J`I71KS6_R+H6tztr2-e6=QTYoeyY`xfB*guQD*}p*Z6$D px+hHH;;xo6*Oul!6#Ogp-`*u`iM8lVHw^|L@O1TaS?83{1OP^B3C;ij literal 0 HcmV?d00001 diff --git a/docs/user/security/index.asciidoc b/docs/user/security/index.asciidoc index 6a5c4a83aa3a..71c5bd268a67 100644 --- a/docs/user/security/index.asciidoc +++ b/docs/user/security/index.asciidoc @@ -47,4 +47,3 @@ include::authorization/kibana-privileges.asciidoc[] include::api-keys/index.asciidoc[] include::encryption-keys/index.asciidoc[] include::role-mappings/index.asciidoc[] -include::rbac_tutorial.asciidoc[] diff --git a/docs/user/security/rbac_tutorial.asciidoc b/docs/user/security/rbac_tutorial.asciidoc deleted file mode 100644 index 6324539c3c10..000000000000 --- a/docs/user/security/rbac_tutorial.asciidoc +++ /dev/null @@ -1,105 +0,0 @@ -[[space-rbac-tutorial]] -=== Tutorial: Use role-based access control to customize Kibana spaces - -With role-based access control (RBAC), you can provide users access to data, tools, -and Kibana spaces. In this tutorial, you will learn how to configure roles -that provide the right users with the right access to the data, tools, and -Kibana spaces. - -[float] -==== Scenario - -Our user is a web developer working on a bank's -online mortgage service. The web developer has these -three requirements: - -* Have access to the data for that service -* Build visualizations and dashboards -* Monitor the performance of the system - -You'll provide the web developer with the access and privileges to get the job done. - -[float] -==== Prerequisites - -To complete this tutorial, you'll need the following: - -* **Administrative privileges**: You must have a role that grants privileges to create a space, role, and user. This is any role which grants the `manage_security` cluster privilege. By default, the `superuser` role provides this access. See the {ref}/built-in-roles.html[built-in] roles. -* **A space**: In this tutorial, use `Dev Mortgage` as the space -name. See <> for -details on creating a space. -* **Data**: You can use <> or -live data. In the following steps, Filebeat and Metricbeat data are used. - -[float] -==== Steps - -With the requirements in mind, here are the steps that you will work -through in this tutorial: - -* Create a role named `mortgage-developer` -* Give the role permission to access the data in the relevant indices -* Give the role permission to create visualizations and dashboards -* Create the web developer's user account with the proper roles - -[float] -==== Create a role - -Open the main menu, then click *Stack Management > Roles* -for an overview of your roles. This view provides actions -for you to create, edit, and delete roles. - -[role="screenshot"] -image::security/images/role-management.png["Role management"] - - -You can create as many roles as you like. Click *Create role* and -provide a name. Use `dev-mortgage` because this role is for a developer -working on the bank's mortgage application. - - -[float] -==== Give the role permission to access the data - -Access to data in indices is an index-level privilege, so in -*Index privileges*, add lines for the indices that contain the -data for this role. Two privileges are required: `read` and -`view_index_metadata`. All privileges are detailed in the -https://www.elastic.co/guide/en/elasticsearch/reference/current/security-privileges.html[security privileges] documentation. - -In the screenshots, Filebeat and Metricbeat data is used, but you -should use the index patterns for your indices. - -[role="screenshot"] -image::security/images/role-index-privilege.png["Index privilege"] - -[float] -==== Give the role permissions to {kib} apps - -To enable users to create dashboards, visualizations, and saved searches, add {kib} privileges to the `dev-mortgage` role. - -. On the *{kib} privileges* window, select *Dev Mortgage* from the *Space* dropdown. - -. Click **Add space privilege**. - -. For *Dashboard*, *Visualize Library*, and *Discover*, click *All*. -+ -It is common to create saved searches in *Discover* while creating visualizations. -+ -[role="screenshot"] -image::security/images/role-space-visualization.png["Associate space"] - -[float] -==== Create the developer user account with the proper roles - -. Open the main menu, then click *Stack Management > Users*. -. Click **Create user**, then give the user the `dev-mortgage` -and `monitoring-user` roles, which are required for *Stack Monitoring* users. - -[role="screenshot"] -image::security/images/role-new-user.png["Developer user"] - -Finally, have the developer log in and access the Dev Mortgage space -and create a new visualization. - -NOTE: If the user is assigned to only one space, they will automatically enter that space on login. diff --git a/docs/user/security/tutorials/how-to-secure-access-to-kibana.asciidoc b/docs/user/security/tutorials/how-to-secure-access-to-kibana.asciidoc new file mode 100644 index 000000000000..5fa0d084b76d --- /dev/null +++ b/docs/user/security/tutorials/how-to-secure-access-to-kibana.asciidoc @@ -0,0 +1,136 @@ +[[tutorial-secure-access-to-kibana]] +== Securing access to {kib} + + +{kib} is home to an ever-growing suite of powerful features, which help you get the most out of your data. Your data is important, and should be protected. {kib} allows you to secure access to your data and control how users are able to interact with your data. + +For example, some users might only need to view your stunning dashboards, while others might need to manage your fleet of Elastic agents and run machine learning jobs to detect anomalous behavior in your network. + +This guide introduces you to three of {kib}'s security features: spaces, roles, and users. By the end of this tutorial, you will learn how to manage these entities, and how you can leverage them to secure access to both {kib} and your data. + +[float] +=== Spaces + +Do you have multiple teams using {kib}? Do you want a “playground” to experiment with new visualizations or alerts? If so, then <> can help. + +Think of a space as another instance of {kib}. A space allows you to organize your <>, <>, <>, and much more into their own categories. For example, you might have a Marketing space for your marketeers to track the results of their campaigns, and an Engineering space for your developers to {apm-get-started-ref}/overview.html[monitor application performance]. + +The assets you create in one space are isolated from other spaces, so when you enter a space, you only see the assets that belong to that space. + +Refer to the <> for more information. + +[float] +=== Roles + +Once your spaces are setup, the next step to securing access is to provision your roles. Roles are a collection of privileges that allow you to perform actions in {kib} and Elasticsearch. Roles are assigned to users, and to {ref}/built-in-users.html[system accounts] that power the Elastic Stack. + +You can create your own roles, or use any of the {ref}/built-in-roles.html[built-in roles]. Some built-in roles are intended for Elastic Stack components and should not be assigned to end users directly. + +One of the more useful built-in roles is `kibana_admin`. Assigning this role to your users will grant access to all of {kib}'s features. This includes the ability to manage Spaces. + +The built-in roles are great for getting started with the Elastic Stack, and for system administrators who do not need more restrictive access. With so many features, it’s not possible to ship more granular roles to accommodate everyone’s needs. This is where custom roles come in. + +As an administrator, you have the ability to create your own roles to describe exactly the kind of access your users should have. For example, you might create a `marketing_user` role, which you then assign to all users in your marketing department. This role would grant access to all of the necessary data and features for this team to be successful, without granting them access they don’t require. + + +[float] +=== Users + +Once your roles are setup, the next step to securing access is to create your users, and assign them one or more roles. {kib}'s user management allows you to provision accounts for each of your users. + +TIP: Want Single Sign-on? {kib} supports a wide range of SSO implementations, including SAML, OIDC, LDAP/AD, and Kerberos. <>. + + +[float] +[[tutorial-secure-kibana-dashboards-only]] +=== Example: Create a user with access only to dashboards + +Let’s work through an example together. Consider a marketing analyst who wants to monitor the effectiveness of their campaigns. They should be able to see their team’s dashboards, but not be allowed to view or manage anything else in {kib}. All of the team’s dashboards are located in the Marketing space. + +[float] +==== Create a space + +Create a Marketing space for your marketing analysts to use. + +. Open the main menu, and select **Stack Management**. +. Under **{kib}**, select **Spaces**. +. Click **Create a space**. +. Give this space a unique name. For example: `Marketing`. +. Click **Create space**. ++ +If you’ve followed the example above, you should end up with a space that looks like this: ++ +[role="screenshot"] +image::user/security/images/tutorial-secure-access-example-1-space.png[Create space UI] + + +[float] +==== Create a role + +To effectively use dashboards, create a role that describes the privileges you want to grant. +In this example, a marketing analyst will need: + +* Access to **read** the data that powers the dashboards +* Access to **read** the dashboards within the `Marketing` space + +To create the role: + +. Open the main menu, and select **Stack Management**. +. Under **Security**, select **Roles**. +. Click **Create role**. +. Give this role a unique name. For example: `marketing_dashboards_role`. +. For this example, you want to store all marketing data in the `acme-marketing-*` set of indices. To grant this access, locate the **Index privileges** section and enter: +.. `acme-marketing-*` in the **Indices** field. +.. `read` and `view_index_metadata` in the **Privileges** field. ++ +TIP: You can add multiple patterns of indices, and grant different access levels to each. Click **Add index privilege** to grant additional access. +. To grant access to dashboards in the `Marketing` space, locate the {kib} section, and click **Add {kib} privilege**: +.. From the **Spaces** dropdown, select the `Marketing` space. +.. Expand the **Analytics** section, and select the **Read** privilege for **Dashboard**. +.. Click **Add Kibana privilege**. +. Click **Create role**. ++ +If you’ve followed the example above, you should end up with a role that looks like this: ++ +[role="screenshot"] +image::user/security/images/tutorial-secure-access-example-1-role.png[Create role UI] + + +[float] +==== Create a user + +Now that you created a role, create a user account. + +. Navigate to *Stack Management*, and under *Security*, select *Users*. +. Click *Create user*. +. Give this user a descriptive username, and choose a secure password. +. Assign the *marketing_dashboards_role* that you previously created to this new user. +. Click *Create user*. + +[role="screenshot"] +image::user/security/images/tutorial-secure-access-example-1-user.png[Create user UI] + +[float] +==== Verify + +Verify that the user and role are working correctly. + +. Logout of {kib} if you are already logged in. +. In the login screen, enter the username and password for the account you created. ++ +You’re taken into the `Marketing` space, and the main navigation shows only the *Dashboard* application. ++ +[role="screenshot"] +image::user/security/images/tutorial-secure-access-example-1-test.png[Verifying access to dashboards] + + +[float] +=== What's next? + +This guide is an introduction to {kib}'s security features. Check out these additional resources to learn more about authenticating and authorizing your users. + +* View the <> to learn more about single-sign on and other login features. + +* View the <> to learn more about authorizing access to {kib}'s features. + +Still have questions? Ask on our https://discuss.elastic.co/c/kibana[Kibana discuss forum] and a fellow community member or Elastic engineer will help out. diff --git a/docs/user/setup.asciidoc b/docs/user/setup.asciidoc index b4cc564af35a..5955bee41938 100644 --- a/docs/user/setup.asciidoc +++ b/docs/user/setup.asciidoc @@ -54,6 +54,8 @@ include::{kib-repo-dir}/setup/start-stop.asciidoc[] include::{kib-repo-dir}/setup/access.asciidoc[] +include::security/tutorials/how-to-secure-access-to-kibana.asciidoc[] + include::{kib-repo-dir}/setup/connect-to-elasticsearch.asciidoc[] include::{kib-repo-dir}/setup/upgrade.asciidoc[] From 452d8c4a8579e78aa8d3f43a8a97613f49a115c5 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 8 Apr 2021 13:23:05 -0500 Subject: [PATCH 38/49] skip flaky test blocking snapshot promotion. #96515 --- .../security_solution_endpoint_api_int/apis/artifacts/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts b/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts index e1edeb780869..14e08992de9b 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/artifacts/index.ts @@ -19,7 +19,8 @@ export default function (providerContext: FtrProviderContext) { const supertestWithoutAuth = getSupertestWithoutAuth(providerContext); let agentAccessAPIKey: string; - describe('artifact download', () => { + // flaky https://github.com/elastic/kibana/issues/96515 + describe.skip('artifact download', () => { const esArchiverSnapshots = [ 'endpoint/artifacts/fleet_artifacts', 'endpoint/artifacts/api_feature', From fc9e79933075d7705e662679cbfa0c861564d367 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 8 Apr 2021 13:36:45 -0500 Subject: [PATCH 39/49] skip a11y spaces tests. #77933, #96625 --- x-pack/test/accessibility/apps/spaces.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/x-pack/test/accessibility/apps/spaces.ts b/x-pack/test/accessibility/apps/spaces.ts index dc0dfad2debf..a2f0e835c0b3 100644 --- a/x-pack/test/accessibility/apps/spaces.ts +++ b/x-pack/test/accessibility/apps/spaces.ts @@ -18,13 +18,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const toasts = getService('toasts'); - describe('Kibana spaces page meets a11y validations', () => { + // flaky + // https://github.com/elastic/kibana/issues/77933 + // https://github.com/elastic/kibana/issues/96625 + describe.skip('Kibana spaces page meets a11y validations', () => { before(async () => { await esArchiver.load('empty_kibana'); await PageObjects.common.navigateToApp('home'); }); - // flaky https://github.com/elastic/kibana/issues/77933 it.skip('a11y test for manage spaces menu from top nav on Kibana home', async () => { await PageObjects.spaceSelector.openSpacesNav(); await retry.waitFor( @@ -34,7 +36,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await a11y.testAppSnapshot(); }); - // flaky it.skip('a11y test for manage spaces page', async () => { await PageObjects.spaceSelector.clickManageSpaces(); await PageObjects.header.waitUntilLoadingHasFinished(); From e88c23ffedf6f8aa662c7305329f7fdbaa9ad140 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 8 Apr 2021 13:50:56 -0600 Subject: [PATCH 40/49] [7.x] [file upload] document file upload privileges and provide actionable UI when failures occur (#95883) (#96252) * [file upload] document file upload privileges and provide actionable UI when failures occur (#95883) * [file upload] document file upload privileges and provide actionable UI when failures occur * doc link * call hasImportPermission * docs tweeks * tslint * Update docs/maps/import-geospatial-data.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/maps/import-geospatial-data.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/maps/import-geospatial-data.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/maps/import-geospatial-data.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * review feedback * fix bullet list format * clean-up i18n ids * Update docs/maps/import-geospatial-data.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * documenation review feedback * add period to last privilege bullet item Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> * Update docs/maps/import-geospatial-data.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- docs/maps/import-geospatial-data.asciidoc | 24 ++++ .../public/doc_links/doc_links_service.ts | 1 + x-pack/plugins/file_upload/common/types.ts | 5 +- .../components/import_complete_view.tsx | 133 +++++++++++++----- .../components/json_upload_and_parse.tsx | 26 ++++ .../file_upload/public/kibana_services.ts | 1 + .../translations/translations/ja-JP.json | 4 - .../translations/translations/zh-CN.json | 4 - 8 files changed, 154 insertions(+), 44 deletions(-) diff --git a/docs/maps/import-geospatial-data.asciidoc b/docs/maps/import-geospatial-data.asciidoc index fb4250368086..7ffee6410bb6 100644 --- a/docs/maps/import-geospatial-data.asciidoc +++ b/docs/maps/import-geospatial-data.asciidoc @@ -6,6 +6,30 @@ To import geospatical data into the Elastic Stack, the data must be indexed as { Geospatial data comes in many formats. Choose an import tool based on the format of your geospatial data. +[discrete] +[[import-geospatial-privileges]] +=== Security privileges + +The {stack-security-features} provide roles and privileges that control which users can upload files. +You can manage your roles, privileges, and +spaces in **{stack-manage-app}** in {kib}. For more information, see +{ref}/security-privileges.html[Security privileges], +<>, and <>. + +To upload GeoJSON files in {kib} with *Maps*, you must have: + +* The `all` {kib} privilege for *Maps*. +* The `all` {kib} privilege for *Index Pattern Management*. +* The `create` and `create_index` index privileges for destination indices. +* To use the index in *Maps*, you must also have the `read` and `view_index_metadata` index privileges for destination indices. + +To upload CSV files in {kib} with the *{file-data-viz}*, you must have privileges to upload GeoJSON files and: + +* The `manage_pipeline` cluster privilege. +* The `read` {kib} privilege for *Machine Learning*. +* The `machine_learning_admin` or `machine_learning_user` role. + + [discrete] === Upload CSV with latitude and longitude columns diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index e81d03283383..b6c9177b794f 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -217,6 +217,7 @@ export class DocLinksService { }, maps: { guide: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/maps.html`, + importGeospatialPrivileges: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/import-geospatial-data.html#import-geospatial-privileges`, }, monitoring: { alertsKibana: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/kibana-alerts.html`, diff --git a/x-pack/plugins/file_upload/common/types.ts b/x-pack/plugins/file_upload/common/types.ts index 0fc59e2b525a..11cf4ac3615b 100644 --- a/x-pack/plugins/file_upload/common/types.ts +++ b/x-pack/plugins/file_upload/common/types.ts @@ -5,6 +5,7 @@ * 2.0. */ +import type { estypes } from '@elastic/elasticsearch'; import { ES_FIELD_TYPES } from '../../../../src/plugins/data/common'; export interface HasImportPermission { @@ -83,7 +84,9 @@ export interface ImportResponse { pipelineId?: string; docCount: number; failures: ImportFailure[]; - error?: any; + error?: { + error: estypes.ErrorCause; + }; ingestError?: boolean; } diff --git a/x-pack/plugins/file_upload/public/components/import_complete_view.tsx b/x-pack/plugins/file_upload/public/components/import_complete_view.tsx index 29aed0cd52f7..a3bc2ed082b1 100644 --- a/x-pack/plugins/file_upload/public/components/import_complete_view.tsx +++ b/x-pack/plugins/file_upload/public/components/import_complete_view.tsx @@ -7,19 +7,20 @@ import React, { Component, Fragment } from 'react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { EuiButtonIcon, EuiCallOut, EuiCopy, EuiFlexGroup, EuiFlexItem, + EuiLink, EuiSpacer, EuiText, EuiTitle, } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; import { CodeEditor, KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; -import { getHttp, getUiSettings } from '../kibana_services'; +import { getDocLinks, getHttp, getUiSettings } from '../kibana_services'; import { ImportResults } from '../importer'; const services = { @@ -27,8 +28,10 @@ const services = { }; interface Props { + failedPermissionCheck: boolean; importResults?: ImportResults; indexPatternResp?: object; + indexName: string; } export class ImportCompleteView extends Component { @@ -57,9 +60,12 @@ export class ImportCompleteView extends Component { iconType="copy" color="text" data-test-subj={copyButtonDataTestSubj} - aria-label={i18n.translate('xpack.fileUpload.copyButtonAriaLabel', { - defaultMessage: 'Copy to clipboard', - })} + aria-label={i18n.translate( + 'xpack.fileUpload.importComplete.copyButtonAriaLabel', + { + defaultMessage: 'Copy to clipboard', + } + )} /> )} @@ -90,21 +96,65 @@ export class ImportCompleteView extends Component { } _getStatusMsg() { + if (this.props.failedPermissionCheck) { + return ( + +

    + {i18n.translate('xpack.fileUpload.importComplete.permissionFailureMsg', { + defaultMessage: + 'You do not have permission to create or import data into index "{indexName}".', + values: { indexName: this.props.indexName }, + })} +

    + + {i18n.translate('xpack.fileUpload.importComplete.permission.docLink', { + defaultMessage: 'View file import permissions', + })} + + + ); + } + if (!this.props.importResults || !this.props.importResults.success) { - return i18n.translate('xpack.fileUpload.uploadFailureMsg', { - defaultMessage: 'File upload failed.', - }); + const errorMsg = + this.props.importResults && this.props.importResults.error + ? i18n.translate('xpack.fileUpload.importComplete.uploadFailureMsgErrorBlock', { + defaultMessage: 'Error: {reason}', + values: { reason: this.props.importResults.error.error.reason }, + }) + : ''; + return ( + +

    {errorMsg}

    +
    + ); } - const successMsg = i18n.translate('xpack.fileUpload.uploadSuccessMsg', { - defaultMessage: 'File upload complete: indexed {numFeatures} features.', + const successMsg = i18n.translate('xpack.fileUpload.importComplete.uploadSuccessMsg', { + defaultMessage: 'Indexed {numFeatures} features.', values: { numFeatures: this.props.importResults.docCount, }, }); const failedFeaturesMsg = this.props.importResults.failures?.length - ? i18n.translate('xpack.fileUpload.failedFeaturesMsg', { + ? i18n.translate('xpack.fileUpload.importComplete.failedFeaturesMsg', { defaultMessage: 'Unable to index {numFailures} features.', values: { numFailures: this.props.importResults.failures.length, @@ -112,47 +162,60 @@ export class ImportCompleteView extends Component { }) : ''; - return `${successMsg} ${failedFeaturesMsg}`; + return ( + +

    {`${successMsg} ${failedFeaturesMsg}`}

    +
    + ); + } + + _renderIndexManagementMsg() { + return this.props.importResults && this.props.importResults.success ? ( + +

    + + + + +

    + + ) : null; } render() { return ( - -

    {this._getStatusMsg()}

    -
    + {this._getStatusMsg()} + {this._renderCodeEditor( this.props.importResults, - i18n.translate('xpack.fileUpload.jsonImport.indexingResponse', { + i18n.translate('xpack.fileUpload.importComplete.indexingResponse', { defaultMessage: 'Import response', }), 'indexRespCopyButton' )} {this._renderCodeEditor( this.props.indexPatternResp, - i18n.translate('xpack.fileUpload.jsonImport.indexPatternResponse', { + i18n.translate('xpack.fileUpload.importComplete.indexPatternResponse', { defaultMessage: 'Index pattern response', }), 'indexPatternRespCopyButton' )} - -
    - - - - -
    -
    + {this._renderIndexManagementMsg()}
    ); } diff --git a/x-pack/plugins/file_upload/public/components/json_upload_and_parse.tsx b/x-pack/plugins/file_upload/public/components/json_upload_and_parse.tsx index 371d68443bc2..d73c6e9c5fb3 100644 --- a/x-pack/plugins/file_upload/public/components/json_upload_and_parse.tsx +++ b/x-pack/plugins/file_upload/public/components/json_upload_and_parse.tsx @@ -16,6 +16,7 @@ import { FileUploadComponentProps } from '../lazy_load_bundle'; import { ImportResults } from '../importer'; import { GeoJsonImporter } from '../importer/geojson_importer'; import { Settings } from '../../common'; +import { hasImportPermission } from '../api'; enum PHASE { CONFIGURE = 'CONFIGURE', @@ -31,6 +32,7 @@ function getWritingToIndexMsg(progress: number) { } interface State { + failedPermissionCheck: boolean; geoFieldType: ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE; importStatus: string; importResults?: ImportResults; @@ -45,6 +47,7 @@ export class JsonUploadAndParse extends Component ); } diff --git a/x-pack/plugins/file_upload/public/kibana_services.ts b/x-pack/plugins/file_upload/public/kibana_services.ts index a604136ca34e..dfe2785e7a2b 100644 --- a/x-pack/plugins/file_upload/public/kibana_services.ts +++ b/x-pack/plugins/file_upload/public/kibana_services.ts @@ -15,6 +15,7 @@ export function setStartServices(core: CoreStart, plugins: FileUploadStartDepend pluginsStart = plugins; } +export const getDocLinks = () => coreStart.docLinks; export const getIndexPatternService = () => pluginsStart.data.indexPatterns; export const getHttp = () => coreStart.http; export const getSavedObjectsClient = () => coreStart.savedObjects.client; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e42b87f38847..a330589907aa 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -8155,10 +8155,6 @@ "xpack.fileUpload.indexSettings.indexNameAlreadyExistsErrorMessage": "インデックス名またはパターンはすでに存在します。", "xpack.fileUpload.indexSettings.indexNameContainsIllegalCharactersErrorMessage": "インデックス名に許可されていない文字が含まれています。", "xpack.fileUpload.indexSettings.indexNameGuidelines": "インデックス名ガイドライン", - "xpack.fileUpload.jsonImport.indexingResponse": "インデックス応答", - "xpack.fileUpload.jsonImport.indexMgmtLink": "インデックス管理", - "xpack.fileUpload.jsonImport.indexModsMsg": "次を使用すると、その他のインデックス修正を行うことができます。\n", - "xpack.fileUpload.jsonImport.indexPatternResponse": "インデックスパターン応答", "xpack.fileUpload.jsonUploadAndParse.dataIndexingError": "データインデックスエラー", "xpack.fileUpload.jsonUploadAndParse.indexPatternError": "インデックスパターンエラー", "xpack.fleet.agentBulkActions.clearSelection": "選択した項目をクリア", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 623e127bd84b..b7daf5135555 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -8227,10 +8227,6 @@ "xpack.fileUpload.indexSettings.indexNameAlreadyExistsErrorMessage": "索引名称或模式已存在。", "xpack.fileUpload.indexSettings.indexNameContainsIllegalCharactersErrorMessage": "索引名称包含非法字符。", "xpack.fileUpload.indexSettings.indexNameGuidelines": "索引名称指引", - "xpack.fileUpload.jsonImport.indexingResponse": "索引响应", - "xpack.fileUpload.jsonImport.indexMgmtLink": "索引管理", - "xpack.fileUpload.jsonImport.indexModsMsg": "要进一步做索引修改,可以使用\n", - "xpack.fileUpload.jsonImport.indexPatternResponse": "索引模式响应", "xpack.fileUpload.jsonUploadAndParse.dataIndexingError": "数据索引错误", "xpack.fileUpload.jsonUploadAndParse.indexPatternError": "索引模式错误", "xpack.fleet.agentBulkActions.agentsSelected": "已选择 {count, plural, other {# 个代理}}", From c4d0935adc869486c4a42c5ad1351b7d7035d8c5 Mon Sep 17 00:00:00 2001 From: Thom Heymann <190132+thomheymann@users.noreply.github.com> Date: Thu, 8 Apr 2021 21:56:41 +0100 Subject: [PATCH 41/49] Improved role management error handling for partially authorized users (#96468) (#96631) * Role management: Gracefully handle underprivileged users * Removed redundant condition --- .../roles/edit_role/edit_role_page.test.tsx | 28 ++++++++++--------- .../roles/edit_role/edit_role_page.tsx | 8 ++---- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx index 3002db642bc1..5df73f7f8ec4 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx @@ -480,23 +480,25 @@ describe('', () => { }); }); - it('can render if features are not available', async () => { - const { http } = coreMock.createStart(); - http.get.mockImplementation(async (path: any) => { - if (path === '/api/features') { - const error = { response: { status: 404 } }; - throw error; - } + it('registers fatal error if features endpoint fails unexpectedly', async () => { + const error = { response: { status: 500 } }; + const getFeatures = jest.fn().mockRejectedValue(error); + const props = getProps({ action: 'edit' }); + const wrapper = mountWithIntl(); - if (path === '/api/spaces/space') { - return buildSpaces(); - } - }); + await waitForRender(wrapper); + expect(props.fatalErrors.add).toHaveBeenLastCalledWith(error); + expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(0); + }); - const wrapper = mountWithIntl(); + it('can render if features call is not allowed', async () => { + const error = { response: { status: 403 } }; + const getFeatures = jest.fn().mockRejectedValue(error); + const props = getProps({ action: 'edit' }); + const wrapper = mountWithIntl(); await waitForRender(wrapper); - + expect(props.fatalErrors.add).not.toHaveBeenCalled(); expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1); expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0); expectSaveFormButtons(wrapper); diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx index 5d6b4a1b4fda..f810cd2079d1 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx @@ -256,13 +256,12 @@ function useFeatures( // possible that a user with `manage_security` will attempt to visit the role management page without the // correct Kibana privileges. If that's the case, then they receive a partial view of the role, and the UI does // not allow them to make changes to that role's kibana privileges. When this user visits the edit role page, - // this API endpoint will throw a 404, which causes view to fail completely. So we instead attempt to detect the - // 404 here, and respond in a way that still allows the UI to render itself. - const unauthorizedForFeatures = err.response?.status === 404; + // this API endpoint will throw a 403, which causes view to fail completely. So we instead attempt to detect the + // 403 here, and respond in a way that still allows the UI to render itself. + const unauthorizedForFeatures = err.response?.status === 403; if (unauthorizedForFeatures) { return [] as KibanaFeature[]; } - fatalErrors.add(err); }) .then((retrievedFeatures) => { @@ -296,7 +295,6 @@ export const EditRolePage: FunctionComponent = ({ // We should keep the same mutable instance of Validator for every re-render since we'll // eventually enable validation after the first time user tries to save a role. const { current: validator } = useRef(new RoleValidator({ shouldValidate: false })); - const [formError, setFormError] = useState(null); const runAsUsers = useRunAsUsers(userAPIClient, fatalErrors); const indexPatternsTitles = useIndexPatternsTitles(indexPatterns, fatalErrors, notifications); From 0f575aeba5841e53c6bd778502d0392887d2277a Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Thu, 8 Apr 2021 16:46:37 -0500 Subject: [PATCH 42/49] [DOCS] Adds principal associated to keytab file (#96498) (#96652) * [DOCS] Adds principal associated to keytab file * Update docs/user/security/authentication/index.asciidoc Co-authored-by: Aleh Zasypkin * Review comments Co-authored-by: Aleh Zasypkin Co-authored-by: Aleh Zasypkin --- docs/user/security/authentication/index.asciidoc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/user/security/authentication/index.asciidoc b/docs/user/security/authentication/index.asciidoc index f82f9a92298a..23f24108ec8b 100644 --- a/docs/user/security/authentication/index.asciidoc +++ b/docs/user/security/authentication/index.asciidoc @@ -292,7 +292,11 @@ xpack.security.authc.providers: order: 1 ----------------------------------------------- -Kibana uses SPNEGO, which wraps the Kerberos protocol for use with HTTP, extending it to web applications. At the end of the Kerberos handshake, Kibana will forward the service ticket to Elasticsearch. Elasticsearch will unpack it and it will respond with an access and refresh token which are then used for subsequent authentication. +IMPORTANT: {kib} uses SPNEGO, which wraps the Kerberos protocol for use with HTTP, extending it to web applications. +At the end of the Kerberos handshake, {kib} forwards the service ticket to {es}, then {es} unpacks the service ticket and responds with an access and refresh token, which are used for subsequent authentication. +On every {es} node that {kib} connects to, the keytab file should always contain the HTTP service principal for the {kib} host. +The HTTP service principal name must have the `HTTP/kibana.domain.local@KIBANA.DOMAIN.LOCAL` format. + [[anonymous-authentication]] ==== Anonymous authentication From 3808adbe182e7add85c129a85f3f01cf9757a18c Mon Sep 17 00:00:00 2001 From: Nick Peihl Date: Thu, 8 Apr 2021 15:01:54 -0700 Subject: [PATCH 43/49] [docs] Link troubleshooting info for Elastic Maps Service (#96231) (#96666) --- docs/maps/trouble-shooting.asciidoc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/maps/trouble-shooting.asciidoc b/docs/maps/trouble-shooting.asciidoc index 1c53fbd55ea4..11aa636e0d85 100644 --- a/docs/maps/trouble-shooting.asciidoc +++ b/docs/maps/trouble-shooting.asciidoc @@ -44,10 +44,13 @@ Increase <> for large index patterns. * Ensure fill color and border color are distinguishable from map tiles. It's hard to see white features on a white background. [float] -==== Tiles are not displayed +==== Elastic Maps Service basemaps are not displayed +*Maps* uses tile and vector data from Elastic Maps Service by default. See <> for more info. -* Ensure your tile server has configured https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS[Cross-Origin Resource Sharing (CORS)] so tile requests from your Kibana domain have permission to access your tile server domain. -* Ensure tiles have the required coordinate system. Vector data must use EPSG:4326 and tiles must use EPSG:3857. +[float] +==== Custom tiles are not displayed +* When using a custom tile service, ensure your tile server has configured https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS[Cross-Origin Resource Sharing (CORS)] so tile requests from your {kib} domain have permission to access your tile server domain. +* Ensure custom vector and tile services have the required coordinate system. Vector data must use EPSG:4326 and tiles must use EPSG:3857. [float] ==== Coordinate and region map visualizations not available in New Visualization menu From db1597c18c9b7019df7ef477879c48608f7872d9 Mon Sep 17 00:00:00 2001 From: gchaps <33642766+gchaps@users.noreply.github.com> Date: Thu, 8 Apr 2021 15:12:15 -0700 Subject: [PATCH 44/49] [DOCS] Updates advanced settings doc (#93968) (#96643) * [DOCS] Updates advanced settings doc * [DOCS] Edits advanced settings doc * [DOCS] Updates descriptions per review comments * Clarify that TSVB setting is dependent on the other setting * Update docs/management/advanced-options.asciidoc Co-authored-by: Kaarina Tungseth * Update docs/management/advanced-options.asciidoc Co-authored-by: Kaarina Tungseth * Update docs/management/advanced-options.asciidoc Co-authored-by: Kaarina Tungseth * Update docs/management/advanced-options.asciidoc Co-authored-by: Kaarina Tungseth Co-authored-by: Wylie Conlon Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kaarina Tungseth Co-authored-by: Wylie Conlon Co-authored-by: Kaarina Tungseth --- docs/management/advanced-options.asciidoc | 14 ++++++++------ src/plugins/data/server/ui_settings.ts | 16 +++++++++++----- .../vis_type_timeseries/server/ui_settings.ts | 5 +++-- .../plugins/translations/translations/ja-JP.json | 6 ------ .../plugins/translations/translations/zh-CN.json | 6 ------ 5 files changed, 22 insertions(+), 25 deletions(-) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 9670fc82f670..5068d17d6e41 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -119,8 +119,12 @@ When date histograms use the `auto` interval, Kibana attempts to generate this number of bars. [[histogram-maxbars]]`histogram:maxBars`:: -Date histograms are not generated with more bars than the value of this property, -scaling values when necessary. +To improve performance, limits the density of date and number histograms across {kib} +using a test query. When the test query contains too many buckets, +the interval between buckets increases. This setting applies separately +to each histogram aggregation, and does not apply to other types of aggregations. +To find the maximum value of this setting, divide the {es} `search.max_buckets` +value by the maximum number of aggregations in each visualization. [[history-limit]]`history:limit`:: In fields that have history, such as query inputs, show this many recent values. @@ -134,9 +138,7 @@ Fields that exist outside of `_source`. Kibana merges these fields into the document when displaying it. [[metrics-maxbuckets]]`metrics:max_buckets`:: -The maximum numbers of buckets that a single data source can return. This might -arise when the user selects a short interval (for example, 1s) for a long time -period (1 year). +Affects the *TSVB* histogram density. Must be set higher than `histogram:maxBars`. [[query-allowleadingwildcards]]`query:allowLeadingWildcards`:: Allows a wildcard (*) as the first character in a query clause. Only applies @@ -222,7 +224,7 @@ Banners are a https://www.elastic.co/subscriptions[subscription feature]. [horizontal] [[banners-placement]]`banners:placement`:: -Set to `Top` to display a banner above the Elastic header for this space. Defaults to the value of +Set to `Top` to display a banner above the Elastic header for this space. Defaults to the value of the `xpack.banners.placement` configuration property. [[banners-textcontent]]`banners:textContent`:: diff --git a/src/plugins/data/server/ui_settings.ts b/src/plugins/data/server/ui_settings.ts index 23589c22b337..971ae3bb7507 100644 --- a/src/plugins/data/server/ui_settings.ts +++ b/src/plugins/data/server/ui_settings.ts @@ -304,23 +304,29 @@ export function getUiSettings(): Record> { }, [UI_SETTINGS.HISTOGRAM_BAR_TARGET]: { name: i18n.translate('data.advancedSettings.histogram.barTargetTitle', { - defaultMessage: 'Target bars', + defaultMessage: 'Target buckets', }), value: 50, description: i18n.translate('data.advancedSettings.histogram.barTargetText', { defaultMessage: - 'Attempt to generate around this many bars when using "auto" interval in date histograms', + 'Attempt to generate around this many buckets when using "auto" interval in date and numeric histograms', }), schema: schema.number(), }, [UI_SETTINGS.HISTOGRAM_MAX_BARS]: { name: i18n.translate('data.advancedSettings.histogram.maxBarsTitle', { - defaultMessage: 'Maximum bars', + defaultMessage: 'Maximum buckets', }), value: 100, description: i18n.translate('data.advancedSettings.histogram.maxBarsText', { - defaultMessage: - 'Never show more than this many bars in date histograms, scale values if needed', + defaultMessage: ` + Limits the density of date and number histograms across Kibana + for better performance using a test query. If the test query would too many buckets, + the interval between buckets will be increased. This setting applies separately + to each histogram aggregation, and does not apply to other types of aggregation. + To find the maximum value of this setting, divide the Elasticsearch 'search.max_buckets' + value by the maximum number of aggregations in each visualization. + `, }), schema: schema.number(), }, diff --git a/src/plugins/vis_type_timeseries/server/ui_settings.ts b/src/plugins/vis_type_timeseries/server/ui_settings.ts index 9b7f6a1c832e..07d2355b2225 100644 --- a/src/plugins/vis_type_timeseries/server/ui_settings.ts +++ b/src/plugins/vis_type_timeseries/server/ui_settings.ts @@ -16,11 +16,12 @@ import { MAX_BUCKETS_SETTING } from '../common/constants'; export const uiSettings: Record = { [MAX_BUCKETS_SETTING]: { name: i18n.translate('visTypeTimeseries.advancedSettings.maxBucketsTitle', { - defaultMessage: 'Maximum buckets', + defaultMessage: 'TSVB buckets limit', }), value: 2000, description: i18n.translate('visTypeTimeseries.advancedSettings.maxBucketsText', { - defaultMessage: 'The maximum number of buckets a single datasource can return', + defaultMessage: + 'Affects the TSVB histogram density. Must be set higher than "histogram:maxBars".', }), schema: schema.number(), }, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a330589907aa..c7b5bed230b7 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -746,10 +746,6 @@ "data.advancedSettings.format.percentFormat.numeralFormatLinkText": "数字フォーマット", "data.advancedSettings.format.percentFormatText": "「パーセント」フォーマットのデフォルト{numeralFormatLink}です", "data.advancedSettings.format.percentFormatTitle": "パーセントフォーマット", - "data.advancedSettings.histogram.barTargetText": "日付ヒストグラムで「自動」間隔を使用する際、この数に近いバーの作成を試みます", - "data.advancedSettings.histogram.barTargetTitle": "目標バー数", - "data.advancedSettings.histogram.maxBarsText": "日付ヒストグラムに表示されるバーの数の上限です。必要に応じて値をスケーリングしてください", - "data.advancedSettings.histogram.maxBarsTitle": "最高バー数", "data.advancedSettings.historyLimitText": "履歴があるフィールド (例:クエリインプット) に個の数の最近の値が表示されます", "data.advancedSettings.historyLimitTitle": "履歴制限数", "data.advancedSettings.indexPatternPlaceholderText": "「管理 > インデックスパターン > インデックスパターンを作成」で使用される「インデックスパターン名」フィールドのプレースホルダーです。", @@ -4020,8 +4016,6 @@ "visTypeTimeseries.addDeleteButtons.deleteButtonDefaultTooltip": "削除", "visTypeTimeseries.addDeleteButtons.reEnableTooltip": "再度有効にする", "visTypeTimeseries.addDeleteButtons.temporarilyDisableTooltip": "一時的に無効にする", - "visTypeTimeseries.advancedSettings.maxBucketsText": "1つのデータソースが返せるバケットの最大数です", - "visTypeTimeseries.advancedSettings.maxBucketsTitle": "バケットの最大数", "visTypeTimeseries.aggLookup.averageLabel": "平均", "visTypeTimeseries.aggLookup.calculationLabel": "計算", "visTypeTimeseries.aggLookup.cardinalityLabel": "基数", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index b7daf5135555..5dd8695063fb 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -749,10 +749,6 @@ "data.advancedSettings.format.percentFormat.numeralFormatLinkText": "数值格式", "data.advancedSettings.format.percentFormatText": "“百分比”格式的默认{numeralFormatLink}", "data.advancedSettings.format.percentFormatTitle": "百分比格式", - "data.advancedSettings.histogram.barTargetText": "在日期直方图中使用“auto”时尝试生成大约此数目的条形", - "data.advancedSettings.histogram.barTargetTitle": "目标条形数", - "data.advancedSettings.histogram.maxBarsText": "在日期直方图中不要显示超过该数目的条形,需要时显示刻度值", - "data.advancedSettings.histogram.maxBarsTitle": "最大条形数", "data.advancedSettings.historyLimitText": "在具有历史记录 (例如查询输入) 的字段中,显示此数目的最近值", "data.advancedSettings.historyLimitTitle": "历史记录限制", "data.advancedSettings.indexPatternPlaceholderText": "在“管理”>“索引模式”>“创建索引模式”中“索引模式名称”字段的占位符。", @@ -4048,8 +4044,6 @@ "visTypeTimeseries.addDeleteButtons.deleteButtonDefaultTooltip": "删除", "visTypeTimeseries.addDeleteButtons.reEnableTooltip": "重新启用", "visTypeTimeseries.addDeleteButtons.temporarilyDisableTooltip": "暂时禁用", - "visTypeTimeseries.advancedSettings.maxBucketsText": "单个数据源可以返回的最大存储桶数目", - "visTypeTimeseries.advancedSettings.maxBucketsTitle": "最大存储桶数", "visTypeTimeseries.aggLookup.averageLabel": "平均值", "visTypeTimeseries.aggLookup.calculationLabel": "计算", "visTypeTimeseries.aggLookup.cardinalityLabel": "基数", From 203214fb747097575037d46e4080c9b5b1097c78 Mon Sep 17 00:00:00 2001 From: Davey Holler Date: Thu, 8 Apr 2021 15:43:44 -0700 Subject: [PATCH 45/49] App Search Polish (#96345) (#96645) * Button adjustments to Engine Overview page * Subdued preview panel color * Vertically aligns "manage fields" and "preview" Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../app_search/components/engines/components/header.tsx | 2 +- .../app_search/components/engines/engines_overview.tsx | 6 ++++-- .../relevance_tuning_form/relevance_tuning_form.tsx | 1 + .../relevance_tuning/relevance_tuning_preview.tsx | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.tsx index fb3b771850a3..df87f2e5230d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/header.tsx @@ -26,7 +26,7 @@ export const EnginesOverviewHeader: React.FC = () => { rightSideItems={[ // eslint-disable-next-line @elastic/eui/href-or-on-click { {canManageEngines && ( @@ -108,6 +109,7 @@ export const EnginesOverview: React.FC = () => { + { return (
    +

    {i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_preview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_preview.tsx index 5e5ee2ea8d0f..911e97de5b53 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_preview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_preview.tsx @@ -48,7 +48,7 @@ export const RelevanceTuningPreview: React.FC = () => { const { engineName, isMetaEngine } = useValues(EngineLogic); return ( - +

    {i18n.translate('xpack.enterpriseSearch.appSearch.engine.relevanceTuning.preview.title', { From cfd530b75c64c66b4bc738b32c43543abf6c79db Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 8 Apr 2021 19:40:18 -0400 Subject: [PATCH 46/49] [CI] Don't retry steps after a build has been aborted or timed out (#96600) (#96651) Co-authored-by: Brian Seeders --- vars/retryable.groovy | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vars/retryable.groovy b/vars/retryable.groovy index ed84a00ece49..bfd021ddd816 100644 --- a/vars/retryable.groovy +++ b/vars/retryable.groovy @@ -48,7 +48,10 @@ def call(label, Closure closure) { try { closure() - } catch (ex) { + } catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException ex) { + // If the build was aborted, don't retry the step + throw ex + } catch (Exception ex) { if (haveReachedMaxRetries()) { print "Couldn't retry '${label}', have already reached the max number of retries for this build." throw ex From 29a9d2574470c258ed71f74ce3dd35e816f060c0 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 8 Apr 2021 19:43:21 -0400 Subject: [PATCH 47/49] [ML] Add ML plugin contract mocks (#96265) (#96610) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Quynh Nguyen <43350163+qn895@users.noreply.github.com> --- .../__mocks__/ml_url_generator.ts | 17 +++++++++++ x-pack/plugins/ml/public/mocks.ts | 24 +++++++++++++++ x-pack/plugins/ml/server/mocks.ts | 30 +++++++++++++++++++ .../providers/__mocks__/alerting_service.ts | 11 +++++++ .../providers/__mocks__/anomaly_detectors.ts | 14 +++++++++ .../providers/__mocks__/jobs_service.ts | 11 +++++++ .../providers/__mocks__/modules.ts | 14 +++++++++ .../providers/__mocks__/results_service.ts | 11 +++++++ .../providers/__mocks__/system.ts | 13 ++++++++ .../rules/create_rules_bulk_route.test.ts | 4 +-- .../routes/rules/create_rules_route.test.ts | 4 +-- .../routes/rules/import_rules_route.test.ts | 4 +-- .../rules/patch_rules_bulk_route.test.ts | 4 +-- .../routes/rules/patch_rules_route.test.ts | 4 +-- .../rules/update_rules_bulk_route.test.ts | 4 +-- .../routes/rules/update_rules_route.test.ts | 4 +-- .../server/lib/machine_learning/authz.test.ts | 8 ++--- .../server/lib/machine_learning/mocks.ts | 20 ++----------- .../usage/detections/detections.test.ts | 6 ++-- 19 files changed, 168 insertions(+), 39 deletions(-) create mode 100644 x-pack/plugins/ml/public/ml_url_generator/__mocks__/ml_url_generator.ts create mode 100644 x-pack/plugins/ml/public/mocks.ts create mode 100644 x-pack/plugins/ml/server/mocks.ts create mode 100644 x-pack/plugins/ml/server/shared_services/providers/__mocks__/alerting_service.ts create mode 100644 x-pack/plugins/ml/server/shared_services/providers/__mocks__/anomaly_detectors.ts create mode 100644 x-pack/plugins/ml/server/shared_services/providers/__mocks__/jobs_service.ts create mode 100644 x-pack/plugins/ml/server/shared_services/providers/__mocks__/modules.ts create mode 100644 x-pack/plugins/ml/server/shared_services/providers/__mocks__/results_service.ts create mode 100644 x-pack/plugins/ml/server/shared_services/providers/__mocks__/system.ts diff --git a/x-pack/plugins/ml/public/ml_url_generator/__mocks__/ml_url_generator.ts b/x-pack/plugins/ml/public/ml_url_generator/__mocks__/ml_url_generator.ts new file mode 100644 index 000000000000..e5c6a2345e16 --- /dev/null +++ b/x-pack/plugins/ml/public/ml_url_generator/__mocks__/ml_url_generator.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ML_APP_URL_GENERATOR } from '../../../common/constants/ml_url_generator'; +import { UrlGeneratorContract } from '../../../../../../src/plugins/share/public'; + +export const createMlUrlGeneratorMock = () => + ({ + id: ML_APP_URL_GENERATOR, + isDeprecated: false, + createUrl: jest.fn(), + migrate: jest.fn(), + } as jest.Mocked>); diff --git a/x-pack/plugins/ml/public/mocks.ts b/x-pack/plugins/ml/public/mocks.ts new file mode 100644 index 000000000000..6b55cb3b6b65 --- /dev/null +++ b/x-pack/plugins/ml/public/mocks.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { createMlUrlGeneratorMock } from './ml_url_generator/__mocks__/ml_url_generator'; +import { MlPluginSetup, MlPluginStart } from './plugin'; +const createSetupContract = (): jest.Mocked => { + return { + urlGenerator: createMlUrlGeneratorMock(), + }; +}; + +const createStartContract = (): jest.Mocked => { + return { + urlGenerator: createMlUrlGeneratorMock(), + }; +}; + +export const mlPluginMock = { + createSetupContract, + createStartContract, +}; diff --git a/x-pack/plugins/ml/server/mocks.ts b/x-pack/plugins/ml/server/mocks.ts new file mode 100644 index 000000000000..e50f78a0fd99 --- /dev/null +++ b/x-pack/plugins/ml/server/mocks.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { createJobServiceProviderMock } from './shared_services/providers/__mocks__/jobs_service'; +import { createAnomalyDetectorsProviderMock } from './shared_services/providers/__mocks__/anomaly_detectors'; +import { createMockMlSystemProvider } from './shared_services/providers/__mocks__/system'; +import { createModulesProviderMock } from './shared_services/providers/__mocks__/modules'; +import { createResultsServiceProviderMock } from './shared_services/providers/__mocks__/results_service'; +import { createAlertingServiceProviderMock } from './shared_services/providers/__mocks__/alerting_service'; +import { MlPluginSetup } from './plugin'; + +const createSetupContract = () => + (({ + jobServiceProvider: createJobServiceProviderMock(), + anomalyDetectorsProvider: createAnomalyDetectorsProviderMock(), + mlSystemProvider: createMockMlSystemProvider(), + modulesProvider: createModulesProviderMock(), + resultsServiceProvider: createResultsServiceProviderMock(), + alertingServiceProvider: createAlertingServiceProviderMock(), + } as unknown) as jest.Mocked); + +const createStartContract = () => jest.fn(); + +export const mlPluginServerMock = { + createSetupContract, + createStartContract, +}; diff --git a/x-pack/plugins/ml/server/shared_services/providers/__mocks__/alerting_service.ts b/x-pack/plugins/ml/server/shared_services/providers/__mocks__/alerting_service.ts new file mode 100644 index 000000000000..957321e61b83 --- /dev/null +++ b/x-pack/plugins/ml/server/shared_services/providers/__mocks__/alerting_service.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export const createAlertingServiceProviderMock = () => + jest.fn(() => ({ + preview: jest.fn(), + execute: jest.fn(), + })); diff --git a/x-pack/plugins/ml/server/shared_services/providers/__mocks__/anomaly_detectors.ts b/x-pack/plugins/ml/server/shared_services/providers/__mocks__/anomaly_detectors.ts new file mode 100644 index 000000000000..12b12e4ba06d --- /dev/null +++ b/x-pack/plugins/ml/server/shared_services/providers/__mocks__/anomaly_detectors.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const createAnomalyDetectorsProviderMock = () => + jest.fn(() => ({ + jobs: jest.fn(), + jobStats: jest.fn(), + datafeeds: jest.fn(), + datafeedStats: jest.fn(), + })); diff --git a/x-pack/plugins/ml/server/shared_services/providers/__mocks__/jobs_service.ts b/x-pack/plugins/ml/server/shared_services/providers/__mocks__/jobs_service.ts new file mode 100644 index 000000000000..e39373d66eff --- /dev/null +++ b/x-pack/plugins/ml/server/shared_services/providers/__mocks__/jobs_service.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const createJobServiceProviderMock = () => + jest.fn(() => ({ + jobsSummary: jest.fn(), + })); diff --git a/x-pack/plugins/ml/server/shared_services/providers/__mocks__/modules.ts b/x-pack/plugins/ml/server/shared_services/providers/__mocks__/modules.ts new file mode 100644 index 000000000000..b33e11dae587 --- /dev/null +++ b/x-pack/plugins/ml/server/shared_services/providers/__mocks__/modules.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const createModulesProviderMock = () => + jest.fn(() => ({ + recognize: jest.fn(), + getModule: jest.fn(), + listModules: jest.fn(), + setup: jest.fn(), + })); diff --git a/x-pack/plugins/ml/server/shared_services/providers/__mocks__/results_service.ts b/x-pack/plugins/ml/server/shared_services/providers/__mocks__/results_service.ts new file mode 100644 index 000000000000..7fd60d0b3428 --- /dev/null +++ b/x-pack/plugins/ml/server/shared_services/providers/__mocks__/results_service.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const createResultsServiceProviderMock = () => + jest.fn(() => ({ + getAnomaliesTableData: jest.fn(), + })); diff --git a/x-pack/plugins/ml/server/shared_services/providers/__mocks__/system.ts b/x-pack/plugins/ml/server/shared_services/providers/__mocks__/system.ts new file mode 100644 index 000000000000..c002ddc4ced5 --- /dev/null +++ b/x-pack/plugins/ml/server/shared_services/providers/__mocks__/system.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const createMockMlSystemProvider = () => + jest.fn(() => ({ + mlCapabilities: jest.fn(), + mlInfo: jest.fn(), + mlAnomalySearch: jest.fn(), + })); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts index c5cbbeb09ed6..ef7236084508 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts @@ -27,12 +27,12 @@ jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); describe('create_rules_bulk', () => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); - let ml: ReturnType; + let ml: ReturnType; beforeEach(() => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); - ml = mlServicesMock.create(); + ml = mlServicesMock.createSetupContract(); clients.clusterClient.callAsCurrentUser.mockResolvedValue(getNonEmptyIndex()); // index exists clients.alertsClient.find.mockResolvedValue(getEmptyFindResult()); // no existing rules diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts index dd636d5a180d..d6693dc1f7a0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts @@ -29,12 +29,12 @@ jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); describe('create_rules', () => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); - let ml: ReturnType; + let ml: ReturnType; beforeEach(() => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); - ml = mlServicesMock.create(); + ml = mlServicesMock.createSetupContract(); clients.clusterClient.callAsCurrentUser.mockResolvedValue(getNonEmptyIndex()); // index exists clients.alertsClient.find.mockResolvedValue(getEmptyFindResult()); // no current rules diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts index 0a265adf620e..b0b423265180 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts @@ -34,7 +34,7 @@ describe('import_rules_route', () => { let server: ReturnType; let request: ReturnType; let { clients, context } = requestContextMock.createTools(); - let ml: ReturnType; + let ml: ReturnType; beforeEach(() => { server = serverMock.create(); @@ -42,7 +42,7 @@ describe('import_rules_route', () => { config = createMockConfig(); const hapiStream = buildHapiStream(ruleIdsToNdJsonString(['rule-1'])); request = getImportRulesRequest(hapiStream); - ml = mlServicesMock.create(); + ml = mlServicesMock.createSetupContract(); clients.clusterClient.callAsCurrentUser.mockResolvedValue(getNonEmptyIndex()); // index exists clients.alertsClient.find.mockResolvedValue(getEmptyFindResult()); // no extant rules diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts index 88250fb920d6..93fdf9c5f819 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts @@ -24,12 +24,12 @@ jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); describe('patch_rules_bulk', () => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); - let ml: ReturnType; + let ml: ReturnType; beforeEach(() => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); - ml = mlServicesMock.create(); + ml = mlServicesMock.createSetupContract(); clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); // rule exists clients.alertsClient.update.mockResolvedValue(getResult()); // update succeeds diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts index 1f21a11f22ef..6e62f65f4485 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts @@ -26,12 +26,12 @@ jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); describe('patch_rules', () => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); - let ml: ReturnType; + let ml: ReturnType; beforeEach(() => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); - ml = mlServicesMock.create(); + ml = mlServicesMock.createSetupContract(); clients.alertsClient.get.mockResolvedValue(getResult()); // existing rule clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); // existing rule diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts index 09ac156c375e..41b31b04e342 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts @@ -26,12 +26,12 @@ jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); describe('update_rules_bulk', () => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); - let ml: ReturnType; + let ml: ReturnType; beforeEach(() => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); - ml = mlServicesMock.create(); + ml = mlServicesMock.createSetupContract(); clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); clients.alertsClient.update.mockResolvedValue(getResult()); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts index e5bea42bc49a..c80d32e09cca 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts @@ -28,12 +28,12 @@ jest.mock('../../rules/update_rules_notifications'); describe('update_rules', () => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); - let ml: ReturnType; + let ml: ReturnType; beforeEach(() => { server = serverMock.create(); ({ clients, context } = requestContextMock.createTools()); - ml = mlServicesMock.create(); + ml = mlServicesMock.createSetupContract(); clients.alertsClient.get.mockResolvedValue(getResult()); // existing rule clients.alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); // rule exists diff --git a/x-pack/plugins/security_solution/server/lib/machine_learning/authz.test.ts b/x-pack/plugins/security_solution/server/lib/machine_learning/authz.test.ts index b41ba543675e..d87c53ecfba7 100644 --- a/x-pack/plugins/security_solution/server/lib/machine_learning/authz.test.ts +++ b/x-pack/plugins/security_solution/server/lib/machine_learning/authz.test.ts @@ -16,7 +16,7 @@ jest.mock('../../../common/machine_learning/has_ml_admin_permissions'); describe('isMlAdmin', () => { it('returns true if hasMlAdminPermissions is true', async () => { - const mockMl = mlServicesMock.create(); + const mockMl = mlServicesMock.createSetupContract(); const request = httpServerMock.createKibanaRequest(); const savedObjectsClient = savedObjectsClientMock.create(); (hasMlAdminPermissions as jest.Mock).mockReturnValue(true); @@ -25,7 +25,7 @@ describe('isMlAdmin', () => { }); it('returns false if hasMlAdminPermissions is false', async () => { - const mockMl = mlServicesMock.create(); + const mockMl = mlServicesMock.createSetupContract(); const request = httpServerMock.createKibanaRequest(); const savedObjectsClient = savedObjectsClientMock.create(); (hasMlAdminPermissions as jest.Mock).mockReturnValue(false); @@ -56,13 +56,13 @@ describe('hasMlLicense', () => { describe('mlAuthz', () => { let licenseMock: ReturnType; - let mlMock: ReturnType; + let mlMock: ReturnType; let request: KibanaRequest; let savedObjectsClient: SavedObjectsClientContract; beforeEach(() => { licenseMock = licensingMock.createLicenseMock(); - mlMock = mlServicesMock.create(); + mlMock = mlServicesMock.createSetupContract(); request = httpServerMock.createKibanaRequest(); savedObjectsClient = savedObjectsClientMock.create(); }); diff --git a/x-pack/plugins/security_solution/server/lib/machine_learning/mocks.ts b/x-pack/plugins/security_solution/server/lib/machine_learning/mocks.ts index 5d1b090e98a7..a121a682d289 100644 --- a/x-pack/plugins/security_solution/server/lib/machine_learning/mocks.ts +++ b/x-pack/plugins/security_solution/server/lib/machine_learning/mocks.ts @@ -5,25 +5,9 @@ * 2.0. */ -import { MlPluginSetup } from '../../../../ml/server'; -import { elasticsearchServiceMock } from '../../../../../../src/core/server/mocks'; +import { mlPluginServerMock } from '../../../../ml/server/mocks'; -const createMockClient = () => elasticsearchServiceMock.createLegacyClusterClient(); -const createMockMlSystemProvider = () => - jest.fn(() => ({ - mlCapabilities: jest.fn(), - })); - -export const mlServicesMock = { - create: () => - (({ - modulesProvider: jest.fn(), - jobServiceProvider: jest.fn(), - anomalyDetectorsProvider: jest.fn(), - mlSystemProvider: createMockMlSystemProvider(), - mlClient: createMockClient(), - } as unknown) as jest.Mocked), -}; +export const mlServicesMock = mlPluginServerMock; const mockValidateRuleType = jest.fn().mockResolvedValue({ valid: true, message: undefined }); const createBuildMlAuthzMock = () => diff --git a/x-pack/plugins/security_solution/server/usage/detections/detections.test.ts b/x-pack/plugins/security_solution/server/usage/detections/detections.test.ts index b53f90f40f62..64a33068ad68 100644 --- a/x-pack/plugins/security_solution/server/usage/detections/detections.test.ts +++ b/x-pack/plugins/security_solution/server/usage/detections/detections.test.ts @@ -21,12 +21,12 @@ import { fetchDetectionsUsage, fetchDetectionsMetrics } from './index'; describe('Detections Usage and Metrics', () => { let esClientMock: jest.Mocked; let savedObjectsClientMock: jest.Mocked; - let mlMock: ReturnType; + let mlMock: ReturnType; describe('fetchDetectionsUsage()', () => { beforeEach(() => { esClientMock = elasticsearchServiceMock.createClusterClient().asInternalUser; - mlMock = mlServicesMock.create(); + mlMock = mlServicesMock.createSetupContract(); }); it('returns zeroed counts if both calls are empty', async () => { @@ -108,7 +108,7 @@ describe('Detections Usage and Metrics', () => { describe('fetchDetectionsMetrics()', () => { beforeEach(() => { - mlMock = mlServicesMock.create(); + mlMock = mlServicesMock.createSetupContract(); }); it('returns an empty array if there is no data', async () => { From 81b46f1302fa108caca01e12ab3de6c5e648afe5 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Fri, 9 Apr 2021 01:44:56 +0200 Subject: [PATCH 48/49] [Rollup] Migrate to new ES client (#95926) (#96405) * initial pass at es client migration * fixed potential for not passing in an error message and triggering an unhandled exception * reworked ad hoc fixing of error response * delete legacy client file and remove use of legacyEs service * remove unused import Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> # Conflicts: # x-pack/plugins/rollup/server/routes/api/jobs/register_start_route.ts Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../errors/handle_es_error.ts | 2 +- .../server/client/elasticsearch_rollup.ts | 142 ------------------ x-pack/plugins/rollup/server/plugin.ts | 25 +-- .../routes/api/indices/register_get_route.ts | 17 +-- .../register_validate_index_pattern_route.ts | 50 +++--- .../routes/api/jobs/register_create_route.ts | 12 +- .../routes/api/jobs/register_delete_route.ts | 27 ++-- .../routes/api/jobs/register_get_route.ts | 10 +- .../routes/api/jobs/register_start_route.ts | 33 ++-- .../routes/api/jobs/register_stop_route.ts | 12 +- .../api/search/register_search_route.ts | 20 +-- .../plugins/rollup/server/services/license.ts | 7 +- .../plugins/rollup/server/shared_imports.ts | 2 +- x-pack/plugins/rollup/server/types.ts | 27 +--- .../apis/management/rollup/lib/es_index.js | 2 +- .../apps/rollup_job/hybrid_index_pattern.js | 14 +- .../functional/apps/rollup_job/rollup_jobs.js | 2 +- .../test/functional/apps/rollup_job/tsvb.js | 7 +- 18 files changed, 100 insertions(+), 311 deletions(-) delete mode 100644 x-pack/plugins/rollup/server/client/elasticsearch_rollup.ts diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts index a98a74375638..42e18b72057c 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts @@ -36,7 +36,7 @@ export const handleEsError = ({ return response.customError({ statusCode, body: { - message: body.error?.reason, + message: body.error?.reason ?? error.message ?? 'Unknown error', attributes: { // The full original ES error object error: body.error, diff --git a/x-pack/plugins/rollup/server/client/elasticsearch_rollup.ts b/x-pack/plugins/rollup/server/client/elasticsearch_rollup.ts deleted file mode 100644 index 0296428c4961..000000000000 --- a/x-pack/plugins/rollup/server/client/elasticsearch_rollup.ts +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export const elasticsearchJsPlugin = (Client: any, config: any, components: any) => { - const ca = components.clientAction.factory; - - Client.prototype.rollup = components.clientAction.namespaceFactory(); - const rollup = Client.prototype.rollup.prototype; - - rollup.rollupIndexCapabilities = ca({ - urls: [ - { - fmt: '/<%=indexPattern%>/_rollup/data', - req: { - indexPattern: { - type: 'string', - }, - }, - }, - ], - method: 'GET', - }); - - rollup.search = ca({ - urls: [ - { - fmt: '/<%=index%>/_rollup_search', - req: { - index: { - type: 'string', - }, - }, - }, - ], - needBody: true, - method: 'POST', - }); - - rollup.fieldCapabilities = ca({ - urls: [ - { - fmt: '/<%=indexPattern%>/_field_caps?fields=*', - req: { - indexPattern: { - type: 'string', - }, - }, - }, - ], - method: 'GET', - }); - - rollup.jobs = ca({ - urls: [ - { - fmt: '/_rollup/job/_all', - }, - ], - method: 'GET', - }); - - rollup.job = ca({ - urls: [ - { - fmt: '/_rollup/job/<%=id%>', - req: { - id: { - type: 'string', - }, - }, - }, - ], - method: 'GET', - }); - - rollup.startJob = ca({ - urls: [ - { - fmt: '/_rollup/job/<%=id%>/_start', - req: { - id: { - type: 'string', - }, - }, - }, - ], - method: 'POST', - }); - - rollup.stopJob = ca({ - params: { - waitForCompletion: { - type: 'boolean', - name: 'wait_for_completion', - }, - }, - urls: [ - { - fmt: '/_rollup/job/<%=id%>/_stop', - req: { - id: { - type: 'string', - }, - }, - }, - ], - method: 'POST', - }); - - rollup.deleteJob = ca({ - urls: [ - { - fmt: '/_rollup/job/<%=id%>', - req: { - id: { - type: 'string', - }, - }, - }, - ], - method: 'DELETE', - }); - - rollup.createJob = ca({ - urls: [ - { - fmt: '/_rollup/job/<%=id%>', - req: { - id: { - type: 'string', - }, - }, - }, - ], - needBody: true, - method: 'PUT', - }); -}; diff --git a/x-pack/plugins/rollup/server/plugin.ts b/x-pack/plugins/rollup/server/plugin.ts index 1b982ab45205..ff6adc1c8d24 100644 --- a/x-pack/plugins/rollup/server/plugin.ts +++ b/x-pack/plugins/rollup/server/plugin.ts @@ -19,25 +19,16 @@ import { i18n } from '@kbn/i18n'; import { schema } from '@kbn/config-schema'; import { PLUGIN, CONFIG_ROLLUPS } from '../common'; -import { Dependencies, RollupHandlerContext } from './types'; +import { Dependencies } from './types'; import { registerApiRoutes } from './routes'; import { License } from './services'; import { registerRollupUsageCollector } from './collectors'; import { rollupDataEnricher } from './rollup_data_enricher'; import { IndexPatternsFetcher } from './shared_imports'; -import { elasticsearchJsPlugin } from './client/elasticsearch_rollup'; -import { isEsError } from './shared_imports'; +import { handleEsError } from './shared_imports'; import { formatEsError } from './lib/format_es_error'; import { getCapabilitiesForRollupIndices } from '../../../../src/plugins/data/server'; -async function getCustomEsClient(getStartServices: CoreSetup['getStartServices']) { - const [core] = await getStartServices(); - // Extend the elasticsearchJs client with additional endpoints. - const esClientConfig = { plugins: [elasticsearchJsPlugin] }; - - return core.elasticsearch.legacy.createClient('rollup', esClientConfig); -} - export class RollupPlugin implements Plugin { private readonly logger: Logger; private readonly globalConfig$: Observable; @@ -82,21 +73,11 @@ export class RollupPlugin implements Plugin { ], }); - http.registerRouteHandlerContext( - 'rollup', - async (context, request) => { - this.rollupEsClient = this.rollupEsClient ?? (await getCustomEsClient(getStartServices)); - return { - client: this.rollupEsClient.asScoped(request), - }; - } - ); - registerApiRoutes({ router: http.createRouter(), license: this.license, lib: { - isEsError, + handleEsError, formatEsError, getCapabilitiesForRollupIndices, }, diff --git a/x-pack/plugins/rollup/server/routes/api/indices/register_get_route.ts b/x-pack/plugins/rollup/server/routes/api/indices/register_get_route.ts index 694ab3c467c1..1d3be4b8e1fb 100644 --- a/x-pack/plugins/rollup/server/routes/api/indices/register_get_route.ts +++ b/x-pack/plugins/rollup/server/routes/api/indices/register_get_route.ts @@ -14,7 +14,7 @@ import { RouteDependencies } from '../../../types'; export const registerGetRoute = ({ router, license, - lib: { isEsError, formatEsError, getCapabilitiesForRollupIndices }, + lib: { handleEsError, getCapabilitiesForRollupIndices }, }: RouteDependencies) => { router.get( { @@ -23,18 +23,13 @@ export const registerGetRoute = ({ }, license.guardApiRoute(async (context, request, response) => { try { - const data = await context.rollup!.client.callAsCurrentUser( - 'rollup.rollupIndexCapabilities', - { - indexPattern: '_all', - } - ); + const { client: clusterClient } = context.core.elasticsearch; + const { body: data } = await clusterClient.asCurrentUser.rollup.getRollupIndexCaps({ + index: '_all', + }); return response.ok({ body: getCapabilitiesForRollupIndices(data) }); } catch (err) { - if (isEsError(err)) { - return response.customError({ statusCode: err.statusCode, body: err }); - } - throw err; + return handleEsError({ error: err, response }); } }) ); diff --git a/x-pack/plugins/rollup/server/routes/api/indices/register_validate_index_pattern_route.ts b/x-pack/plugins/rollup/server/routes/api/indices/register_validate_index_pattern_route.ts index 90eabaa88b64..b2431c383823 100644 --- a/x-pack/plugins/rollup/server/routes/api/indices/register_validate_index_pattern_route.ts +++ b/x-pack/plugins/rollup/server/routes/api/indices/register_validate_index_pattern_route.ts @@ -32,10 +32,6 @@ interface FieldCapability { scaled_float?: any; } -interface FieldCapabilities { - fields: FieldCapability[]; -} - function isNumericField(fieldCapability: FieldCapability) { const numericTypes = [ 'long', @@ -59,7 +55,7 @@ function isNumericField(fieldCapability: FieldCapability) { export const registerValidateIndexPatternRoute = ({ router, license, - lib: { isEsError, formatEsError }, + lib: { handleEsError }, }: RouteDependencies) => { router.get( { @@ -71,16 +67,12 @@ export const registerValidateIndexPatternRoute = ({ }, }, license.guardApiRoute(async (context, request, response) => { + const { client: clusterClient } = context.core.elasticsearch; try { const { indexPattern } = request.params; - const [fieldCapabilities, rollupIndexCapabilities]: [ - FieldCapabilities, - { [key: string]: any } - ] = await Promise.all([ - context.rollup!.client.callAsCurrentUser('rollup.fieldCapabilities', { indexPattern }), - context.rollup!.client.callAsCurrentUser('rollup.rollupIndexCapabilities', { - indexPattern, - }), + const [{ body: fieldCapabilities }, { body: rollupIndexCapabilities }] = await Promise.all([ + clusterClient.asCurrentUser.fieldCaps({ index: indexPattern, fields: '*' }), + clusterClient.asCurrentUser.rollup.getRollupIndexCaps({ index: indexPattern }), ]); const doesMatchIndices = Object.entries(fieldCapabilities.fields).length !== 0; @@ -92,23 +84,21 @@ export const registerValidateIndexPatternRoute = ({ const fieldCapabilitiesEntries = Object.entries(fieldCapabilities.fields); - fieldCapabilitiesEntries.forEach( - ([fieldName, fieldCapability]: [string, FieldCapability]) => { - if (fieldCapability.date) { - dateFields.push(fieldName); - return; - } + fieldCapabilitiesEntries.forEach(([fieldName, fieldCapability]) => { + if (fieldCapability.date) { + dateFields.push(fieldName); + return; + } - if (isNumericField(fieldCapability)) { - numericFields.push(fieldName); - return; - } + if (isNumericField(fieldCapability)) { + numericFields.push(fieldName); + return; + } - if (fieldCapability.keyword) { - keywordFields.push(fieldName); - } + if (fieldCapability.keyword) { + keywordFields.push(fieldName); } - ); + }); const body = { doesMatchIndices, @@ -132,11 +122,7 @@ export const registerValidateIndexPatternRoute = ({ return response.ok({ body: notFoundBody }); } - if (isEsError(err)) { - return response.customError({ statusCode: err.statusCode, body: err }); - } - - throw err; + return handleEsError({ error: err, response }); } }) ); diff --git a/x-pack/plugins/rollup/server/routes/api/jobs/register_create_route.ts b/x-pack/plugins/rollup/server/routes/api/jobs/register_create_route.ts index bcb3a337aa72..11cfaf8851d4 100644 --- a/x-pack/plugins/rollup/server/routes/api/jobs/register_create_route.ts +++ b/x-pack/plugins/rollup/server/routes/api/jobs/register_create_route.ts @@ -12,7 +12,7 @@ import { RouteDependencies } from '../../../types'; export const registerCreateRoute = ({ router, license, - lib: { isEsError, formatEsError }, + lib: { handleEsError }, }: RouteDependencies) => { router.put( { @@ -29,21 +29,19 @@ export const registerCreateRoute = ({ }, }, license.guardApiRoute(async (context, request, response) => { + const { client: clusterClient } = context.core.elasticsearch; try { const { id, ...rest } = request.body.job; // Create job. - await context.rollup!.client.callAsCurrentUser('rollup.createJob', { + await clusterClient.asCurrentUser.rollup.putJob({ id, body: rest, }); // Then request the newly created job. - const results = await context.rollup!.client.callAsCurrentUser('rollup.job', { id }); + const { body: results } = await clusterClient.asCurrentUser.rollup.getJobs({ id }); return response.ok({ body: results.jobs[0] }); } catch (err) { - if (isEsError(err)) { - return response.customError({ statusCode: err.statusCode, body: err }); - } - throw err; + return handleEsError({ error: err, response }); } }) ); diff --git a/x-pack/plugins/rollup/server/routes/api/jobs/register_delete_route.ts b/x-pack/plugins/rollup/server/routes/api/jobs/register_delete_route.ts index 4bbe73753e96..f90a81f73823 100644 --- a/x-pack/plugins/rollup/server/routes/api/jobs/register_delete_route.ts +++ b/x-pack/plugins/rollup/server/routes/api/jobs/register_delete_route.ts @@ -12,7 +12,7 @@ import { RouteDependencies } from '../../../types'; export const registerDeleteRoute = ({ router, license, - lib: { isEsError, formatEsError }, + lib: { handleEsError }, }: RouteDependencies) => { router.post( { @@ -24,28 +24,29 @@ export const registerDeleteRoute = ({ }, }, license.guardApiRoute(async (context, request, response) => { + const { client: clusterClient } = context.core.elasticsearch; try { const { jobIds } = request.body; const data = await Promise.all( - jobIds.map((id: string) => - context.rollup!.client.callAsCurrentUser('rollup.deleteJob', { id }) - ) + jobIds.map((id: string) => clusterClient.asCurrentUser.rollup.deleteJob({ id })) ).then(() => ({ success: true })); return response.ok({ body: data }); } catch (err) { // There is an issue opened on ES to handle the following error correctly // https://github.com/elastic/elasticsearch/issues/42908 // Until then we'll modify the response here. - if (err.response && err.response.includes('Job must be [STOPPED] before deletion')) { - err.status = 400; - err.statusCode = 400; - err.displayName = 'Bad request'; - err.message = JSON.parse(err.response).task_failures[0].reason.reason; - } - if (isEsError(err)) { - return response.customError({ statusCode: err.statusCode, body: err }); + if ( + err?.meta && + err.body?.task_failures[0]?.reason?.reason?.includes( + 'Job must be [STOPPED] before deletion' + ) + ) { + err.meta.status = 400; + err.meta.statusCode = 400; + err.meta.displayName = 'Bad request'; + err.message = err.body.task_failures[0].reason.reason; } - throw err; + return handleEsError({ error: err, response }); } }) ); diff --git a/x-pack/plugins/rollup/server/routes/api/jobs/register_get_route.ts b/x-pack/plugins/rollup/server/routes/api/jobs/register_get_route.ts index a9a30c0370c5..9944df2e5591 100644 --- a/x-pack/plugins/rollup/server/routes/api/jobs/register_get_route.ts +++ b/x-pack/plugins/rollup/server/routes/api/jobs/register_get_route.ts @@ -11,7 +11,7 @@ import { RouteDependencies } from '../../../types'; export const registerGetRoute = ({ router, license, - lib: { isEsError, formatEsError }, + lib: { handleEsError }, }: RouteDependencies) => { router.get( { @@ -19,14 +19,12 @@ export const registerGetRoute = ({ validate: false, }, license.guardApiRoute(async (context, request, response) => { + const { client: clusterClient } = context.core.elasticsearch; try { - const data = await context.rollup!.client.callAsCurrentUser('rollup.jobs'); + const { body: data } = await clusterClient.asCurrentUser.rollup.getJobs({ id: '_all' }); return response.ok({ body: data }); } catch (err) { - if (isEsError(err)) { - return response.customError({ statusCode: err.statusCode, body: err }); - } - throw err; + return handleEsError({ error: err, response }); } }) ); diff --git a/x-pack/plugins/rollup/server/routes/api/jobs/register_start_route.ts b/x-pack/plugins/rollup/server/routes/api/jobs/register_start_route.ts index dc6e7d2aadc0..cee0898073da 100644 --- a/x-pack/plugins/rollup/server/routes/api/jobs/register_start_route.ts +++ b/x-pack/plugins/rollup/server/routes/api/jobs/register_start_route.ts @@ -12,7 +12,7 @@ import { RouteDependencies } from '../../../types'; export const registerStartRoute = ({ router, license, - lib: { isEsError, formatEsError }, + lib: { handleEsError }, }: RouteDependencies) => { router.post( { @@ -29,31 +29,30 @@ export const registerStartRoute = ({ }, }, license.guardApiRoute(async (context, request, response) => { + const { client: clusterClient } = context.core.elasticsearch; try { const { jobIds } = request.body; const data = await Promise.all( - jobIds.map((id: string) => - context.rollup!.client.callAsCurrentUser('rollup.startJob', { id }) - ) + jobIds.map((id: string) => clusterClient.asCurrentUser.rollup.startJob({ id })) ).then(() => ({ success: true })); return response.ok({ body: data }); } catch (err) { // There is an issue opened on ES to handle the following error correctly - // https://github.com/elastic/elasticsearch/issues/39845, which was addressed in 8.0 - // but not backported to 7.x because it's breaking. So we need to modify the response - // here for 7.x. - if (err.message.includes('Cannot start task for Rollup Job')) { - err.status = 400; - err.statusCode = 400; - err.body.error.status = 400; - err.displayName = 'Bad request'; - } - - if (isEsError(err)) { - return response.customError({ statusCode: err.statusCode, body: err }); + // https://github.com/elastic/elasticsearch/issues/42908 + // Until then we'll modify the response here. + if ( + err?.meta && + err.body?.task_failures[0]?.reason?.reason?.includes( + 'Job must be [STOPPED] before deletion' + ) + ) { + err.meta.status = 400; + err.meta.statusCode = 400; + err.meta.displayName = 'Bad request'; + err.message = err.body.task_failures[0].reason.reason; } - throw err; + return handleEsError({ error: err, response }); } }) ); diff --git a/x-pack/plugins/rollup/server/routes/api/jobs/register_stop_route.ts b/x-pack/plugins/rollup/server/routes/api/jobs/register_stop_route.ts index faaf377a2d83..164273f604b4 100644 --- a/x-pack/plugins/rollup/server/routes/api/jobs/register_stop_route.ts +++ b/x-pack/plugins/rollup/server/routes/api/jobs/register_stop_route.ts @@ -12,7 +12,7 @@ import { RouteDependencies } from '../../../types'; export const registerStopRoute = ({ router, license, - lib: { isEsError, formatEsError }, + lib: { handleEsError }, }: RouteDependencies) => { router.post( { @@ -27,23 +27,21 @@ export const registerStopRoute = ({ }, }, license.guardApiRoute(async (context, request, response) => { + const { client: clusterClient } = context.core.elasticsearch; try { const { jobIds } = request.body; // For our API integration tests we need to wait for the jobs to be stopped // in order to be able to delete them sequentially. const { waitForCompletion } = request.query; const stopRollupJob = (id: string) => - context.rollup!.client.callAsCurrentUser('rollup.stopJob', { + clusterClient.asCurrentUser.rollup.stopJob({ id, - waitForCompletion: waitForCompletion === 'true', + wait_for_completion: waitForCompletion === 'true', }); const data = await Promise.all(jobIds.map(stopRollupJob)).then(() => ({ success: true })); return response.ok({ body: data }); } catch (err) { - if (isEsError(err)) { - return response.customError({ statusCode: err.statusCode, body: err }); - } - throw err; + return handleEsError({ error: err, response }); } }) ); diff --git a/x-pack/plugins/rollup/server/routes/api/search/register_search_route.ts b/x-pack/plugins/rollup/server/routes/api/search/register_search_route.ts index f77ae7829bb6..62aec4e01eaa 100644 --- a/x-pack/plugins/rollup/server/routes/api/search/register_search_route.ts +++ b/x-pack/plugins/rollup/server/routes/api/search/register_search_route.ts @@ -12,7 +12,7 @@ import { RouteDependencies } from '../../../types'; export const registerSearchRoute = ({ router, license, - lib: { isEsError, formatEsError }, + lib: { handleEsError }, }: RouteDependencies) => { router.post( { @@ -27,21 +27,21 @@ export const registerSearchRoute = ({ }, }, license.guardApiRoute(async (context, request, response) => { + const { client: clusterClient } = context.core.elasticsearch; try { const requests = request.body.map(({ index, query }: { index: string; query?: any }) => - context.rollup.client.callAsCurrentUser('rollup.search', { - index, - rest_total_hits_as_int: true, - body: query, - }) + clusterClient.asCurrentUser.rollup + .rollupSearch({ + index, + rest_total_hits_as_int: true, + body: query, + }) + .then(({ body }) => body) ); const data = await Promise.all(requests); return response.ok({ body: data }); } catch (err) { - if (isEsError(err)) { - return response.customError({ statusCode: err.statusCode, body: err }); - } - throw err; + return handleEsError({ error: err, response }); } }) ); diff --git a/x-pack/plugins/rollup/server/services/license.ts b/x-pack/plugins/rollup/server/services/license.ts index d2c3ff82eab1..1b88a4020afa 100644 --- a/x-pack/plugins/rollup/server/services/license.ts +++ b/x-pack/plugins/rollup/server/services/license.ts @@ -5,12 +5,11 @@ * 2.0. */ -import { Logger } from 'src/core/server'; +import { Logger, RequestHandlerContext } from 'src/core/server'; import { KibanaRequest, KibanaResponseFactory, RequestHandler } from 'src/core/server'; import { LicensingPluginSetup } from '../../../licensing/server'; import { LicenseType } from '../../../licensing/common/types'; -import type { RollupHandlerContext } from '../types'; export interface LicenseStatus { isValid: boolean; @@ -57,11 +56,11 @@ export class License { }); } - guardApiRoute(handler: RequestHandler) { + guardApiRoute(handler: RequestHandler) { const license = this; return function licenseCheck( - ctx: RollupHandlerContext, + ctx: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory ) { diff --git a/x-pack/plugins/rollup/server/shared_imports.ts b/x-pack/plugins/rollup/server/shared_imports.ts index 2167558c3965..fe157644c6b3 100644 --- a/x-pack/plugins/rollup/server/shared_imports.ts +++ b/x-pack/plugins/rollup/server/shared_imports.ts @@ -7,4 +7,4 @@ export { IndexPatternsFetcher } from '../../../../src/plugins/data/server'; -export { isEsError } from '../../../../src/plugins/es_ui_shared/server'; +export { handleEsError } from '../../../../src/plugins/es_ui_shared/server'; diff --git a/x-pack/plugins/rollup/server/types.ts b/x-pack/plugins/rollup/server/types.ts index 45dcc976b211..c774644da46c 100644 --- a/x-pack/plugins/rollup/server/types.ts +++ b/x-pack/plugins/rollup/server/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IRouter, ILegacyScopedClusterClient, RequestHandlerContext } from 'src/core/server'; +import { IRouter } from 'src/core/server'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { VisTypeTimeseriesSetup } from 'src/plugins/vis_type_timeseries/server'; @@ -15,7 +15,7 @@ import { PluginSetupContract as FeaturesPluginSetup } from '../../features/serve import { LicensingPluginSetup } from '../../licensing/server'; import { License } from './services'; import { IndexPatternsFetcher } from './shared_imports'; -import { isEsError } from './shared_imports'; +import { handleEsError } from './shared_imports'; import { formatEsError } from './lib/format_es_error'; export interface Dependencies { @@ -27,10 +27,10 @@ export interface Dependencies { } export interface RouteDependencies { - router: RollupPluginRouter; + router: IRouter; license: License; lib: { - isEsError: typeof isEsError; + handleEsError: typeof handleEsError; formatEsError: typeof formatEsError; getCapabilitiesForRollupIndices: typeof getCapabilitiesForRollupIndices; }; @@ -38,22 +38,3 @@ export interface RouteDependencies { IndexPatternsFetcher: typeof IndexPatternsFetcher; }; } - -/** - * @internal - */ -interface RollupApiRequestHandlerContext { - client: ILegacyScopedClusterClient; -} - -/** - * @internal - */ -export interface RollupHandlerContext extends RequestHandlerContext { - rollup: RollupApiRequestHandlerContext; -} - -/** - * @internal - */ -export type RollupPluginRouter = IRouter; diff --git a/x-pack/test/api_integration/apis/management/rollup/lib/es_index.js b/x-pack/test/api_integration/apis/management/rollup/lib/es_index.js index d4c6be0f4a0d..7aacd9f6a7fc 100644 --- a/x-pack/test/api_integration/apis/management/rollup/lib/es_index.js +++ b/x-pack/test/api_integration/apis/management/rollup/lib/es_index.js @@ -13,7 +13,7 @@ import { getRandomString } from './random'; * @param {ElasticsearchClient} es The Elasticsearch client instance */ export const initElasticsearchIndicesHelpers = (getService) => { - const es = getService('legacyEs'); + const es = getService('es'); const esDeleteAllIndices = getService('esDeleteAllIndices'); let indicesCreated = []; diff --git a/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js b/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js index 4fd7c2cc2f06..1eb286290127 100644 --- a/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js +++ b/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js @@ -10,7 +10,7 @@ import expect from '@kbn/expect'; import mockRolledUpData, { mockIndices } from './hybrid_index_helper'; export default function ({ getService, getPageObjects }) { - const es = getService('legacyEs'); + const es = getService('es'); const esArchiver = getService('esArchiver'); const find = getService('find'); const retry = getService('retry'); @@ -43,7 +43,7 @@ export default function ({ getService, getPageObjects }) { 'waiting for 3 records to be loaded into elasticsearch.', 10000, async () => { - const response = await es.indices.get({ + const { body: response } = await es.indices.get({ index: `${rollupSourceIndexPrefix}*`, allow_no_indices: false, }); @@ -53,9 +53,8 @@ export default function ({ getService, getPageObjects }) { await retry.try(async () => { //Create a rollup for kibana to recognize - await es.transport.request({ - path: `/_rollup/job/${rollupJobName}`, - method: 'PUT', + await es.rollup.putJob({ + id: rollupJobName, body: { index_pattern: `${rollupSourceIndexPrefix}*`, rollup_index: rollupTargetIndexName, @@ -104,10 +103,7 @@ export default function ({ getService, getPageObjects }) { after(async () => { // Delete the rollup job. - await es.transport.request({ - path: `/_rollup/job/${rollupJobName}`, - method: 'DELETE', - }); + await es.rollup.deleteJob({ id: rollupJobName }); await esDeleteAllIndices([ rollupTargetIndexName, diff --git a/x-pack/test/functional/apps/rollup_job/rollup_jobs.js b/x-pack/test/functional/apps/rollup_job/rollup_jobs.js index 60a878f343c5..a0684a77748b 100644 --- a/x-pack/test/functional/apps/rollup_job/rollup_jobs.js +++ b/x-pack/test/functional/apps/rollup_job/rollup_jobs.js @@ -10,7 +10,7 @@ import expect from '@kbn/expect'; import { mockIndices } from './hybrid_index_helper'; export default function ({ getService, getPageObjects }) { - const es = getService('legacyEs'); + const es = getService('es'); const esArchiver = getService('esArchiver'); const PageObjects = getPageObjects(['rollup', 'common', 'security']); const security = getService('security'); diff --git a/x-pack/test/functional/apps/rollup_job/tsvb.js b/x-pack/test/functional/apps/rollup_job/tsvb.js index aebea93f1e4b..d0c7c86d6d5c 100644 --- a/x-pack/test/functional/apps/rollup_job/tsvb.js +++ b/x-pack/test/functional/apps/rollup_job/tsvb.js @@ -9,7 +9,7 @@ import expect from '@kbn/expect'; import mockRolledUpData from './hybrid_index_helper'; export default function ({ getService, getPageObjects }) { - const es = getService('legacyEs'); + const es = getService('es'); const esArchiver = getService('esArchiver'); const retry = getService('retry'); const esDeleteAllIndices = getService('esDeleteAllIndices'); @@ -49,9 +49,8 @@ export default function ({ getService, getPageObjects }) { await retry.try(async () => { //Create a rollup for kibana to recognize - await es.transport.request({ - path: `/_rollup/job/${rollupJobName}`, - method: 'PUT', + await es.rollup.putJob({ + id: rollupJobName, body: { index_pattern: rollupSourceIndexName, rollup_index: rollupTargetIndexName, From 5071192d171de88e6ffee75329a2ff810ac728c1 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Fri, 9 Apr 2021 01:45:53 +0200 Subject: [PATCH 49/49] [Ingest Pipelines] Add generated copy for all processors (#95507) (#96659) * - minor refactor of 'description' -> 'typeDescription' for generic processor descriptions - added initial pass of generated descriptions for all processors * fix i18n * added wrapping div and title to description and changed default description to appear as placeholder * reworked the description width and overflow styling * only show the text title on hover when we are not showing the text input * fixed a number of minor issues with using values as though they are strings and doing better serialization * slight optimisation to scss * - implement copy feedback - clean up a lot of uses of "target_field = field". it is better to not show these - made "replacement" a required field on gsub (which it was not) * revert the previouis validation as empty values are acceptbale for the replacement text * - updated the copy per feedback and fixed a missing i18n.translate - slight update to SCSS classes to not have unused class * Added an empty string field validator that accepts spaces so that the KV processor value and field split fields accept " " * replace use of HTML "title" with EuiToolTip * remove unused variable and import * implemented feedback; removed if from default descriptions and other minor updates * update default description of foreach to always display Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../inline_text_input.tsx | 14 +- .../pipeline_processors_editor_item.scss | 20 +- .../pipeline_processors_editor_item.tsx | 30 +- .../common_fields/processor_type_field.tsx | 2 +- .../processor_form/processors/kv.tsx | 9 +- .../processor_form/processors/shared.ts | 18 +- .../shared/map_processor_type_to_form.tsx | 384 +++++++++++++++--- 7 files changed, 404 insertions(+), 73 deletions(-) diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/inline_text_input.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/inline_text_input.tsx index 1e10d650bed2..cd7c91685467 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/inline_text_input.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/inline_text_input.tsx @@ -7,7 +7,7 @@ import classNames from 'classnames'; import React, { useState, useEffect, useCallback, memo } from 'react'; -import { EuiFieldText, EuiText, keys } from '@elastic/eui'; +import { EuiFieldText, EuiText, keys, EuiToolTip } from '@elastic/eui'; export interface Props { placeholder: string; @@ -90,11 +90,13 @@ function _InlineTextInput({ tabIndex={disabled ? -1 : 0} onFocus={() => setIsShowingTextInput(true)} > - -
    - {text || {placeholder}} -
    -
    + + +
    + {text || {placeholder}} +
    +
    +

fIKVGvLrvqS|Pm_G$0!V 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 diff --git a/docs/user/security/images/tutorial-secure-access-example-1-role.png b/docs/user/security/images/tutorial-secure-access-example-1-role.png new file mode 100644 index 0000000000000000000000000000000000000000..53540da7170ea654b17fb290baa2a95d25764607 GIT binary patch literal 320953 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 l360EHx`iXf96 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�h(2}lV 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 literal 0 HcmV?d00001 diff --git a/docs/user/security/images/tutorial-secure-access-example-1-space.png b/docs/user/security/images/tutorial-secure-access-example-1-space.png new file mode 100644 index 0000000000000000000000000000000000000000..a48fdeaa6efa1f6867395868bd47c7046845b95b GIT binary patch literal 328089 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�?Q{_n~Eb*TP#SpG-j`Trf3=ruU1A+QK*FeZ8J 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

); } diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.scss b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.scss index d51dee31e9f8..ff78296a6043 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.scss +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.scss @@ -38,7 +38,6 @@ overflow-x: hidden; white-space: nowrap; text-overflow: ellipsis; - max-width: 600px; } &__textInput { @@ -60,4 +59,23 @@ // Prevent content jump when spinner renders min-width: 15px; } + + &__controlsContainer { + // Make sure this element knows how wide it is + width: 100%; + // The last element in these controls is an editable text description that can contain an unknown amount (i.e., width) of text. + overflow: hidden; + } + + // By default, flex sets the element width to "auto", we set this explicitly again to avoid the flex item growing beyond the width given + // by flex. This applies to both of the classes below. + &__controlsFlexItem { + min-width: 0; + } + &__descriptionContainer { + min-width: 0; + &--displayNone { + display: none; + } + } } diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx index 320f99acd08f..1ba883990ce1 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx @@ -67,6 +67,8 @@ export const PipelineProcessorsEditorItem: FunctionComponent = memo( const isMovingOtherProcessor = editor.mode.id === 'movingProcessor' && !isMovingThisProcessor; const isDimmed = isEditingOtherProcessor || isMovingOtherProcessor; + const processorDescriptor = getProcessorDescriptor(processor.type); + const { testPipelineData } = useTestPipelineContext(); const { config: { selectedDocumentIndex }, @@ -85,10 +87,14 @@ export const PipelineProcessorsEditorItem: FunctionComponent = memo( 'pipelineProcessorsEditor__item--dimmed': isDimmed, }); - const inlineTextInputContainerClasses = classNames({ - // eslint-disable-next-line @typescript-eslint/naming-convention - 'pipelineProcessorsEditor__item--displayNone': isInMoveMode && !processor.options.description, - }); + const inlineTextInputContainerClasses = classNames( + 'pipelineProcessorsEditor__item__descriptionContainer', + { + // eslint-disable-next-line @typescript-eslint/naming-convention + 'pipelineProcessorsEditor__item__descriptionContainer--displayNone': + isInMoveMode && !processor.options.description, + } + ); const onDescriptionChange = useCallback( (nextDescription) => { @@ -167,8 +173,13 @@ export const PipelineProcessorsEditorItem: FunctionComponent = memo( data-test-subj={selectorToDataTestSubject(selector)} data-processor-id={processor.id} > - - + + {renderMoveButton()} {isExecutingPipeline ? ( @@ -193,7 +204,7 @@ export const PipelineProcessorsEditorItem: FunctionComponent = memo( }} data-test-subj="manageItemButton" > - {getProcessorDescriptor(processor.type)?.label ?? processor.type} + {processorDescriptor?.label ?? processor.type} @@ -203,7 +214,10 @@ export const PipelineProcessorsEditorItem: FunctionComponent = memo( onChange={onDescriptionChange} ariaLabel={i18nTexts.processorTypeLabel({ type: processor.type })} text={description} - placeholder={i18nTexts.descriptionPlaceholder} + placeholder={ + processorDescriptor?.getDefaultDescription(processor.options) ?? + i18nTexts.descriptionPlaceholder + } /> diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/common_fields/processor_type_field.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/common_fields/processor_type_field.tsx index 25d3e5307304..1160038b52af 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/common_fields/processor_type_field.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/common_fields/processor_type_field.tsx @@ -81,7 +81,7 @@ export const ProcessorTypeField: FunctionComponent = ({ initialType }) => const type = typeField.value; const processorDescriptor = getProcessorDescriptor(type); if (processorDescriptor) { - description = processorDescriptor.description || ''; + description = processorDescriptor.typeDescription || ''; selectedOptions = [{ label: processorDescriptor.label, value: type }]; } else { // If there is no label for this processor type, just use the type as the label diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/kv.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/kv.tsx index 694ae4e07070..0c8a6ee9c9e2 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/kv.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/kv.tsx @@ -12,20 +12,17 @@ import { EuiCode } from '@elastic/eui'; import { FIELD_TYPES, - fieldValidators, UseField, Field, ComboBoxField, ToggleField, } from '../../../../../../shared_imports'; -import { FieldsConfig, from, to } from './shared'; +import { FieldsConfig, from, to, isEmptyString } from './shared'; import { FieldNameField } from './common_fields/field_name_field'; import { TargetField } from './common_fields/target_field'; import { IgnoreMissingField } from './common_fields/ignore_missing_field'; -const { emptyField } = fieldValidators; - const fieldsConfig: FieldsConfig = { /* Required fields config */ field_split: { @@ -45,7 +42,7 @@ const fieldsConfig: FieldsConfig = { ), validations: [ { - validator: emptyField( + validator: isEmptyString( i18n.translate('xpack.ingestPipelines.pipelineEditor.kvForm.fieldSplitRequiredError', { defaultMessage: 'A value is required.', }) @@ -70,7 +67,7 @@ const fieldsConfig: FieldsConfig = { ), validations: [ { - validator: emptyField( + validator: isEmptyString( i18n.translate('xpack.ingestPipelines.pipelineEditor.kvForm.valueSplitRequiredError', { defaultMessage: 'A value is required.', }) diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/shared.ts b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/shared.ts index bafba412c767..9a45f7f0017c 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/shared.ts +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/shared.ts @@ -10,7 +10,9 @@ import * as rt from 'io-ts'; import { i18n } from '@kbn/i18n'; import { isRight } from 'fp-ts/lib/Either'; -import { FieldConfig, ValidationFunc } from '../../../../../../shared_imports'; +import { FieldConfig, ValidationFunc, fieldValidators } from '../../../../../../shared_imports'; + +const { emptyField } = fieldValidators; export const arrayOfStrings = rt.array(rt.string); @@ -118,6 +120,20 @@ export const isJSONStringValidator: ValidationFunc = ({ value }) => { } }; +/** + * Similar to the emptyField validator but we accept whitespace characters. + */ +export const isEmptyString = (message: string): ValidationFunc => (field) => { + const { value } = field; + if (typeof value === 'string') { + const hasLength = Boolean(value.length); + const hasNonWhiteSpaceChars = hasLength && Boolean(value.trim().length); + if (hasNonWhiteSpaceChars) { + return emptyField(message)(field); + } + } +}; + export const EDITOR_PX_HEIGHT = { extraSmall: 75, small: 100, diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/shared/map_processor_type_to_form.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/shared/map_processor_type_to_form.tsx index 9095ab1927cb..5ab2d68aa193 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/shared/map_processor_type_to_form.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/shared/map_processor_type_to_form.tsx @@ -56,7 +56,14 @@ interface FieldDescriptor { * A sentence case label that can be displayed to users */ label: string; - description?: string | ((esDocUrl: string) => ReactNode); + /** + * A general description of the processor type + */ + typeDescription?: string | ((esDocUrl: string) => ReactNode); + /** + * Default + */ + getDefaultDescription: (processorOptions: Record) => string | undefined; } type MapProcessorTypeToDescriptor = Record; @@ -68,10 +75,18 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.append', { defaultMessage: 'Append', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.append', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.append', { defaultMessage: "Appends values to a field's array. If the field contains a single value, the processor first converts it to an array. If the field doesn't exist, the processor creates an array containing the appended values.", }), + getDefaultDescription: ({ field, value }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.append', { + defaultMessage: 'Appends "{value}" to the "{field}" field', + values: { + field, + value, + }, + }), }, bytes: { FieldsComponent: Bytes, @@ -79,10 +94,17 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.bytes', { defaultMessage: 'Bytes', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.bytes', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.bytes', { defaultMessage: 'Converts digital storage units to bytes. For example, 1KB becomes 1024 bytes.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.bytes', { + defaultMessage: 'Converts "{field}" to its value in bytes', + values: { + field, + }, + }), }, circle: { FieldsComponent: Circle, @@ -90,9 +112,16 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.circle', { defaultMessage: 'Circle', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.circle', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.circle', { defaultMessage: 'Converts a circle definition into an approximate polygon.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.circle', { + defaultMessage: 'Converts a circle definition of "{field}" into an approximate polygon', + values: { + field, + }, + }), }, convert: { FieldsComponent: Convert, @@ -100,10 +129,18 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.convert', { defaultMessage: 'Convert', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.convert', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.convert', { defaultMessage: 'Converts a field to a different data type. For example, you can convert a string to an long.', }), + getDefaultDescription: ({ field, type }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.convert', { + defaultMessage: 'Converts "{field}" to type "{type}"', + values: { + field, + type, + }, + }), }, csv: { FieldsComponent: CSV, @@ -111,9 +148,17 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.csv', { defaultMessage: 'CSV', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.csv', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.csv', { defaultMessage: 'Extracts field values from CSV data.', }), + getDefaultDescription: ({ field, target_fields: targetFields }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.csv', { + defaultMessage: 'Extracts CSV values from "{field}" to {target_fields}', + values: { + field, + target_fields: targetFields.map((v: string) => `"${v}"`).join(', '), + }, + }), }, date: { FieldsComponent: DateProcessor, @@ -121,9 +166,17 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.date', { defaultMessage: 'Date', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.date', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.date', { defaultMessage: 'Converts a date to a document timestamp.', }), + getDefaultDescription: ({ field, target_field: targetField = '@timestamp' }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.date', { + defaultMessage: 'Parses a date from "{field}" to a date type on field "{target_field}"', + values: { + field, + target_field: targetField, + }, + }), }, date_index_name: { FieldsComponent: DateIndexName, @@ -131,13 +184,32 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.dateIndexName', { defaultMessage: 'Date index name', }), - description: () => ( + typeDescription: () => ( {'my-index-yyyy-MM-dd'} }} /> ), + getDefaultDescription: ({ field, index_name_prefix: indexNamePrefix }) => { + const prefix = indexNamePrefix + ? i18n.translate( + 'xpack.ingestPipelines.processors.defaultDescription.dateIndexName.indexNamePrefixDefault.prefixValueLabel', + { defaultMessage: 'with the prefix "{prefix}"', values: { prefix: indexNamePrefix } } + ) + : i18n.translate( + 'xpack.ingestPipelines.processors.defaultDescription.dateIndexName.indexNamePrefixDefault.noPrefixValueLabel', + { defaultMessage: 'with no prefix' } + ); + return i18n.translate('xpack.ingestPipelines.processors.defaultDescription.date_index_name', { + defaultMessage: + 'Adds documents to a time-based index based on the timestamp value in "{field}", {prefix}', + values: { + field, + prefix, + }, + }); + }, }, dissect: { FieldsComponent: Dissect, @@ -145,9 +217,16 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.dissect', { defaultMessage: 'Dissect', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.dissect', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.dissect', { defaultMessage: 'Uses dissect patterns to extract matches from a field.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.dissect', { + defaultMessage: 'Extracts values from "{field}" that match a dissect pattern', + values: { + field, + }, + }), }, dot_expander: { FieldsComponent: DotExpander, @@ -155,10 +234,17 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.dotExpander', { defaultMessage: 'Dot expander', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.dotExpander', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.dotExpander', { defaultMessage: 'Expands a field containing dot notation into an object field. The object field is then accessible by other processors in the pipeline.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.dot_expander', { + defaultMessage: 'Expands "{field}" into an object field', + values: { + field, + }, + }), }, drop: { FieldsComponent: Drop, @@ -166,10 +252,13 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.drop', { defaultMessage: 'Drop', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.drop', { - defaultMessage: - 'Drops documents without returning an error. Used to only index documents that meet specified conditions.', + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.drop', { + defaultMessage: 'Drops documents without returning an error.', }), + getDefaultDescription: () => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.drop', { + defaultMessage: 'Drops documents without returning an error', + }), }, enrich: { FieldsComponent: Enrich, @@ -177,7 +266,7 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.enrich', { defaultMessage: 'Enrich', }), - description: (esDocUrl) => { + typeDescription: (esDocUrl) => { return ( ); }, + getDefaultDescription: ({ field, policy_name: policyName, target_field: targetField }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.enrich', { + defaultMessage: + 'Enriches data to "{target_field}" if the "{policy_name}" policy matches "{field}"', + values: { + field, + policy_name: policyName, + target_field: targetField, + }, + }), }, fail: { FieldsComponent: Fail, @@ -199,10 +298,14 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.fail', { defaultMessage: 'Fail', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.fail', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.fail', { defaultMessage: 'Returns a custom error message on failure. Often used to notify requesters of required conditions.', }), + getDefaultDescription: () => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.fail', { + defaultMessage: 'Raises an exception that halts execution', + }), }, foreach: { FieldsComponent: Foreach, @@ -210,9 +313,16 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.foreach', { defaultMessage: 'Foreach', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.foreach', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.foreach', { defaultMessage: 'Applies an ingest processor to each value in an array.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.foreach', { + defaultMessage: 'Runs a processor for each object in "{field}"', + values: { + field, + }, + }), }, geoip: { FieldsComponent: GeoIP, @@ -220,10 +330,17 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.geoip', { defaultMessage: 'GeoIP', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.geoip', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.geoip', { defaultMessage: 'Adds geo data based on an IP address. Uses geo data from a Maxmind database file.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.geoip', { + defaultMessage: 'Adds geo data to documents based on the value of "{field}"', + values: { + field, + }, + }), }, grok: { FieldsComponent: Grok, @@ -231,7 +348,7 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.grok', { defaultMessage: 'Grok', }), - description: (esDocUrl) => { + typeDescription: (esDocUrl) => { return ( ); }, + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.grok', { + defaultMessage: 'Extracts values from "{field}" that match a grok pattern', + values: { + field, + }, + }), }, gsub: { FieldsComponent: Gsub, @@ -253,9 +377,18 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.gsub', { defaultMessage: 'Gsub', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.gsub', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.gsub', { defaultMessage: 'Uses a regular expression to replace field substrings.', }), + getDefaultDescription: ({ pattern, field, replacement }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.gsub', { + defaultMessage: 'Replaces values matching "{pattern}" in "{field}" with "{replacement}"', + values: { + pattern, + field, + replacement, + }, + }), }, html_strip: { FieldsComponent: HtmlStrip, @@ -263,9 +396,16 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.htmlStrip', { defaultMessage: 'HTML strip', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.htmlStrip', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.htmlStrip', { defaultMessage: 'Removes HTML tags from a field.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.html_strip', { + defaultMessage: 'Removes HTML tags from "{field}"', + values: { + field, + }, + }), }, inference: { FieldsComponent: Inference, @@ -273,10 +413,21 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.inference', { defaultMessage: 'Inference', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.inference', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.inference', { defaultMessage: 'Uses a pre-trained data frame analytics model to infer against incoming data.', }), + getDefaultDescription: ({ + model_id: modelId, + target_field: targetField = 'ml.inference.', + }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.inference', { + defaultMessage: 'Runs the model "{modelId}" and stores the result in "{target_field}"', + values: { + modelId, + target_field: targetField, + }, + }), }, join: { FieldsComponent: Join, @@ -284,10 +435,17 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.join', { defaultMessage: 'Join', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.join', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.join', { defaultMessage: 'Joins array elements into a string. Inserts a separator between each element.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.join', { + defaultMessage: 'Joins each element of the array stored in "{field}"', + values: { + field, + }, + }), }, json: { FieldsComponent: Json, @@ -295,9 +453,16 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.json', { defaultMessage: 'JSON', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.json', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.json', { defaultMessage: 'Creates a JSON object from a compatible string.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.json', { + defaultMessage: 'Parses "{field}" to create a JSON object from a string', + values: { + field, + }, + }), }, kv: { FieldsComponent: Kv, @@ -305,9 +470,19 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.kv', { defaultMessage: 'Key-value (KV)', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.kv', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.kv', { defaultMessage: 'Extracts fields from a string containing key-value pairs.', }), + getDefaultDescription: ({ field, field_split: fieldSplit, value_split: valueSplit }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.kv', { + defaultMessage: + 'Extracts key-value pairs from "{field}" and splits on "{field_split}" and "{value_split}"', + values: { + field, + field_split: fieldSplit, + value_split: valueSplit, + }, + }), }, lowercase: { FieldsComponent: Lowercase, @@ -315,9 +490,16 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.lowercase', { defaultMessage: 'Lowercase', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.lowercase', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.lowercase', { defaultMessage: 'Converts a string to lowercase.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.lowercase', { + defaultMessage: 'Converts values in "{field}" to lowercase', + values: { + field, + }, + }), }, pipeline: { FieldsComponent: Pipeline, @@ -325,9 +507,16 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.pipeline', { defaultMessage: 'Pipeline', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.pipeline', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.pipeline', { defaultMessage: 'Runs another ingest node pipeline.', }), + getDefaultDescription: ({ name }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.pipeline', { + defaultMessage: 'Runs the "{name}" ingest pipeline', + values: { + name, + }, + }), }, remove: { FieldsComponent: Remove, @@ -335,9 +524,16 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.remove', { defaultMessage: 'Remove', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.remove', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.remove', { defaultMessage: 'Removes one or more fields.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.remove', { + defaultMessage: 'Removes "{field}"', + values: { + field: Array.isArray(field) ? field.map((v) => `"${v}"`).join(', ') : field, + }, + }), }, rename: { FieldsComponent: Rename, @@ -345,9 +541,17 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.rename', { defaultMessage: 'Rename', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.rename', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.rename', { defaultMessage: 'Renames an existing field.', }), + getDefaultDescription: ({ field, target_field: targetField }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.rename', { + defaultMessage: 'Renames "{field}" to "{target_field}"', + values: { + field, + target_field: targetField, + }, + }), }, script: { FieldsComponent: Script, @@ -355,9 +559,10 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.script', { defaultMessage: 'Script', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.script', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.script', { defaultMessage: 'Runs a script on incoming documents.', }), + getDefaultDescription: () => 'Runs a script on incoming documents', }, set: { FieldsComponent: SetProcessor, @@ -365,9 +570,17 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.set', { defaultMessage: 'Set', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.set', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.set', { defaultMessage: 'Sets the value of a field.', }), + getDefaultDescription: ({ field, value }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.set', { + defaultMessage: 'Sets value of "{field}" to "{value}"', + values: { + field, + value, + }, + }), }, set_security_user: { FieldsComponent: SetSecurityUser, @@ -375,10 +588,18 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.setSecurityUser', { defaultMessage: 'Set security user', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.setSecurityUser', { - defaultMessage: - 'Adds details about the current user, such user name and email address, to incoming documents. Requires an authenticated user for the indexing request.', - }), + typeDescription: i18n.translate( + 'xpack.ingestPipelines.processors.description.setSecurityUser', + { + defaultMessage: + 'Adds details about the current user, such user name and email address, to incoming documents. Requires an authenticated user for the indexing request.', + } + ), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.setSecurityUser', { + defaultMessage: 'Adds details about the current user to "{field}"', + values: { field }, + }), }, sort: { FieldsComponent: Sort, @@ -386,9 +607,26 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.sort', { defaultMessage: 'Sort', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.sort', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.sort', { defaultMessage: "Sorts a field's array elements.", }), + getDefaultDescription: ({ field, order = 'asc' }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.sort', { + defaultMessage: 'Sorts elements in the array "{field}" in {order} order', + values: { + field, + order: + order === 'asc' + ? i18n.translate( + 'xpack.ingestPipelines.processors.defaultDescription.sort.orderAscendingLabel', + { defaultMessage: 'ascending' } + ) + : i18n.translate( + 'xpack.ingestPipelines.processors.defaultDescription.sort.orderDescendingLabel', + { defaultMessage: 'descending' } + ), + }, + }), }, split: { FieldsComponent: Split, @@ -396,9 +634,16 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.split', { defaultMessage: 'Split', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.split', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.split', { defaultMessage: 'Splits a field value into an array.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.split', { + defaultMessage: 'Splits the string stored in "{field}" to an array', + values: { + field, + }, + }), }, trim: { FieldsComponent: Trim, @@ -406,9 +651,16 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.trim', { defaultMessage: 'Trim', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.trim', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.trim', { defaultMessage: 'Removes leading and trailing whitespace from a string.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.trim', { + defaultMessage: 'Trims whitespaces from "{field}"', + values: { + field, + }, + }), }, uppercase: { FieldsComponent: Uppercase, @@ -416,9 +668,16 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.uppercase', { defaultMessage: 'Uppercase', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.uppercase', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.uppercase', { defaultMessage: 'Converts a string to uppercase.', }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.uppercase', { + defaultMessage: 'Converts values in "{field}" to uppercase', + values: { + field, + }, + }), }, urldecode: { FieldsComponent: UrlDecode, @@ -426,19 +685,16 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.urldecode', { defaultMessage: 'URL decode', }), - description: i18n.translate('xpack.ingestPipelines.processors.description.urldecode', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.urldecode', { defaultMessage: 'Decodes a URL-encoded string.', }), - }, - user_agent: { - FieldsComponent: UserAgent, - docLinkPath: '/user-agent-processor.html', - label: i18n.translate('xpack.ingestPipelines.processors.label.userAgent', { - defaultMessage: 'User agent', - }), - description: i18n.translate('xpack.ingestPipelines.processors.description.userAgent', { - defaultMessage: "Extracts values from a browser's user agent string.", - }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.url_decode', { + defaultMessage: 'Decodes the URL in "{field}"', + values: { + field, + }, + }), }, uri_parts: { FieldsComponent: UriParts, @@ -446,10 +702,38 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { label: i18n.translate('xpack.ingestPipelines.processors.label.uriPartsLabel', { defaultMessage: 'URI parts', }), - description: i18n.translate('xpack.ingestPipelines.processors.uriPartsDescription', { + typeDescription: i18n.translate('xpack.ingestPipelines.processors.uriPartsDescription', { defaultMessage: 'Parses a Uniform Resource Identifier (URI) string and extracts its components as an object.', }), + getDefaultDescription: ({ field, target_field: targetField = 'url' }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.uri_parts', { + defaultMessage: + 'Parses the URI string in "{field}" and stores the result in "{target_field}"', + values: { + field, + target_field: targetField, + }, + }), + }, + user_agent: { + FieldsComponent: UserAgent, + docLinkPath: '/user-agent-processor.html', + label: i18n.translate('xpack.ingestPipelines.processors.label.userAgent', { + defaultMessage: 'User agent', + }), + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.userAgent', { + defaultMessage: "Extracts values from a browser's user agent string.", + }), + getDefaultDescription: ({ field, target_field: targetField = 'user_agent' }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.user_agent', { + defaultMessage: + 'Extracts the user agent from "{field}" and stores the results in "{target_field}"', + values: { + field, + target_field: targetField, + }, + }), }, };