diff --git a/.browserslistrc b/.browserslistrc index 04395b913c9c..36298c0f8cb9 100644 --- a/.browserslistrc +++ b/.browserslistrc @@ -4,6 +4,8 @@ last 2 Chrome versions last 2 Safari versions > 0.25% not ie 11 +not op_mini all +not samsung 4 [dev] last 1 chrome versions diff --git a/.github/ISSUE_TEMPLATE/v8_breaking_change.md b/.github/ISSUE_TEMPLATE/v8_breaking_change.md index c91b937586a0..42783808e32e 100644 --- a/.github/ISSUE_TEMPLATE/v8_breaking_change.md +++ b/.github/ISSUE_TEMPLATE/v8_breaking_change.md @@ -7,6 +7,16 @@ assignees: '' --- + + ## Change description **Which release will ship the breaking change?** diff --git a/docs/development/core/server/kibana-plugin-core-server.kibanarequest.md b/docs/development/core/server/kibana-plugin-core-server.kibanarequest.md index 1134994faa9b..4129662acb2b 100644 --- a/docs/development/core/server/kibana-plugin-core-server.kibanarequest.md +++ b/docs/development/core/server/kibana-plugin-core-server.kibanarequest.md @@ -30,9 +30,9 @@ export declare class KibanaRequestboolean | Whether or not the request is a "system request" rather than an application-level request. Can be set on the client using the HttpFetchOptions#asSystemRequest option. | | [params](./kibana-plugin-core-server.kibanarequest.params.md) | | Params | | | [query](./kibana-plugin-core-server.kibanarequest.query.md) | | Query | | -| [rewrittenUrl](./kibana-plugin-core-server.kibanarequest.rewrittenurl.md) | | Url | URL rewritten in onPreRouting request interceptor. | +| [rewrittenUrl](./kibana-plugin-core-server.kibanarequest.rewrittenurl.md) | | URL | URL rewritten in onPreRouting request interceptor. | | [route](./kibana-plugin-core-server.kibanarequest.route.md) | | RecursiveReadonly<KibanaRequestRoute<Method>> | matched route details | | [socket](./kibana-plugin-core-server.kibanarequest.socket.md) | | IKibanaSocket | [IKibanaSocket](./kibana-plugin-core-server.ikibanasocket.md) | -| [url](./kibana-plugin-core-server.kibanarequest.url.md) | | Url | a WHATWG URL standard object. | +| [url](./kibana-plugin-core-server.kibanarequest.url.md) | | URL | a WHATWG URL standard object. | | [uuid](./kibana-plugin-core-server.kibanarequest.uuid.md) | | string | A UUID to identify this request. | diff --git a/docs/development/core/server/kibana-plugin-core-server.kibanarequest.rewrittenurl.md b/docs/development/core/server/kibana-plugin-core-server.kibanarequest.rewrittenurl.md index 10628bafaf1d..fb547330ee6e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.kibanarequest.rewrittenurl.md +++ b/docs/development/core/server/kibana-plugin-core-server.kibanarequest.rewrittenurl.md @@ -9,5 +9,5 @@ URL rewritten in onPreRouting request interceptor. Signature: ```typescript -readonly rewrittenUrl?: Url; +readonly rewrittenUrl?: URL; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.kibanarequest.url.md b/docs/development/core/server/kibana-plugin-core-server.kibanarequest.url.md index 31d134819720..b72760e272bb 100644 --- a/docs/development/core/server/kibana-plugin-core-server.kibanarequest.url.md +++ b/docs/development/core/server/kibana-plugin-core-server.kibanarequest.url.md @@ -9,5 +9,5 @@ a WHATWG URL standard object. Signature: ```typescript -readonly url: Url; +readonly url: URL; ``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrenderer.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrenderer.md index 66c2e1e3c0c8..32a715157865 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrenderer.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrenderer.md @@ -7,5 +7,5 @@ Signature: ```typescript -ReactExpressionRenderer: ({ className, dataAttrs, padding, renderError, expression, onEvent, reload$, ...expressionLoaderOptions }: ReactExpressionRendererProps) => JSX.Element +ReactExpressionRenderer: ({ className, dataAttrs, padding, renderError, expression, onEvent, reload$, debounce, ...expressionLoaderOptions }: ReactExpressionRendererProps) => JSX.Element ``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.debounce.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.debounce.md new file mode 100644 index 000000000000..3f7eb12fbb7a --- /dev/null +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.debounce.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-expressions-public](./kibana-plugin-plugins-expressions-public.md) > [ReactExpressionRendererProps](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md) > [debounce](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.debounce.md) + +## ReactExpressionRendererProps.debounce property + +Signature: + +```typescript +debounce?: number; +``` diff --git a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md index 5622516530ed..e4980ce04b9e 100644 --- a/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md +++ b/docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.md @@ -16,6 +16,7 @@ export interface ReactExpressionRendererProps extends IExpressionLoaderParams | --- | --- | --- | | [className](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.classname.md) | string | | | [dataAttrs](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.dataattrs.md) | string[] | | +| [debounce](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.debounce.md) | number | | | [expression](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.expression.md) | string | ExpressionAstExpression | | | [onEvent](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.onevent.md) | (event: ExpressionRendererEvent) => void | | | [padding](./kibana-plugin-plugins-expressions-public.reactexpressionrendererprops.padding.md) | 'xs' | 's' | 'm' | 'l' | 'xl' | | diff --git a/examples/embeddable_explorer/tsconfig.json b/examples/embeddable_explorer/tsconfig.json index 86b35c5e4943..4baebebcea42 100644 --- a/examples/embeddable_explorer/tsconfig.json +++ b/examples/embeddable_explorer/tsconfig.json @@ -9,10 +9,11 @@ "public/**/*.ts", "public/**/*.tsx", "server/**/*.ts", - "../../typings/**/*", + "../../typings/**/*" ], "exclude": [], "references": [ - { "path": "../../src/core/tsconfig.json" } + { "path": "../../src/core/tsconfig.json" }, + { "path": "../../src/plugins/inspector/tsconfig.json" } ] } diff --git a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap index cb5bb1e8fc52..ddb19c8cdc3d 100644 --- a/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap +++ b/packages/kbn-optimizer/src/integration_tests/__snapshots__/basic_optimization.test.ts.snap @@ -108,4 +108,4 @@ exports[`prepares assets for distribution: baz bundle 1`] = ` exports[`prepares assets for distribution: foo async bundle 1`] = `"(window[\\"foo_bundle_jsonpfunction\\"]=window[\\"foo_bundle_jsonpfunction\\"]||[]).push([[1],{3:function(module,__webpack_exports__,__webpack_require__){\\"use strict\\";__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__,\\"foo\\",(function(){return foo}));function foo(){}}}]);"`; -exports[`prepares assets for distribution: foo bundle 1`] = `"(function(modules){function webpackJsonpCallback(data){var chunkIds=data[0];var moreModules=data[1];var moduleId,chunkId,i=0,resolves=[];for(;i = { * Returns an object with public methods only. */ export type PublicMethodsOf = Pick>; + +/** + * Makes an object with readonly properties mutable. + */ +export type Writable = { + -readonly [K in keyof T]: T[K]; +}; diff --git a/src/core/typings.ts b/packages/kbn-utility-types/jest/index.ts similarity index 99% rename from src/core/typings.ts rename to packages/kbn-utility-types/jest/index.ts index fe182ddfb131..8b3d926b8e8d 100644 --- a/src/core/typings.ts +++ b/packages/kbn-utility-types/jest/index.ts @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - export type DeeplyMockedKeys = { [P in keyof T]: T[P] extends (...args: any[]) => any ? jest.MockInstance, Parameters> diff --git a/packages/kbn-utility-types/jest/package.json b/packages/kbn-utility-types/jest/package.json new file mode 100644 index 000000000000..9f92fc5e9452 --- /dev/null +++ b/packages/kbn-utility-types/jest/package.json @@ -0,0 +1,3 @@ +{ + "types": "../target/jest/index.d.ts" +} diff --git a/packages/kbn-utility-types/test-d/method_keys_of.ts b/packages/kbn-utility-types/test-d/method_keys_of.ts new file mode 100644 index 000000000000..46cb17122f41 --- /dev/null +++ b/packages/kbn-utility-types/test-d/method_keys_of.ts @@ -0,0 +1,34 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { expectType } from 'tsd'; +import { MethodKeysOf } from '../index'; + +class Test { + public name: string = ''; + getName() { + return this.name; + } + // @ts-ignore + private getDoubleName() { + return this.name.repeat(2); + } +} + +expectType>('getName'); diff --git a/packages/kbn-utility-types/test-d/public_methods_of.ts b/packages/kbn-utility-types/test-d/public_methods_of.ts new file mode 100644 index 000000000000..3f5d442342b1 --- /dev/null +++ b/packages/kbn-utility-types/test-d/public_methods_of.ts @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { expectAssignable, expectNotAssignable } from 'tsd'; +import { PublicMethodsOf } from '../index'; + +class Test { + public name: string = ''; + getName() { + return this.name; + } + // @ts-ignore + private getDoubleName() { + return this.name.repeat(2); + } +} + +expectAssignable>({ + getName() { + return ''; + }, +}); + +expectNotAssignable>({ + getName() { + return 1; + }, +}); + +expectNotAssignable>({ + getDoubleName() { + return 1; + }, +}); diff --git a/packages/kbn-utility-types/test-d/writable.ts b/packages/kbn-utility-types/test-d/writable.ts new file mode 100644 index 000000000000..0771fa926c4e --- /dev/null +++ b/packages/kbn-utility-types/test-d/writable.ts @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { expectAssignable } from 'tsd'; +import { Writable } from '../index'; + +type WritableArray = Writable; +expectAssignable(['1']); + +type WritableObject = Writable<{ + readonly name: string; +}>; +expectAssignable({ name: '1' }); diff --git a/packages/kbn-utility-types/tsconfig.json b/packages/kbn-utility-types/tsconfig.json index 79cf423fe78a..c2d206526e6f 100644 --- a/packages/kbn-utility-types/tsconfig.json +++ b/packages/kbn-utility-types/tsconfig.json @@ -7,10 +7,11 @@ "stripInternal": true, "declarationMap": true, "types": [ - "node" + "node", + "jest" ] }, - "include": ["index.ts", "test-d/**/*"], + "include": ["index.ts", "jest/**/*", "test-d/**/*"], "exclude": [ "target" ] diff --git a/src/core/public/apm_system.test.ts b/src/core/public/apm_system.test.ts index 8467076c3154..be1cb6dc6820 100644 --- a/src/core/public/apm_system.test.ts +++ b/src/core/public/apm_system.test.ts @@ -18,8 +18,8 @@ */ jest.mock('@elastic/apm-rum'); +import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; import { init, apm } from '@elastic/apm-rum'; -import { DeeplyMockedKeys } from '../typings'; import { ApmSystem } from './apm_system'; const initMock = init as jest.Mocked; diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index 683d15328818..cbcd23615d34 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -18,7 +18,7 @@ */ import { BehaviorSubject } from 'rxjs'; import type { PublicMethodsOf } from '@kbn/utility-types'; -import { DeeplyMockedKeys } from '../../typings'; +import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; import { ChromeBadge, ChromeBrand, ChromeBreadcrumb, ChromeService, InternalChromeStart } from './'; const createStartContractMock = () => { diff --git a/src/core/public/notifications/notifications_service.mock.ts b/src/core/public/notifications/notifications_service.mock.ts index 521ce52c90d0..b69b4604d078 100644 --- a/src/core/public/notifications/notifications_service.mock.ts +++ b/src/core/public/notifications/notifications_service.mock.ts @@ -17,7 +17,7 @@ * under the License. */ import type { PublicMethodsOf } from '@kbn/utility-types'; -import { MockedKeys } from '../../typings'; +import type { MockedKeys } from '@kbn/utility-types/jest'; import { NotificationsService, NotificationsSetup, diff --git a/src/core/public/overlays/overlay_service.mock.ts b/src/core/public/overlays/overlay_service.mock.ts index 72a51b0b1418..595813972b8b 100644 --- a/src/core/public/overlays/overlay_service.mock.ts +++ b/src/core/public/overlays/overlay_service.mock.ts @@ -17,7 +17,7 @@ * under the License. */ import type { PublicMethodsOf } from '@kbn/utility-types'; -import { DeeplyMockedKeys } from '../../typings'; +import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; import { OverlayService, OverlayStart } from './overlay_service'; import { overlayBannersServiceMock } from './banners/banners_service.mock'; import { overlayFlyoutServiceMock } from './flyout/flyout_service.mock'; diff --git a/src/core/server/core_context.mock.ts b/src/core/server/core_context.mock.ts index 8bbba586d46f..4df0b2dfb9d8 100644 --- a/src/core/server/core_context.mock.ts +++ b/src/core/server/core_context.mock.ts @@ -18,7 +18,7 @@ */ import { REPO_ROOT } from '@kbn/dev-utils'; -import { DeeplyMockedKeys } from '../typings'; +import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; import { CoreContext } from './core_context'; import { Env, IConfigService } from './config'; import { configServiceMock, getEnvOptions } from './config/mocks'; diff --git a/src/core/server/elasticsearch/client/mocks.ts b/src/core/server/elasticsearch/client/mocks.ts index 260efa40ac43..bedd0e65c5a8 100644 --- a/src/core/server/elasticsearch/client/mocks.ts +++ b/src/core/server/elasticsearch/client/mocks.ts @@ -18,7 +18,7 @@ */ import { Client, ApiResponse } from '@elastic/elasticsearch'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; -import { DeeplyMockedKeys } from '../../../typings'; +import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; import { ElasticsearchClient } from './types'; import { ICustomClusterClient } from './cluster_client'; diff --git a/src/core/server/http/http_server.mocks.ts b/src/core/server/http/http_server.mocks.ts index 6aad232cf42b..d615e799f383 100644 --- a/src/core/server/http/http_server.mocks.ts +++ b/src/core/server/http/http_server.mocks.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import { parse as parseUrl } from 'url'; import { Request } from 'hapi'; import { merge } from 'lodash'; import { Socket } from 'net'; @@ -72,6 +73,7 @@ function createKibanaRequestMock

({ auth = { isAuthenticated: true }, }: RequestFixtureOptions = {}) { const queryString = stringify(query, { sort: false }); + const url = parseUrl(`${path}${queryString ? `?${queryString}` : ''}`); return KibanaRequest.from( createRawRequestMock({ @@ -83,12 +85,7 @@ function createKibanaRequestMock

({ payload: body, path, method, - url: { - path, - pathname: path, - query: queryString, - search: queryString ? `?${queryString}` : queryString, - }, + url, route: { settings: { tags: routeTags, auth: routeAuthRequired, app: kibanaRouteOptions }, }, @@ -121,6 +118,11 @@ interface DeepPartialArray extends Array> {} type DeepPartialObject = { [P in keyof T]+?: DeepPartial }; function createRawRequestMock(customization: DeepPartial = {}) { + const pathname = customization.url?.pathname || '/'; + const path = `${pathname}${customization.url?.search || ''}`; + const url = Object.assign({ pathname, path, href: path }, customization.url); + + // @ts-expect-error _core isn't supposed to be accessed - remove once we upgrade to hapi v18 return merge( {}, { @@ -129,17 +131,21 @@ function createRawRequestMock(customization: DeepPartial = {}) { isAuthenticated: true, }, headers: {}, - path: '/', + path, route: { settings: {} }, - url: { - href: '/', - }, + url, raw: { req: { - url: '/', + url: path, socket: {}, }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, }, customization ) as Request; diff --git a/src/core/server/http/http_server.ts b/src/core/server/http/http_server.ts index 2440f2b1da0b..d94bce12fb43 100644 --- a/src/core/server/http/http_server.ts +++ b/src/core/server/http/http_server.ts @@ -271,7 +271,7 @@ export class HttpServer { } this.registerOnPreRouting((request, response, toolkit) => { - const oldUrl = request.url.href!; + const oldUrl = request.url.pathname + request.url.search; const newURL = basePathService.remove(oldUrl); const shouldRedirect = newURL !== oldUrl; if (shouldRedirect) { diff --git a/src/core/server/http/integration_tests/lifecycle.test.ts b/src/core/server/http/integration_tests/lifecycle.test.ts index 01817b29de8a..37401a2c24cc 100644 --- a/src/core/server/http/integration_tests/lifecycle.test.ts +++ b/src/core/server/http/integration_tests/lifecycle.test.ts @@ -124,7 +124,13 @@ describe('OnPreRouting', () => { const router = createRouter('/'); router.get({ path: '/login', validate: false }, (context, req, res) => { - return res.ok({ body: { rewrittenUrl: req.rewrittenUrl?.path } }); + return res.ok({ + body: { + rewrittenUrl: req.rewrittenUrl + ? `${req.rewrittenUrl.pathname}${req.rewrittenUrl.search}` + : undefined, + }, + }); }); registerOnPreRouting((req, res, t) => t.rewriteUrl('/login')); @@ -143,7 +149,13 @@ describe('OnPreRouting', () => { const router = createRouter('/'); router.get({ path: '/reroute-2', validate: false }, (context, req, res) => { - return res.ok({ body: { rewrittenUrl: req.rewrittenUrl?.path } }); + return res.ok({ + body: { + rewrittenUrl: req.rewrittenUrl + ? `${req.rewrittenUrl.pathname}${req.rewrittenUrl.search}` + : undefined, + }, + }); }); registerOnPreRouting((req, res, t) => t.rewriteUrl('/reroute-1')); @@ -163,7 +175,13 @@ describe('OnPreRouting', () => { const router = createRouter('/'); router.get({ path: '/login', validate: false }, (context, req, res) => { - return res.ok({ body: { rewrittenUrl: req.rewrittenUrl?.path } }); + return res.ok({ + body: { + rewrittenUrl: req.rewrittenUrl + ? `${req.rewrittenUrl.pathname}${req.rewrittenUrl.search}` + : undefined, + }, + }); }); registerOnPreRouting((req, res, t) => t.next()); diff --git a/src/core/server/http/lifecycle/on_pre_routing.ts b/src/core/server/http/lifecycle/on_pre_routing.ts index 92ae1f0b7bbd..e553f113a7cf 100644 --- a/src/core/server/http/lifecycle/on_pre_routing.ts +++ b/src/core/server/http/lifecycle/on_pre_routing.ts @@ -17,6 +17,7 @@ * under the License. */ +import { URL } from 'url'; import { Lifecycle, Request, ResponseToolkit as HapiResponseToolkit } from 'hapi'; import { Logger } from '../../logging'; import { @@ -110,10 +111,30 @@ export function adoptToHapiOnRequest(fn: OnPreRoutingHandler, log: Logger) { if (preRoutingResult.isRewriteUrl(result)) { const appState = request.app as KibanaRequestState; - appState.rewrittenUrl = appState.rewrittenUrl ?? request.url; + appState.rewrittenUrl = + // @ts-expect-error request._core isn't supposed to be accessed - remove once we upgrade to hapi v18 + appState.rewrittenUrl ?? new URL(request.url.href!, request._core.info.uri); const { url } = result; - request.setUrl(url); + + // TODO: Remove once we upgrade to Node.js 12! + // + // Warning: The following for-loop took 10 days to write, and is a hack + // to force V8 to make a copy of the string in memory. + // + // The reason why we need this is because of what appears to be a bug + // in V8 that caused some URL paths to not be routed correctly once + // `request.setUrl` was called with the path. + // + // The details can be seen in this discussion on Twitter: + // https://twitter.com/wa7son/status/1319992632366518277 + let urlCopy = ''; + for (let i = 0; i < url.length; i++) { + urlCopy += url[i]; + } + + request.setUrl(urlCopy); + // We should update raw request as well since it can be proxied to the old platform request.raw.req.url = url; return responseToolkit.continue; diff --git a/src/core/server/http/router/request.ts b/src/core/server/http/router/request.ts index 2d0e8d6c1a6a..561bf742050c 100644 --- a/src/core/server/http/router/request.ts +++ b/src/core/server/http/router/request.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Url } from 'url'; +import { URL } from 'url'; import uuid from 'uuid'; import { Request, RouteOptionsApp, ApplicationState } from 'hapi'; import { Observable, fromEvent, merge } from 'rxjs'; @@ -45,7 +45,7 @@ export interface KibanaRouteOptions extends RouteOptionsApp { export interface KibanaRequestState extends ApplicationState { requestId: string; requestUuid: string; - rewrittenUrl?: Url; + rewrittenUrl?: URL; } /** @@ -163,7 +163,7 @@ export class KibanaRequest< */ public readonly uuid: string; /** a WHATWG URL standard object. */ - public readonly url: Url; + public readonly url: URL; /** matched route details */ public readonly route: RecursiveReadonly>; /** @@ -190,7 +190,7 @@ export class KibanaRequest< /** * URL rewritten in onPreRouting request interceptor. */ - public readonly rewrittenUrl?: Url; + public readonly rewrittenUrl?: URL; /** @internal */ protected readonly [requestSymbol]: Request; @@ -212,7 +212,8 @@ export class KibanaRequest< this.uuid = appState?.requestUuid ?? uuid.v4(); this.rewrittenUrl = appState?.rewrittenUrl; - this.url = request.url; + // @ts-expect-error request._core isn't supposed to be accessed - remove once we upgrade to hapi v18 + this.url = new URL(request.url.href!, request._core.info.uri); this.headers = deepFreeze({ ...request.headers }); this.isSystemRequest = request.headers['kbn-system-request'] === 'true' || @@ -304,8 +305,8 @@ export class KibanaRequest< if (authOptions === false) return false; throw new Error( `unexpected authentication options: ${JSON.stringify(authOptions)} for route: ${ - this.url.href - }` + this.url.pathname + }${this.url.search}` ); } } diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index 1c0584837dc3..7551f53ab27d 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -19,7 +19,7 @@ import { of } from 'rxjs'; import { duration } from 'moment'; import { ByteSizeValue } from '@kbn/config-schema'; -import { MockedKeys } from '../typings'; +import type { MockedKeys } from '@kbn/utility-types/jest'; import { PluginInitializerContext, CoreSetup, CoreStart, StartServicesAccessor } from '.'; import { loggingSystemMock } from './logging/logging_system.mock'; import { loggingServiceMock } from './logging/logging_service.mock'; diff --git a/src/core/server/saved_objects/export/inject_nested_depdendencies.test.ts b/src/core/server/saved_objects/export/inject_nested_depdendencies.test.ts index 1d5ce5625bf4..862d11cfa663 100644 --- a/src/core/server/saved_objects/export/inject_nested_depdendencies.test.ts +++ b/src/core/server/saved_objects/export/inject_nested_depdendencies.test.ts @@ -78,7 +78,7 @@ describe('getObjectReferencesToFetch()', () => { `); }); - test(`doesn't deal with circular dependencies`, () => { + test('does not fail on circular dependencies', () => { const map = new Map(); map.set('index-pattern:1', { id: '1', @@ -527,7 +527,7 @@ describe('injectNestedDependencies', () => { `); }); - test(`doesn't deal with circular dependencies`, async () => { + test('does not fail on circular dependencies', async () => { const savedObjects = [ { id: '2', diff --git a/src/core/server/saved_objects/export/sort_objects.test.ts b/src/core/server/saved_objects/export/sort_objects.test.ts index 7b6698dfaf88..cd116d767b0c 100644 --- a/src/core/server/saved_objects/export/sort_objects.test.ts +++ b/src/core/server/saved_objects/export/sort_objects.test.ts @@ -46,27 +46,27 @@ describe('sortObjects()', () => { }, ]; expect(sortObjects(docs)).toMatchInlineSnapshot(` -Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "ref1", - "type": "index-pattern", - }, - ], - "type": "search", - }, -] -`); + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "ref1", + "type": "index-pattern", + }, + ], + "type": "search", + }, + ] + `); }); test('should not mutate parameter', () => { @@ -91,49 +91,49 @@ Array [ }, ]; expect(sortObjects(docs)).toMatchInlineSnapshot(` -Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "ref1", - "type": "index-pattern", - }, - ], - "type": "search", - }, -] -`); + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "ref1", + "type": "index-pattern", + }, + ], + "type": "search", + }, + ] + `); expect(docs).toMatchInlineSnapshot(` -Array [ - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "ref1", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, -] -`); + Array [ + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "ref1", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + ] + `); }); test('should sort unordered array', () => { @@ -199,71 +199,71 @@ Array [ }, ]; expect(sortObjects(docs)).toMatchInlineSnapshot(` -Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "ref1", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "attributes": Object {}, - "id": "3", - "references": Array [ - Object { - "id": "2", - "name": "ref1", - "type": "search", - }, - ], - "type": "visualization", - }, - Object { - "attributes": Object {}, - "id": "4", - "references": Array [ - Object { - "id": "1", - "name": "ref1", - "type": "index-pattern", - }, - ], - "type": "visualization", - }, - Object { - "attributes": Object {}, - "id": "5", - "references": Array [ - Object { - "id": "3", - "name": "ref1", - "type": "visualization", - }, - Object { - "id": "4", - "name": "ref2", - "type": "visualization", - }, - ], - "type": "dashboard", - }, -] -`); + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "ref1", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "attributes": Object {}, + "id": "3", + "references": Array [ + Object { + "id": "2", + "name": "ref1", + "type": "search", + }, + ], + "type": "visualization", + }, + Object { + "attributes": Object {}, + "id": "4", + "references": Array [ + Object { + "id": "1", + "name": "ref1", + "type": "index-pattern", + }, + ], + "type": "visualization", + }, + Object { + "attributes": Object {}, + "id": "5", + "references": Array [ + Object { + "id": "3", + "name": "ref1", + "type": "visualization", + }, + Object { + "id": "4", + "name": "ref2", + "type": "visualization", + }, + ], + "type": "dashboard", + }, + ] + `); }); - test('detects circular dependencies', () => { + test('should not fail on circular dependencies', () => { const docs = [ { id: '1', @@ -290,8 +290,149 @@ Array [ ], }, ]; - expect(() => sortObjects(docs)).toThrowErrorMatchingInlineSnapshot( - `"circular reference: [foo:1] ref-> [foo:2] ref-> [foo:1]"` - ); + + expect(sortObjects(docs)).toMatchInlineSnapshot(` + Array [ + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "ref1", + "type": "foo", + }, + ], + "type": "foo", + }, + Object { + "attributes": Object {}, + "id": "1", + "references": Array [ + Object { + "id": "2", + "name": "ref1", + "type": "foo", + }, + ], + "type": "foo", + }, + ] + `); + }); + test('should not fail on complex circular dependencies', () => { + const docs = [ + { + id: '1', + type: 'foo', + attributes: {}, + references: [ + { + name: 'ref12', + type: 'foo', + id: '2', + }, + { + name: 'ref13', + type: 'baz', + id: '3', + }, + ], + }, + { + id: '2', + type: 'foo', + attributes: {}, + references: [ + { + name: 'ref13', + type: 'foo', + id: '3', + }, + ], + }, + { + id: '3', + type: 'baz', + attributes: {}, + references: [ + { + name: 'ref13', + type: 'xyz', + id: '4', + }, + ], + }, + { + id: '4', + type: 'xyz', + attributes: {}, + references: [ + { + name: 'ref14', + type: 'foo', + id: '1', + }, + ], + }, + ]; + + expect(sortObjects(docs)).toMatchInlineSnapshot(` + Array [ + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "3", + "name": "ref13", + "type": "foo", + }, + ], + "type": "foo", + }, + Object { + "attributes": Object {}, + "id": "4", + "references": Array [ + Object { + "id": "1", + "name": "ref14", + "type": "foo", + }, + ], + "type": "xyz", + }, + Object { + "attributes": Object {}, + "id": "3", + "references": Array [ + Object { + "id": "4", + "name": "ref13", + "type": "xyz", + }, + ], + "type": "baz", + }, + Object { + "attributes": Object {}, + "id": "1", + "references": Array [ + Object { + "id": "2", + "name": "ref12", + "type": "foo", + }, + Object { + "id": "3", + "name": "ref13", + "type": "baz", + }, + ], + "type": "foo", + }, + ] + `); }); }); diff --git a/src/core/server/saved_objects/export/sort_objects.ts b/src/core/server/saved_objects/export/sort_objects.ts index 64bab9f43bf1..ec83b687527f 100644 --- a/src/core/server/saved_objects/export/sort_objects.ts +++ b/src/core/server/saved_objects/export/sort_objects.ts @@ -17,7 +17,6 @@ * under the License. */ -import Boom from 'boom'; import { SavedObject } from '../types'; export function sortObjects(savedObjects: SavedObject[]): SavedObject[] { @@ -30,11 +29,7 @@ export function sortObjects(savedObjects: SavedObject[]): SavedObject[] { function includeObjects(objects: SavedObject[]) { for (const object of objects) { if (path.has(object)) { - throw Boom.badRequest( - `circular reference: ${[...path, object] - .map((obj) => `[${obj.type}:${obj.id}]`) - .join(' ref-> ')}` - ); + continue; } const refdObjects = object.references diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index d9dc46d2cad9..914b5fbdb519 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -162,7 +162,7 @@ import { Type } from '@kbn/config-schema'; import { TypeOf } from '@kbn/config-schema'; import { UpdateDocumentByQueryParams } from 'elasticsearch'; import { UpdateDocumentParams } from 'elasticsearch'; -import { Url } from 'url'; +import { URL } from 'url'; // @public export interface AppCategory { @@ -1007,11 +1007,11 @@ export class KibanaRequest>; // (undocumented) readonly socket: IKibanaSocket; - readonly url: Url; + readonly url: URL; readonly uuid: string; } diff --git a/src/core/tsconfig.json b/src/core/tsconfig.json index a3531057767d..4281559c9aa1 100644 --- a/src/core/tsconfig.json +++ b/src/core/tsconfig.json @@ -13,8 +13,7 @@ "types/**/*", "test_helpers/**/*", "utils/**/*", - "index.ts", - "typings.ts" + "index.ts" ], "references": [ { "path": "../test_utils/" } diff --git a/src/dev/build/tasks/os_packages/package_scripts/post_install.sh b/src/dev/build/tasks/os_packages/package_scripts/post_install.sh index 1c679bdb40b5..939226b565f7 100644 --- a/src/dev/build/tasks/os_packages/package_scripts/post_install.sh +++ b/src/dev/build/tasks/os_packages/package_scripts/post_install.sh @@ -7,14 +7,17 @@ set_chmod() { chmod -f 660 ${KBN_PATH_CONF}/kibana.yml || true chmod -f 2750 <%= dataDir %> || true chmod -f 2750 ${KBN_PATH_CONF} || true + chmod -f 2750 <%= logDir %> || true } set_chown() { + chown <%= user %>:<%= group %> <%= logDir %> chown -R <%= user %>:<%= group %> <%= dataDir %> chown -R root:<%= group %> ${KBN_PATH_CONF} } -set_access() { +setup() { + [ ! -d "<%= logDir %>" ] && mkdir "<%= logDir %>" set_chmod set_chown } @@ -35,7 +38,7 @@ case $1 in IS_UPGRADE=true fi - set_access + setup ;; abort-deconfigure|abort-upgrade|abort-remove) ;; @@ -55,7 +58,7 @@ case $1 in IS_UPGRADE=true fi - set_access + setup ;; *) diff --git a/src/dev/build/tasks/os_packages/run_fpm.ts b/src/dev/build/tasks/os_packages/run_fpm.ts index b5169ec3d43b..b8289f1da194 100644 --- a/src/dev/build/tasks/os_packages/run_fpm.ts +++ b/src/dev/build/tasks/os_packages/run_fpm.ts @@ -109,6 +109,8 @@ export async function runFpm( `pluginsDir=/usr/share/kibana/plugins`, '--template-value', `dataDir=/var/lib/kibana`, + '--template-value', + `logDir=/var/log/kibana`, // config and data directories are copied to /usr/share and /var/lib // below, so exclude them from the main package source located in diff --git a/src/dev/build/tasks/os_packages/service_templates/systemd/etc/systemd/system/kibana.service b/src/dev/build/tasks/os_packages/service_templates/systemd/etc/systemd/system/kibana.service index e66e0e7c8dfb..05724db8799f 100644 --- a/src/dev/build/tasks/os_packages/service_templates/systemd/etc/systemd/system/kibana.service +++ b/src/dev/build/tasks/os_packages/service_templates/systemd/etc/systemd/system/kibana.service @@ -1,21 +1,32 @@ [Unit] Description=Kibana +Documentation=https://www.elastic.co +Wants=network-online.target +After=network-online.target [Service] Type=simple User=kibana Group=kibana -# Load env vars from /etc/default/ and /etc/sysconfig/ if they exist. -# Prefixing the path with '-' makes it try to load, but if the file doesn't -# exist, it continues onward. + +Environment=KBN_HOME=/usr/share/kibana +Environment=KBN_PATH_CONF=/etc/kibana + EnvironmentFile=-/etc/default/kibana EnvironmentFile=-/etc/sysconfig/kibana -ExecStart=/usr/share/kibana/bin/kibana + +ExecStart=/usr/share/kibana/bin/kibana --logging.dest="/var/log/kibana/kibana.log" + Restart=on-failure RestartSec=3 + StartLimitBurst=3 StartLimitInterval=60 -WorkingDirectory=/ + +WorkingDirectory=/usr/share/kibana + +StandardOutput=journal +StandardError=inherit [Install] WantedBy=multi-user.target diff --git a/src/dev/build/tasks/os_packages/service_templates/sysv/etc/init.d/kibana b/src/dev/build/tasks/os_packages/service_templates/sysv/etc/init.d/kibana index c13676ef031b..eedd4898ce6c 100755 --- a/src/dev/build/tasks/os_packages/service_templates/sysv/etc/init.d/kibana +++ b/src/dev/build/tasks/os_packages/service_templates/sysv/etc/init.d/kibana @@ -35,6 +35,7 @@ fi name=kibana program=/usr/share/kibana/bin/kibana +args="--logging.dest=/var/log/kibana/kibana.log" pidfile="/var/run/kibana/$name.pid" [ -r /etc/default/$name ] && . /etc/default/$name @@ -55,10 +56,6 @@ emit() { } start() { - [ ! -d "/var/log/kibana/" ] && mkdir "/var/log/kibana/" - chown "$user":"$group" "/var/log/kibana/" - chmod 2750 "/var/log/kibana/" - [ ! -d "/var/run/kibana/" ] && mkdir "/var/run/kibana/" chown "$user":"$group" "/var/run/kibana/" chmod 755 "/var/run/kibana/" @@ -66,8 +63,8 @@ start() { chroot --userspec "$user":"$group" "$chroot" sh -c " cd \"$chdir\" - exec \"$program\" - " >> /var/log/kibana/kibana.stdout 2>> /var/log/kibana/kibana.stderr & + exec \"$program $args\" + " >> /var/log/kibana/kibana.log 2>&1 & # Generate the pidfile from here. If we instead made the forked process # generate it there will be a race condition between the pidfile writing diff --git a/src/plugins/data/common/field_formats/index.ts b/src/plugins/data/common/field_formats/index.ts index c1b1619abd24..1f6496ba6ac7 100644 --- a/src/plugins/data/common/field_formats/index.ts +++ b/src/plugins/data/common/field_formats/index.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import { PublicMethodsOf } from '@kbn/utility-types'; import { FieldFormatsRegistry } from './field_formats_registry'; type IFieldFormatsRegistry = PublicMethodsOf; diff --git a/src/plugins/data/common/field_formats/types.ts b/src/plugins/data/common/field_formats/types.ts index af956a20c0dc..5a830586b8d0 100644 --- a/src/plugins/data/common/field_formats/types.ts +++ b/src/plugins/data/common/field_formats/types.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import { PublicMethodsOf } from '@kbn/utility-types'; import { GetConfigFn } from '../types'; import { FieldFormat } from './field_format'; import { FieldFormatsRegistry } from './field_formats_registry'; diff --git a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts index fd3d7a1d138f..aae9b89cdc61 100644 --- a/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts +++ b/src/plugins/data/common/index_patterns/index_patterns/index_patterns.ts @@ -18,6 +18,7 @@ */ import { i18n } from '@kbn/i18n'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { SavedObjectsClientCommon } from '../..'; import { createIndexPatternCache } from '.'; diff --git a/src/plugins/data/common/search/search_source/legacy/default_search_strategy.test.ts b/src/plugins/data/common/search/search_source/legacy/default_search_strategy.test.ts index 3badd456bd72..b13f6ad26654 100644 --- a/src/plugins/data/common/search/search_source/legacy/default_search_strategy.test.ts +++ b/src/plugins/data/common/search/search_source/legacy/default_search_strategy.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { defaultSearchStrategy } from './default_search_strategy'; import { LegacyFetchHandlers, SearchStrategySearchParams } from './types'; import { BehaviorSubject } from 'rxjs'; diff --git a/src/plugins/data/common/search/search_source/mocks.ts b/src/plugins/data/common/search/search_source/mocks.ts index d4c0707f950b..ea7d6b4441cc 100644 --- a/src/plugins/data/common/search/search_source/mocks.ts +++ b/src/plugins/data/common/search/search_source/mocks.ts @@ -18,6 +18,7 @@ */ import { BehaviorSubject } from 'rxjs'; +import type { MockedKeys } from '@kbn/utility-types/jest'; import { uiSettingsServiceMock } from '../../../../../core/public/mocks'; import { SearchSource } from './search_source'; diff --git a/src/plugins/data/public/field_formats/mocks.ts b/src/plugins/data/public/field_formats/mocks.ts index ec1233a085bc..ba1e9de71bab 100644 --- a/src/plugins/data/public/field_formats/mocks.ts +++ b/src/plugins/data/public/field_formats/mocks.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { FieldFormatsStart, FieldFormatsSetup, FieldFormatsService } from '.'; import { fieldFormatsMock } from '../../common/field_formats/mocks'; diff --git a/src/plugins/data/public/query/mocks.ts b/src/plugins/data/public/query/mocks.ts index 53c177de0fa3..f8376d783487 100644 --- a/src/plugins/data/public/query/mocks.ts +++ b/src/plugins/data/public/query/mocks.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Observable } from 'rxjs'; import { QueryService, QuerySetup, QueryStart } from '.'; import { timefilterServiceMock } from './timefilter/timefilter_service.mock'; diff --git a/src/plugins/data/public/query/query_string/query_string_manager.ts b/src/plugins/data/public/query/query_string/query_string_manager.ts index 50732c99a62d..90a622fada95 100644 --- a/src/plugins/data/public/query/query_string/query_string_manager.ts +++ b/src/plugins/data/public/query/query_string/query_string_manager.ts @@ -19,6 +19,7 @@ import { BehaviorSubject } from 'rxjs'; import { skip } from 'rxjs/operators'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { CoreStart } from 'kibana/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { Query, UI_SETTINGS } from '../../../common'; diff --git a/src/plugins/data/public/query/timefilter/time_history.ts b/src/plugins/data/public/query/timefilter/time_history.ts index fe73fd85b164..24786c5eed62 100644 --- a/src/plugins/data/public/query/timefilter/time_history.ts +++ b/src/plugins/data/public/query/timefilter/time_history.ts @@ -18,6 +18,7 @@ */ import moment from 'moment'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { PersistedLog } from '../persisted_log'; import { TimeRange } from '../../../common'; diff --git a/src/plugins/data/public/query/timefilter/timefilter.ts b/src/plugins/data/public/query/timefilter/timefilter.ts index 01b82087cf35..49a8c68f6916 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.ts @@ -20,6 +20,7 @@ import _ from 'lodash'; import { Subject, BehaviorSubject } from 'rxjs'; import moment from 'moment'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { areRefreshIntervalsDifferent, areTimeRangesDifferent } from './lib/diff_time_picker_vals'; import { getForceNow } from './lib/get_force_now'; import { TimefilterConfig, InputTimeRange, TimeRangeBounds } from './types'; 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 060257a88052..9f1c64a1739a 100644 --- a/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts +++ b/src/plugins/data/public/query/timefilter/timefilter_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { TimefilterService, TimeHistoryContract, TimefilterContract } from '.'; import { Observable } from 'rxjs'; diff --git a/src/plugins/data/public/search/collectors/create_usage_collector.test.ts b/src/plugins/data/public/search/collectors/create_usage_collector.test.ts index 9cadb1e796ad..b87ac11e810c 100644 --- a/src/plugins/data/public/search/collectors/create_usage_collector.test.ts +++ b/src/plugins/data/public/search/collectors/create_usage_collector.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { CoreSetup, CoreStart } from '../../../../../core/public'; import { coreMock } from '../../../../../core/public/mocks'; import { usageCollectionPluginMock, Setup } from '../../../../usage_collection/public/mocks'; diff --git a/src/plugins/data/public/search/es_search/get_es_preference.test.ts b/src/plugins/data/public/search/es_search/get_es_preference.test.ts index 05a74b3e6205..8b3d335b38d1 100644 --- a/src/plugins/data/public/search/es_search/get_es_preference.test.ts +++ b/src/plugins/data/public/search/es_search/get_es_preference.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { getEsPreference } from './get_es_preference'; import { CoreStart } from '../../../../../core/public'; import { coreMock } from '../../../../../core/public/mocks'; diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts index e8a728bb9cec..472caa5e4f45 100644 --- a/src/plugins/data/public/search/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { CoreSetup, CoreStart } from '../../../../core/public'; import { coreMock } from '../../../../core/public/mocks'; import { IEsSearchRequest } from '../../common/search'; diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 1afcf4615ab5..087ca9e4f5c4 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -20,6 +20,7 @@ import { get, memoize, trimEnd } from 'lodash'; import { BehaviorSubject, throwError, timer, defer, from, Observable, NEVER } from 'rxjs'; import { catchError, finalize } from 'rxjs/operators'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { CoreStart, CoreSetup, ToastsSetup } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { diff --git a/src/plugins/data/public/search/search_service.test.ts b/src/plugins/data/public/search/search_service.test.ts index b59fa6fa16bf..20041a02067d 100644 --- a/src/plugins/data/public/search/search_service.test.ts +++ b/src/plugins/data/public/search/search_service.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { coreMock } from '../../../../core/public/mocks'; import { CoreSetup, CoreStart } from '../../../../core/public'; diff --git a/src/plugins/data/server/search/routes/call_msearch.test.ts b/src/plugins/data/server/search/routes/call_msearch.test.ts index 3d409e22aaa8..183c2334b4e3 100644 --- a/src/plugins/data/server/search/routes/call_msearch.test.ts +++ b/src/plugins/data/server/search/routes/call_msearch.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; import { Observable } from 'rxjs'; import { IUiSettingsClient, IScopedClusterClient, SharedGlobalConfig } from 'src/core/server'; diff --git a/src/plugins/data/server/search/routes/msearch.test.ts b/src/plugins/data/server/search/routes/msearch.test.ts index 2f414fe0b492..e2e5818cf9a7 100644 --- a/src/plugins/data/server/search/routes/msearch.test.ts +++ b/src/plugins/data/server/search/routes/msearch.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { Observable } from 'rxjs'; import { diff --git a/src/plugins/data/server/search/routes/search.test.ts b/src/plugins/data/server/search/routes/search.test.ts index 834e5de5c312..845ab3bbe4eb 100644 --- a/src/plugins/data/server/search/routes/search.test.ts +++ b/src/plugins/data/server/search/routes/search.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { Observable, from } from 'rxjs'; import { diff --git a/src/plugins/data/server/search/search_service.test.ts b/src/plugins/data/server/search/search_service.test.ts index a001d56b3651..2b513be147e9 100644 --- a/src/plugins/data/server/search/search_service.test.ts +++ b/src/plugins/data/server/search/search_service.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { CoreSetup, CoreStart } from '../../../../core/server'; import { coreMock } from '../../../../core/server/mocks'; diff --git a/src/plugins/data/server/search/search_source/mocks.ts b/src/plugins/data/server/search/search_source/mocks.ts index 7e9cc8f2ff42..73b39b416316 100644 --- a/src/plugins/data/server/search/search_source/mocks.ts +++ b/src/plugins/data/server/search/search_source/mocks.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { KibanaRequest } from 'src/core/server'; import { searchSourceCommonMock } from '../../../common/search/search_source/mocks'; diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 97cbb40c13db..e5882a6cff80 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -37,6 +37,7 @@ import { PathConfigType } from '@kbn/utils'; import { Plugin as Plugin_2 } from 'src/core/server'; import { Plugin as Plugin_3 } from 'kibana/server'; import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/server'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { RecursiveReadonly } from '@kbn/utility-types'; import { RequestAdapter } from 'src/plugins/inspector/common'; import { RequestHandlerContext } from 'src/core/server'; diff --git a/src/plugins/es_ui_shared/public/index.ts b/src/plugins/es_ui_shared/public/index.ts index 94b084e7d3f2..f48198459d48 100644 --- a/src/plugins/es_ui_shared/public/index.ts +++ b/src/plugins/es_ui_shared/public/index.ts @@ -57,7 +57,7 @@ export { export { Forms, ace, GlobalFlyout, XJson }; -export { extractQueryParams } from './url'; +export { extractQueryParams, attemptToURIDecode } from './url'; /** dummy plugin, we just want esUiShared to have its own bundle */ export function plugin() { diff --git a/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.test.ts b/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.test.ts new file mode 100644 index 000000000000..15750c766780 --- /dev/null +++ b/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.test.ts @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { attemptToURIDecode } from './attempt_to_uri_decode'; + +test('decodes an encoded string', () => { + const encodedString = 'test%3F'; + expect(attemptToURIDecode(encodedString)).toBe('test?'); +}); + +// react router partially decodes %25 sequence to % in match params +// https://github.com/elastic/kibana/pull/81664 +test('ignores the error if a string is already decoded', () => { + const decodedString = 'test%'; + expect(attemptToURIDecode(decodedString)).toBe(decodedString); +}); diff --git a/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.ts b/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.ts new file mode 100644 index 000000000000..65444b83f77b --- /dev/null +++ b/src/plugins/es_ui_shared/public/url/attempt_to_uri_decode.ts @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + * Use this function with any match params coming from react router to safely decode values. + * https://github.com/elastic/kibana/pull/81664 + */ +export const attemptToURIDecode = (value: string) => { + let result = value; + try { + result = decodeURIComponent(value); + } catch (e) { + // do nothing + } + return result; +}; diff --git a/src/plugins/es_ui_shared/public/url/index.ts b/src/plugins/es_ui_shared/public/url/index.ts index 692e094f9eda..a40885545ca0 100644 --- a/src/plugins/es_ui_shared/public/url/index.ts +++ b/src/plugins/es_ui_shared/public/url/index.ts @@ -18,3 +18,4 @@ */ export { extractQueryParams } from './extract_query_params'; +export { attemptToURIDecode } from './attempt_to_uri_decode'; diff --git a/src/plugins/expressions/public/public.api.md b/src/plugins/expressions/public/public.api.md index fe95cf5eb0cd..68a3507bbf16 100644 --- a/src/plugins/expressions/public/public.api.md +++ b/src/plugins/expressions/public/public.api.md @@ -1039,7 +1039,7 @@ export interface Range { // Warning: (ae-missing-release-tag) "ReactExpressionRenderer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const ReactExpressionRenderer: ({ className, dataAttrs, padding, renderError, expression, onEvent, reload$, ...expressionLoaderOptions }: ReactExpressionRendererProps) => JSX.Element; +export const ReactExpressionRenderer: ({ className, dataAttrs, padding, renderError, expression, onEvent, reload$, debounce, ...expressionLoaderOptions }: ReactExpressionRendererProps) => JSX.Element; // Warning: (ae-missing-release-tag) "ReactExpressionRendererProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -1050,6 +1050,8 @@ export interface ReactExpressionRendererProps extends IExpressionLoaderParams { // (undocumented) dataAttrs?: string[]; // (undocumented) + debounce?: number; + // (undocumented) expression: string | ExpressionAstExpression; // (undocumented) onEvent?: (event: ExpressionRendererEvent) => void; diff --git a/src/plugins/expressions/public/react_expression_renderer.test.tsx b/src/plugins/expressions/public/react_expression_renderer.test.tsx index 7c1711f056d6..052c2a9f6a24 100644 --- a/src/plugins/expressions/public/react_expression_renderer.test.tsx +++ b/src/plugins/expressions/public/react_expression_renderer.test.tsx @@ -113,6 +113,39 @@ describe('ExpressionRenderer', () => { instance.unmount(); }); + it('waits for debounce period if specified', () => { + jest.useFakeTimers(); + + const refreshSubject = new Subject(); + const loaderUpdate = jest.fn(); + + (ExpressionLoader as jest.Mock).mockImplementation(() => { + return { + render$: new Subject(), + data$: new Subject(), + loading$: new Subject(), + update: loaderUpdate, + destroy: jest.fn(), + }; + }); + + const instance = mount( + + ); + + instance.setProps({ expression: 'abc' }); + + expect(loaderUpdate).toHaveBeenCalledTimes(1); + + act(() => { + jest.runAllTimers(); + }); + + expect(loaderUpdate).toHaveBeenCalledTimes(2); + + instance.unmount(); + }); + it('should display a custom error message if the user provides one and then remove it after successful render', () => { const dataSubject = new Subject(); const data$ = dataSubject.asObservable().pipe(share()); diff --git a/src/plugins/expressions/public/react_expression_renderer.tsx b/src/plugins/expressions/public/react_expression_renderer.tsx index 99d170c96666..fecebf36ab7e 100644 --- a/src/plugins/expressions/public/react_expression_renderer.tsx +++ b/src/plugins/expressions/public/react_expression_renderer.tsx @@ -45,6 +45,7 @@ export interface ReactExpressionRendererProps extends IExpressionLoaderParams { * An observable which can be used to re-run the expression without destroying the component */ reload$?: Observable; + debounce?: number; } export type ReactExpressionRendererType = React.ComponentType; @@ -71,6 +72,7 @@ export const ReactExpressionRenderer = ({ expression, onEvent, reload$, + debounce, ...expressionLoaderOptions }: ReactExpressionRendererProps) => { const mountpoint: React.MutableRefObject = useRef(null); @@ -85,12 +87,28 @@ export const ReactExpressionRenderer = ({ const errorRenderHandlerRef: React.MutableRefObject = useRef( null ); + const [debouncedExpression, setDebouncedExpression] = useState(expression); + useEffect(() => { + if (debounce === undefined) { + return; + } + const handler = setTimeout(() => { + setDebouncedExpression(expression); + }, debounce); + + return () => { + clearTimeout(handler); + }; + }, [expression, debounce]); + + const activeExpression = debounce !== undefined ? debouncedExpression : expression; + const waitingForDebounceToComplete = debounce !== undefined && expression !== debouncedExpression; /* eslint-disable react-hooks/exhaustive-deps */ // OK to ignore react-hooks/exhaustive-deps because options update is handled by calling .update() useEffect(() => { const subs: Subscription[] = []; - expressionLoaderRef.current = new ExpressionLoader(mountpoint.current!, expression, { + expressionLoaderRef.current = new ExpressionLoader(mountpoint.current!, activeExpression, { ...expressionLoaderOptions, // react component wrapper provides different // error handling api which is easier to work with from react @@ -146,21 +164,21 @@ export const ReactExpressionRenderer = ({ useEffect(() => { const subscription = reload$?.subscribe(() => { if (expressionLoaderRef.current) { - expressionLoaderRef.current.update(expression, expressionLoaderOptions); + expressionLoaderRef.current.update(activeExpression, expressionLoaderOptions); } }); return () => subscription?.unsubscribe(); - }, [reload$, expression, ...Object.values(expressionLoaderOptions)]); + }, [reload$, activeExpression, ...Object.values(expressionLoaderOptions)]); // Re-fetch data automatically when the inputs change useShallowCompareEffect( () => { if (expressionLoaderRef.current) { - expressionLoaderRef.current.update(expression, expressionLoaderOptions); + expressionLoaderRef.current.update(activeExpression, expressionLoaderOptions); } }, // when expression is changed by reference and when any other loaderOption is changed by reference - [{ expression, ...expressionLoaderOptions }] + [{ activeExpression, ...expressionLoaderOptions }] ); /* eslint-enable react-hooks/exhaustive-deps */ @@ -188,7 +206,9 @@ export const ReactExpressionRenderer = ({ return (

{state.isEmpty && } - {state.isLoading && } + {(state.isLoading || waitingForDebounceToComplete) && ( + + )} {!state.isLoading && state.error && renderError && diff --git a/src/plugins/home/public/services/environment/environment.mock.ts b/src/plugins/home/public/services/environment/environment.mock.ts index d8be02bf6552..7b1fb0a85e0d 100644 --- a/src/plugins/home/public/services/environment/environment.mock.ts +++ b/src/plugins/home/public/services/environment/environment.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { EnvironmentService, EnvironmentServiceSetup } from './environment'; const createSetupMock = (): jest.Mocked => { diff --git a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts index e1a415ba2d57..6cb4bb1db90a 100644 --- a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts +++ b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { FeatureCatalogueRegistrySetup, FeatureCatalogueRegistry, diff --git a/src/plugins/home/public/services/tutorials/tutorial_service.mock.ts b/src/plugins/home/public/services/tutorials/tutorial_service.mock.ts index 667730e25a2e..7aa1aec0898f 100644 --- a/src/plugins/home/public/services/tutorials/tutorial_service.mock.ts +++ b/src/plugins/home/public/services/tutorials/tutorial_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { TutorialService, TutorialServiceSetup } from './tutorial_service'; const createSetupMock = (): jest.Mocked => { diff --git a/src/plugins/home/server/services/sample_data/sample_data_registry.mock.ts b/src/plugins/home/server/services/sample_data/sample_data_registry.mock.ts index 4d0fb4f96023..717f21576def 100644 --- a/src/plugins/home/server/services/sample_data/sample_data_registry.mock.ts +++ b/src/plugins/home/server/services/sample_data/sample_data_registry.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SampleDataRegistrySetup, SampleDataRegistryStart, diff --git a/src/plugins/home/server/services/tutorials/tutorials_registry.mock.ts b/src/plugins/home/server/services/tutorials/tutorials_registry.mock.ts index 5ff0152062f4..162216161342 100644 --- a/src/plugins/home/server/services/tutorials/tutorials_registry.mock.ts +++ b/src/plugins/home/server/services/tutorials/tutorials_registry.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { TutorialsRegistrySetup, TutorialsRegistryStart, diff --git a/src/plugins/home/server/services/tutorials/tutorials_registry.test.ts b/src/plugins/home/server/services/tutorials/tutorials_registry.test.ts index b91a265da7d1..96dab89bb170 100644 --- a/src/plugins/home/server/services/tutorials/tutorials_registry.test.ts +++ b/src/plugins/home/server/services/tutorials/tutorials_registry.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { TutorialsRegistry } from './tutorials_registry'; import { coreMock } from '../../../../../core/server/mocks'; import { CoreSetup } from '../../../../../core/server'; diff --git a/src/plugins/index_pattern_management/public/service/environment/environment.mock.ts b/src/plugins/index_pattern_management/public/service/environment/environment.mock.ts index 2c2c68b8ead2..5ddbca67d9fe 100644 --- a/src/plugins/index_pattern_management/public/service/environment/environment.mock.ts +++ b/src/plugins/index_pattern_management/public/service/environment/environment.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { EnvironmentService, EnvironmentServiceSetup } from './environment'; import { MlCardState } from '../../types'; diff --git a/src/plugins/index_pattern_management/server/routes/preview_scripted_field.test.ts b/src/plugins/index_pattern_management/server/routes/preview_scripted_field.test.ts index 5de6ddf351c0..9d4c1bf005e6 100644 --- a/src/plugins/index_pattern_management/server/routes/preview_scripted_field.test.ts +++ b/src/plugins/index_pattern_management/server/routes/preview_scripted_field.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { CoreSetup, RequestHandlerContext } from 'src/core/server'; import { coreMock, httpServerMock } from '../../../../../src/core/server/mocks'; import { registerPreviewScriptedFieldRoute } from './preview_scripted_field'; diff --git a/src/plugins/inspector/tsconfig.json b/src/plugins/inspector/tsconfig.json new file mode 100644 index 000000000000..2a9c41464532 --- /dev/null +++ b/src/plugins/inspector/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["common/**/*", "public/**/*", "index.ts"], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../kibana_react/tsconfig.json" } + ] +} diff --git a/src/plugins/kibana_utils/public/storage/storage.test.ts b/src/plugins/kibana_utils/public/storage/storage.test.ts index 8c5d3d11a21f..293194cae55a 100644 --- a/src/plugins/kibana_utils/public/storage/storage.test.ts +++ b/src/plugins/kibana_utils/public/storage/storage.test.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { Storage } from './storage'; import { IStorage, IStorageWrapper } from './types'; diff --git a/src/plugins/saved_objects_management/public/services/action_service.mock.ts b/src/plugins/saved_objects_management/public/services/action_service.mock.ts index 97c95a589b92..dfa5f47325eb 100644 --- a/src/plugins/saved_objects_management/public/services/action_service.mock.ts +++ b/src/plugins/saved_objects_management/public/services/action_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SavedObjectsManagementActionService, SavedObjectsManagementActionServiceSetup, diff --git a/src/plugins/saved_objects_management/public/services/column_service.mock.ts b/src/plugins/saved_objects_management/public/services/column_service.mock.ts index 977b2099771b..9dfa130d463c 100644 --- a/src/plugins/saved_objects_management/public/services/column_service.mock.ts +++ b/src/plugins/saved_objects_management/public/services/column_service.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SavedObjectsManagementColumnService, SavedObjectsManagementColumnServiceSetup, diff --git a/src/plugins/saved_objects_management/public/services/service_registry.ts b/src/plugins/saved_objects_management/public/services/service_registry.ts index 2d6ec0b92047..d4dc6d6166e4 100644 --- a/src/plugins/saved_objects_management/public/services/service_registry.ts +++ b/src/plugins/saved_objects_management/public/services/service_registry.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SavedObjectLoader } from '../../../saved_objects/public'; export interface SavedObjectsManagementServiceRegistryEntry { diff --git a/src/plugins/saved_objects_management/server/services/management.mock.ts b/src/plugins/saved_objects_management/server/services/management.mock.ts index 85c2d3e4b08d..d76560731659 100644 --- a/src/plugins/saved_objects_management/server/services/management.mock.ts +++ b/src/plugins/saved_objects_management/server/services/management.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SavedObjectsManagement } from './management'; type Management = PublicMethodsOf; diff --git a/src/plugins/saved_objects_management/server/services/management.ts b/src/plugins/saved_objects_management/server/services/management.ts index 499f37990c34..f24226d798fa 100644 --- a/src/plugins/saved_objects_management/server/services/management.ts +++ b/src/plugins/saved_objects_management/server/services/management.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ISavedObjectTypeRegistry, SavedObject } from 'src/core/server'; export type ISavedObjectsManagement = PublicMethodsOf; diff --git a/src/plugins/security_oss/public/plugin.mock.ts b/src/plugins/security_oss/public/plugin.mock.ts index c513d241dccb..bb6e1c6bc654 100644 --- a/src/plugins/security_oss/public/plugin.mock.ts +++ b/src/plugins/security_oss/public/plugin.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; import { mockInsecureClusterService } from './insecure_cluster_service/insecure_cluster_service.mock'; import { SecurityOssPluginSetup, SecurityOssPluginStart } from './plugin'; diff --git a/src/plugins/share/public/services/share_menu_manager.mock.ts b/src/plugins/share/public/services/share_menu_manager.mock.ts index 7104abeb2609..c20543fea16d 100644 --- a/src/plugins/share/public/services/share_menu_manager.mock.ts +++ b/src/plugins/share/public/services/share_menu_manager.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ShareMenuManager, ShareMenuManagerStart } from './share_menu_manager'; const createStartMock = (): jest.Mocked => { diff --git a/src/plugins/share/public/services/share_menu_registry.mock.ts b/src/plugins/share/public/services/share_menu_registry.mock.ts index b69032f0b3e0..2645b7a73fdf 100644 --- a/src/plugins/share/public/services/share_menu_registry.mock.ts +++ b/src/plugins/share/public/services/share_menu_registry.mock.ts @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ShareMenuRegistry, ShareMenuRegistrySetup, diff --git a/src/plugins/ui_actions/public/plugin.ts b/src/plugins/ui_actions/public/plugin.ts index f83cc97c2a8e..87a1df959ccb 100644 --- a/src/plugins/ui_actions/public/plugin.ts +++ b/src/plugins/ui_actions/public/plugin.ts @@ -18,6 +18,7 @@ */ import { CoreStart, CoreSetup, Plugin, PluginInitializerContext } from 'src/core/public'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { UiActionsService } from './service'; import { selectRangeTrigger, diff --git a/src/plugins/ui_actions/public/public.api.md b/src/plugins/ui_actions/public/public.api.md index 229997281db4..8393f7480d4e 100644 --- a/src/plugins/ui_actions/public/public.api.md +++ b/src/plugins/ui_actions/public/public.api.md @@ -12,6 +12,7 @@ import { Observable } from 'rxjs'; import { PackageInfo } from '@kbn/config'; import { Plugin } from 'src/core/public'; import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/public'; +import { PublicMethodsOf } from '@kbn/utility-types'; import React from 'react'; import * as Rx from 'rxjs'; import { UiComponent } from 'src/plugins/kibana_utils/public'; diff --git a/src/plugins/vis_type_vega/public/_vega_editor.scss b/src/plugins/vis_type_vega/public/components/vega_editor.scss similarity index 100% rename from src/plugins/vis_type_vega/public/_vega_editor.scss rename to src/plugins/vis_type_vega/public/components/vega_editor.scss diff --git a/src/plugins/vis_type_vega/public/_vega_vis.scss b/src/plugins/vis_type_vega/public/components/vega_vis.scss similarity index 96% rename from src/plugins/vis_type_vega/public/_vega_vis.scss rename to src/plugins/vis_type_vega/public/components/vega_vis.scss index 6a0d20246089..004eed5a3972 100644 --- a/src/plugins/vis_type_vega/public/_vega_vis.scss +++ b/src/plugins/vis_type_vega/public/components/vega_vis.scss @@ -1,3 +1,11 @@ +.vgaVis__wrapper { + @include euiScrollBar; + + display: flex; + flex: 1 1 0; + overflow: auto; +} + .vgaVis { display: flex; flex: 1 1 100%; diff --git a/src/plugins/vis_type_vega/public/components/vega_vis_component.tsx b/src/plugins/vis_type_vega/public/components/vega_vis_component.tsx new file mode 100644 index 000000000000..f1a2f8cbfa8d --- /dev/null +++ b/src/plugins/vis_type_vega/public/components/vega_vis_component.tsx @@ -0,0 +1,85 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useEffect, useMemo, useRef } from 'react'; +import { EuiResizeObserver } from '@elastic/eui'; +import { throttle } from 'lodash'; + +import { IInterpreterRenderHandlers } from 'src/plugins/expressions'; +import { createVegaVisualization } from '../vega_visualization'; +import { VegaVisualizationDependencies } from '../plugin'; +import { VegaParser } from '../data_model/vega_parser'; + +import './vega_vis.scss'; + +interface VegaVisComponentProps { + deps: VegaVisualizationDependencies; + fireEvent: IInterpreterRenderHandlers['event']; + renderComplete: () => void; + visData: VegaParser; +} + +type VegaVisController = InstanceType>; + +const VegaVisComponent = ({ visData, fireEvent, renderComplete, deps }: VegaVisComponentProps) => { + const chartDiv = useRef(null); + const visController = useRef(null); + + useEffect(() => { + if (chartDiv.current) { + const VegaVis = createVegaVisualization(deps); + visController.current = new VegaVis(chartDiv.current, fireEvent); + } + + return () => { + visController.current?.destroy(); + visController.current = null; + }; + }, [deps, fireEvent]); + + useEffect(() => { + if (visController.current) { + visController.current.render(visData).then(renderComplete); + } + }, [visData, renderComplete]); + + const updateChartSize = useMemo( + () => + throttle(() => { + if (visController.current) { + visController.current.render(visData).then(renderComplete); + } + }, 300), + [renderComplete, visData] + ); + + return ( + + {(resizeRef) => ( +
+
+
+ )} + + ); +}; + +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { VegaVisComponent as default }; diff --git a/src/plugins/vis_type_vega/public/components/vega_vis_editor.tsx b/src/plugins/vis_type_vega/public/components/vega_vis_editor.tsx index 5e770fcff556..7d669235c36b 100644 --- a/src/plugins/vis_type_vega/public/components/vega_vis_editor.tsx +++ b/src/plugins/vis_type_vega/public/components/vega_vis_editor.tsx @@ -30,6 +30,8 @@ import { VisParams } from '../vega_fn'; import { VegaHelpMenu } from './vega_help_menu'; import { VegaActionsMenu } from './vega_actions_menu'; +import './vega_editor.scss'; + const aceOptions = { maxLines: Infinity, highlightActiveLine: false, @@ -102,4 +104,6 @@ function VegaVisEditor({ stateParams, setValue }: VisOptionsProps) { ); } -export { VegaVisEditor }; +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { VegaVisEditor as default }; diff --git a/src/plugins/vis_type_vega/public/components/vega_vis_editor_lazy.tsx b/src/plugins/vis_type_vega/public/components/vega_vis_editor_lazy.tsx new file mode 100644 index 000000000000..d6c78972410e --- /dev/null +++ b/src/plugins/vis_type_vega/public/components/vega_vis_editor_lazy.tsx @@ -0,0 +1,29 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { lazy } from 'react'; + +import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisParams } from '../vega_fn'; + +const VegaVisEditor = lazy(() => import('./vega_vis_editor')); + +export const VegaVisEditorComponent = (props: VisOptionsProps) => ( + +); diff --git a/src/plugins/vis_type_vega/public/index.scss b/src/plugins/vis_type_vega/public/index.scss deleted file mode 100644 index 78d9eb61999f..000000000000 --- a/src/plugins/vis_type_vega/public/index.scss +++ /dev/null @@ -1,9 +0,0 @@ -// Prefix all styles with "vga" to avoid conflicts. -// Examples -// vgaChart -// vgaChart__legend -// vgaChart__legend--small -// vgaChart__legend-isLoading - -@import './vega_vis'; -@import './vega_editor'; diff --git a/src/plugins/vis_type_vega/public/plugin.ts b/src/plugins/vis_type_vega/public/plugin.ts index ce5c5130961c..04481685c841 100644 --- a/src/plugins/vis_type_vega/public/plugin.ts +++ b/src/plugins/vis_type_vega/public/plugin.ts @@ -35,10 +35,10 @@ import { import { createVegaFn } from './vega_fn'; import { createVegaTypeDefinition } from './vega_type'; import { IServiceSettings } from '../../maps_legacy/public'; -import './index.scss'; import { ConfigSchema } from '../config'; import { getVegaInspectorView } from './vega_inspector'; +import { getVegaVisRenderer } from './vega_vis_renderer'; /** @internal */ export interface VegaVisualizationDependencies { @@ -93,6 +93,7 @@ export class VegaPlugin implements Plugin, void> { inspector.registerView(getVegaInspectorView({ uiSettings: core.uiSettings })); expressions.registerFunction(() => createVegaFn(visualizationDependencies)); + expressions.registerRenderer(getVegaVisRenderer(visualizationDependencies)); visualizations.createBaseVisualization(createVegaTypeDefinition(visualizationDependencies)); } diff --git a/src/plugins/vis_type_vega/public/to_ast.ts b/src/plugins/vis_type_vega/public/to_ast.ts new file mode 100644 index 000000000000..a5fe8f13c3da --- /dev/null +++ b/src/plugins/vis_type_vega/public/to_ast.ts @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { buildExpression, buildExpressionFunction } from '../../expressions/public'; +import { Vis } from '../../visualizations/public'; +import { VegaExpressionFunctionDefinition, VisParams } from './vega_fn'; + +export const toExpressionAst = (vis: Vis) => { + const vega = buildExpressionFunction('vega', { + spec: vis.params.spec, + }); + + const ast = buildExpression([vega]); + + return ast.toAst(); +}; diff --git a/src/plugins/vis_type_vega/public/vega_fn.ts b/src/plugins/vis_type_vega/public/vega_fn.ts index c88b78948133..25d4e76c336b 100644 --- a/src/plugins/vis_type_vega/public/vega_fn.ts +++ b/src/plugins/vis_type_vega/public/vega_fn.ts @@ -40,21 +40,23 @@ interface Arguments { export type VisParams = Required; -interface RenderValue { +export interface RenderValue { visData: VegaParser; visType: 'vega'; visConfig: VisParams; } -export const createVegaFn = ( - dependencies: VegaVisualizationDependencies -): ExpressionFunctionDefinition< +export type VegaExpressionFunctionDefinition = ExpressionFunctionDefinition< 'vega', Input, Arguments, Output, ExecutionContext -> => ({ +>; + +export const createVegaFn = ( + dependencies: VegaVisualizationDependencies +): VegaExpressionFunctionDefinition => ({ name: 'vega', type: 'render', inputTypes: ['kibana_context', 'null'], @@ -80,7 +82,7 @@ export const createVegaFn = ( return { type: 'render', - as: 'visualization', + as: 'vega_vis', value: { visData: response, visType: 'vega', diff --git a/src/plugins/vis_type_vega/public/vega_inspector/vega_data_inspector.tsx b/src/plugins/vis_type_vega/public/vega_inspector/vega_data_inspector.tsx index 6dfa7a23c4fe..350e781dc707 100644 --- a/src/plugins/vis_type_vega/public/vega_inspector/vega_data_inspector.tsx +++ b/src/plugins/vis_type_vega/public/vega_inspector/vega_data_inspector.tsx @@ -41,7 +41,7 @@ const specLabel = i18n.translate('visTypeVega.inspector.specLabel', { defaultMessage: 'Spec', }); -export const VegaDataInspector = ({ adapters }: VegaDataInspectorProps) => { +const VegaDataInspector = ({ adapters }: VegaDataInspectorProps) => { const tabs = [ { id: 'data-viewer--id', @@ -75,3 +75,7 @@ export const VegaDataInspector = ({ adapters }: VegaDataInspectorProps) => { /> ); }; + +// default export required for React.Lazy +// eslint-disable-next-line import/no-default-export +export { VegaDataInspector as default }; diff --git a/src/plugins/vis_type_vega/public/vega_inspector/vega_inspector.tsx b/src/plugins/vis_type_vega/public/vega_inspector/vega_inspector.tsx index 83d9e467646a..4b3e48d6a37a 100644 --- a/src/plugins/vis_type_vega/public/vega_inspector/vega_inspector.tsx +++ b/src/plugins/vis_type_vega/public/vega_inspector/vega_inspector.tsx @@ -16,14 +16,17 @@ * specific language governing permissions and limitations * under the License. */ -import React from 'react'; +import React, { lazy, Suspense } from 'react'; +import { EuiLoadingSpinner } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { IUiSettingsClient } from 'kibana/public'; -import { VegaAdapter } from './vega_adapter'; -import { VegaDataInspector, VegaDataInspectorProps } from './vega_data_inspector'; import { KibanaContextProvider } from '../../../kibana_react/public'; import { Adapters, RequestAdapter, InspectorViewDescription } from '../../../inspector/public'; +import { VegaAdapter } from './vega_adapter'; +import type { VegaDataInspectorProps } from './vega_data_inspector'; + +const VegaDataInspector = lazy(() => import('./vega_data_inspector')); export interface VegaInspectorAdapters extends Adapters { requests: RequestAdapter; @@ -46,7 +49,9 @@ export const getVegaInspectorView = (dependencies: VegaInspectorViewDependencies }, component: (props) => ( - + }> + + ), } as InspectorViewDescription); diff --git a/src/plugins/vis_type_vega/public/vega_type.ts b/src/plugins/vis_type_vega/public/vega_type.ts index 0496f765e5e9..17f35b75f001 100644 --- a/src/plugins/vis_type_vega/public/vega_type.ts +++ b/src/plugins/vis_type_vega/public/vega_type.ts @@ -21,22 +21,20 @@ import { i18n } from '@kbn/i18n'; import { BaseVisTypeOptions } from 'src/plugins/visualizations/public'; import { DefaultEditorSize } from '../../vis_default_editor/public'; import { VegaVisualizationDependencies } from './plugin'; -import { VegaVisEditor } from './components'; import { createVegaRequestHandler } from './vega_request_handler'; -// @ts-expect-error -import { createVegaVisualization } from './vega_visualization'; import { getDefaultSpec } from './default_spec'; import { createInspectorAdapters } from './vega_inspector'; import { VIS_EVENT_TO_TRIGGER } from '../../visualizations/public'; - +import { toExpressionAst } from './to_ast'; +import { VisParams } from './vega_fn'; import { getInfoMessage } from './components/experimental_map_vis_info'; +import { VegaVisEditorComponent } from './components/vega_vis_editor_lazy'; export const createVegaTypeDefinition = ( dependencies: VegaVisualizationDependencies -): BaseVisTypeOptions => { +): BaseVisTypeOptions => { const requestHandler = createVegaRequestHandler(dependencies); - const visualization = createVegaVisualization(dependencies); return { name: 'vega', @@ -49,13 +47,12 @@ export const createVegaTypeDefinition = ( icon: 'visVega', visConfig: { defaults: { spec: getDefaultSpec() } }, editorConfig: { - optionsTemplate: VegaVisEditor, + optionsTemplate: VegaVisEditorComponent, enableAutoApply: true, defaultSize: DefaultEditorSize.MEDIUM, }, - visualization, requestHandler, - responseHandler: 'none', + toExpressionAst, options: { showIndexSelection: false, showQueryBar: true, diff --git a/src/plugins/vis_type_vega/public/vega_view/vega_base_view.d.ts b/src/plugins/vis_type_vega/public/vega_view/vega_base_view.d.ts new file mode 100644 index 000000000000..54b96813769b --- /dev/null +++ b/src/plugins/vis_type_vega/public/vega_view/vega_base_view.d.ts @@ -0,0 +1,40 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { DataPublicPluginStart } from 'src/plugins/data/public'; +import { IInterpreterRenderHandlers } from 'src/plugins/expressions'; +import { IServiceSettings } from 'src/plugins/maps_legacy/public'; +import { VegaParser } from '../data_model/vega_parser'; + +interface VegaViewParams { + parentEl: HTMLDivElement; + fireEvent: IInterpreterRenderHandlers['event']; + vegaParser: VegaParser; + serviceSettings: IServiceSettings; + filterManager: DataPublicPluginStart['query']['filterManager']; + timefilter: DataPublicPluginStart['query']['timefilter']['timefilter']; + // findIndex: (index: string) => Promise<...>; +} + +export class VegaBaseView { + constructor(params: VegaViewParams); + init(): Promise; + onError(error: any): void; + destroy(): Promise; +} diff --git a/src/plugins/vis_type_vega/public/vega_view/vega_base_view.js b/src/plugins/vis_type_vega/public/vega_view/vega_base_view.js index 979432b2aed2..25ea77ddbccb 100644 --- a/src/plugins/vis_type_vega/public/vega_view/vega_base_view.js +++ b/src/plugins/vis_type_vega/public/vega_view/vega_base_view.js @@ -63,7 +63,7 @@ export class VegaBaseView { this._parser = opts.vegaParser; this._serviceSettings = opts.serviceSettings; this._filterManager = opts.filterManager; - this._applyFilter = opts.applyFilter; + this._fireEvent = opts.fireEvent; this._timefilter = opts.timefilter; this._findIndex = opts.findIndex; this._view = null; @@ -264,7 +264,7 @@ export class VegaBaseView { const indexId = await this._findIndex(index); const filter = esFilters.buildQueryFilter(query, indexId); - this._applyFilter({ filters: [filter] }); + this._fireEvent({ name: 'applyFilter', data: { filters: [filter] } }); } /** @@ -301,19 +301,22 @@ export class VegaBaseView { setTimeFilterHandler(start, end) { const { from, to, mode } = VegaBaseView._parseTimeRange(start, end); - this._applyFilter({ - timeFieldName: '*', - filters: [ - { - range: { - '*': { - mode, - gte: from, - lte: to, + this._fireEvent({ + name: 'applyFilter', + data: { + timeFieldName: '*', + filters: [ + { + range: { + '*': { + mode, + gte: from, + lte: to, + }, }, }, - }, - ], + ], + }, }); } diff --git a/src/plugins/vis_type_vega/public/vega_view/vega_map_view.d.ts b/src/plugins/vis_type_vega/public/vega_view/vega_map_view.d.ts new file mode 100644 index 000000000000..a1210e05f450 --- /dev/null +++ b/src/plugins/vis_type_vega/public/vega_view/vega_map_view.d.ts @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { VegaBaseView } from './vega_base_view'; + +export class VegaMapView extends VegaBaseView {} diff --git a/src/plugins/vis_type_vega/public/components/index.ts b/src/plugins/vis_type_vega/public/vega_view/vega_view.d.ts similarity index 89% rename from src/plugins/vis_type_vega/public/components/index.ts rename to src/plugins/vis_type_vega/public/vega_view/vega_view.d.ts index 90f067c778fd..c137d8222750 100644 --- a/src/plugins/vis_type_vega/public/components/index.ts +++ b/src/plugins/vis_type_vega/public/vega_view/vega_view.d.ts @@ -17,4 +17,6 @@ * under the License. */ -export { VegaVisEditor } from './vega_vis_editor'; +import { VegaBaseView } from './vega_base_view'; + +export class VegaView extends VegaBaseView {} diff --git a/src/plugins/vis_type_vega/public/vega_vis_renderer.tsx b/src/plugins/vis_type_vega/public/vega_vis_renderer.tsx new file mode 100644 index 000000000000..542f59b3dfff --- /dev/null +++ b/src/plugins/vis_type_vega/public/vega_vis_renderer.tsx @@ -0,0 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { lazy } from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; + +import { ExpressionRenderDefinition } from 'src/plugins/expressions'; +import { VisualizationContainer } from '../../visualizations/public'; +import { VegaVisualizationDependencies } from './plugin'; +import { RenderValue } from './vega_fn'; +const VegaVisComponent = lazy(() => import('./components/vega_vis_component')); + +export const getVegaVisRenderer: ( + deps: VegaVisualizationDependencies +) => ExpressionRenderDefinition = (deps) => ({ + name: 'vega_vis', + reuseDomNode: true, + render: (domNode, { visData }, handlers) => { + handlers.onDestroy(() => { + unmountComponentAtNode(domNode); + }); + + render( + + + , + domNode + ); + }, +}); diff --git a/src/plugins/vis_type_vega/public/vega_visualization.test.js b/src/plugins/vis_type_vega/public/vega_visualization.test.js index dcf172276807..837fdf2a9aea 100644 --- a/src/plugins/vis_type_vega/public/vega_visualization.test.js +++ b/src/plugins/vis_type_vega/public/vega_visualization.test.js @@ -30,8 +30,6 @@ import vegaMapGraph from './test_utils/vega_map_test.json'; import { VegaParser } from './data_model/vega_parser'; import { SearchAPI } from './data_model/search_api'; -import { createVegaTypeDefinition } from './vega_type'; - import { setInjectedVars, setData, setSavedObjects, setNotifications } from './services'; import { coreMock } from '../../../core/public/mocks'; import { dataPluginMock } from '../../data/public/mocks'; @@ -49,9 +47,7 @@ jest.mock('./lib/vega', () => ({ describe('VegaVisualizations', () => { let domNode; let VegaVisualization; - let vis; let vegaVisualizationDependencies; - let vegaVisType; let mockWidth; let mockedWidthValue; @@ -91,22 +87,12 @@ describe('VegaVisualizations', () => { getServiceSettings: mockGetServiceSettings, }; - vegaVisType = createVegaTypeDefinition(vegaVisualizationDependencies); VegaVisualization = createVegaVisualization(vegaVisualizationDependencies); }); describe('VegaVisualization - basics', () => { beforeEach(async () => { setupDOM(); - - vis = { - type: vegaVisType, - API: { - events: { - applyFilter: jest.fn(), - }, - }, - }; }); afterEach(() => { @@ -117,7 +103,7 @@ describe('VegaVisualizations', () => { test('should show vegalite graph and update on resize (may fail in dev env)', async () => { let vegaVis; try { - vegaVis = new VegaVisualization(domNode, vis); + vegaVis = new VegaVisualization(domNode, jest.fn()); const vegaParser = new VegaParser( JSON.stringify(vegaliteGraph), @@ -137,7 +123,7 @@ describe('VegaVisualizations', () => { mockedWidthValue = 256; mockedHeightValue = 256; - await vegaVis._vegaView.resize(); + await vegaVis.vegaView.resize(); expect(domNode.innerHTML).toMatchSnapshot(); } finally { @@ -148,7 +134,7 @@ describe('VegaVisualizations', () => { test('should show vega graph (may fail in dev env)', async () => { let vegaVis; try { - vegaVis = new VegaVisualization(domNode, vis); + vegaVis = new VegaVisualization(domNode, jest.fn()); const vegaParser = new VegaParser( JSON.stringify(vegaGraph), new SearchAPI({ @@ -172,7 +158,7 @@ describe('VegaVisualizations', () => { test('should show vega blank rectangle on top of a map (vegamap)', async () => { let vegaVis; try { - vegaVis = new VegaVisualization(domNode, vis); + vegaVis = new VegaVisualization(domNode, jest.fn()); const vegaParser = new VegaParser( JSON.stringify(vegaMapGraph), new SearchAPI({ diff --git a/src/plugins/vis_type_vega/public/vega_visualization.js b/src/plugins/vis_type_vega/public/vega_visualization.ts similarity index 70% rename from src/plugins/vis_type_vega/public/vega_visualization.js rename to src/plugins/vis_type_vega/public/vega_visualization.ts index 2d58e9cda60c..58c436bcd4be 100644 --- a/src/plugins/vis_type_vega/public/vega_visualization.js +++ b/src/plugins/vis_type_vega/public/vega_visualization.ts @@ -17,28 +17,34 @@ * under the License. */ import { i18n } from '@kbn/i18n'; +import { IInterpreterRenderHandlers } from 'src/plugins/expressions'; +import { VegaParser } from './data_model/vega_parser'; +import { VegaVisualizationDependencies } from './plugin'; import { getNotifications, getData, getSavedObjects } from './services'; +import type { VegaView } from './vega_view/vega_view'; -export const createVegaVisualization = ({ getServiceSettings }) => +export const createVegaVisualization = ({ getServiceSettings }: VegaVisualizationDependencies) => class VegaVisualization { - constructor(el, vis) { - this._el = el; - this._vis = vis; + private readonly dataPlugin = getData(); + private readonly savedObjectsClient = getSavedObjects(); + private vegaView: InstanceType | null = null; - this.savedObjectsClient = getSavedObjects(); - this.dataPlugin = getData(); - } + constructor( + private el: HTMLDivElement, + private fireEvent: IInterpreterRenderHandlers['event'] + ) {} /** * Find index pattern by its title, of if not given, gets default * @param {string} [index] * @returns {Promise} index id */ - async findIndex(index) { + async findIndex(index: string) { const { indexPatterns } = this.dataPlugin; let idxObj; if (index) { + // @ts-expect-error idxObj = indexPatterns.findByTitle(this.savedObjectsClient, index); if (!idxObj) { throw new Error( @@ -61,16 +67,10 @@ export const createVegaVisualization = ({ getServiceSettings }) => return idxObj.id; } - /** - * - * @param {VegaParser} visData - * @param {*} status - * @returns {Promise} - */ - async render(visData) { + async render(visData: VegaParser) { const { toasts } = getNotifications(); - if (!visData && !this._vegaView) { + if (!visData && !this.vegaView) { toasts.addWarning( i18n.translate('visTypeVega.visualization.unableToRenderWithoutDataWarningMessage', { defaultMessage: 'Unable to render without data', @@ -82,8 +82,8 @@ export const createVegaVisualization = ({ getServiceSettings }) => try { await this._render(visData); } catch (error) { - if (this._vegaView) { - this._vegaView.onError(error); + if (this.vegaView) { + this.vegaView.onError(error); } else { toasts.addError(error, { title: i18n.translate('visTypeVega.visualization.renderErrorTitle', { @@ -94,20 +94,20 @@ export const createVegaVisualization = ({ getServiceSettings }) => } } - async _render(vegaParser) { + async _render(vegaParser: VegaParser) { if (vegaParser) { // New data received, rebuild the graph - if (this._vegaView) { - await this._vegaView.destroy(); - this._vegaView = null; + if (this.vegaView) { + await this.vegaView.destroy(); + this.vegaView = null; } const serviceSettings = await getServiceSettings(); const { filterManager } = this.dataPlugin.query; const { timefilter } = this.dataPlugin.query.timefilter; const vegaViewParams = { - parentEl: this._el, - applyFilter: this._vis.API.events.applyFilter, + parentEl: this.el, + fireEvent: this.fireEvent, vegaParser, serviceSettings, filterManager, @@ -116,18 +116,17 @@ export const createVegaVisualization = ({ getServiceSettings }) => }; if (vegaParser.useMap) { - const services = { toastService: getNotifications().toasts }; const { VegaMapView } = await import('./vega_view/vega_map_view'); - this._vegaView = new VegaMapView(vegaViewParams, services); + this.vegaView = new VegaMapView(vegaViewParams); } else { - const { VegaView } = await import('./vega_view/vega_view'); - this._vegaView = new VegaView(vegaViewParams); + const { VegaView: VegaViewClass } = await import('./vega_view/vega_view'); + this.vegaView = new VegaViewClass(vegaViewParams); } - await this._vegaView.init(); + await this.vegaView?.init(); } } destroy() { - return this._vegaView && this._vegaView.destroy(); + this.vegaView?.destroy(); } }; diff --git a/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap b/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap index cbdecd4aac74..959d9031853a 100644 --- a/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap +++ b/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap @@ -13,5 +13,3 @@ exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunct exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles region_map function without buckets 1`] = `"regionmap visConfig='{\\"metric\\":{\\"accessor\\":0,\\"label\\":\\"\\",\\"format\\":{},\\"params\\":{},\\"aggType\\":\\"\\"}}' "`; exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles tile_map function 1`] = `"tilemap visConfig='{\\"metric\\":{},\\"dimensions\\":{\\"metric\\":{\\"accessor\\":0,\\"label\\":\\"\\",\\"format\\":{},\\"params\\":{},\\"aggType\\":\\"\\"},\\"geohash\\":1,\\"geocentroid\\":3}}' "`; - -exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles vega function 1`] = `"vega spec='this is a test' "`; diff --git a/src/plugins/visualizations/public/legacy/build_pipeline.test.ts b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts index c744043ed155..501a69080d93 100644 --- a/src/plugins/visualizations/public/legacy/build_pipeline.test.ts +++ b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts @@ -94,14 +94,6 @@ describe('visualize loader pipeline helpers: build pipeline', () => { uiState = {}; }); - it('handles vega function', () => { - const vis = { - params: { spec: 'this is a test' }, - }; - const actual = buildPipelineVisFunction.vega(vis.params, schemasDef, uiState); - expect(actual).toMatchSnapshot(); - }); - it('handles input_control_vis function', () => { const params = { some: 'nested', diff --git a/src/plugins/visualizations/public/legacy/build_pipeline.ts b/src/plugins/visualizations/public/legacy/build_pipeline.ts index eb431212166a..b08583c376b3 100644 --- a/src/plugins/visualizations/public/legacy/build_pipeline.ts +++ b/src/plugins/visualizations/public/legacy/build_pipeline.ts @@ -254,9 +254,6 @@ const adjustVislibDimensionFormmaters = (vis: Vis, dimensions: { y: any[] }): vo }; export const buildPipelineVisFunction: BuildPipelineVisFunction = { - vega: (params) => { - return `vega ${prepareString('spec', params.spec)}`; - }, input_control_vis: (params) => { return `input_control_vis ${prepareJson('visConfig', params)}`; }, diff --git a/test/api_integration/apis/saved_objects/export.js b/test/api_integration/apis/saved_objects/export.ts similarity index 88% rename from test/api_integration/apis/saved_objects/export.js rename to test/api_integration/apis/saved_objects/export.ts index 0c37e6b782a3..7254f3b3fcf3 100644 --- a/test/api_integration/apis/saved_objects/export.js +++ b/test/api_integration/apis/saved_objects/export.ts @@ -18,8 +18,12 @@ */ import expect from '@kbn/expect'; +import type { FtrProviderContext } from '../../ftr_provider_context'; -export default function ({ getService }) { +function ndjsonToObject(input: string) { + return input.split('\n').map((str) => JSON.parse(str)); +} +export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const es = getService('legacyEs'); const esArchiver = getService('esArchiver'); @@ -38,7 +42,7 @@ export default function ({ getService }) { }) .expect(200) .then((resp) => { - const objects = resp.text.split('\n').map(JSON.parse); + const objects = ndjsonToObject(resp.text); expect(objects).to.have.length(4); expect(objects[0]).to.have.property('id', '91200a00-9efd-11e7-acb3-3dab96693fab'); expect(objects[0]).to.have.property('type', 'index-pattern'); @@ -61,7 +65,7 @@ export default function ({ getService }) { }) .expect(200) .then((resp) => { - const objects = resp.text.split('\n').map(JSON.parse); + const objects = ndjsonToObject(resp.text); expect(objects).to.have.length(3); expect(objects[0]).to.have.property('id', '91200a00-9efd-11e7-acb3-3dab96693fab'); expect(objects[0]).to.have.property('type', 'index-pattern'); @@ -86,7 +90,7 @@ export default function ({ getService }) { }) .expect(200) .then((resp) => { - const objects = resp.text.split('\n').map(JSON.parse); + const objects = ndjsonToObject(resp.text); expect(objects).to.have.length(4); expect(objects[0]).to.have.property('id', '91200a00-9efd-11e7-acb3-3dab96693fab'); expect(objects[0]).to.have.property('type', 'index-pattern'); @@ -109,7 +113,7 @@ export default function ({ getService }) { }) .expect(200) .then((resp) => { - const objects = resp.text.split('\n').map(JSON.parse); + const objects = resp.text.split('\n').map((str) => JSON.parse(str)); expect(objects).to.have.length(4); expect(objects[0]).to.have.property('id', '91200a00-9efd-11e7-acb3-3dab96693fab'); expect(objects[0]).to.have.property('type', 'index-pattern'); @@ -133,7 +137,7 @@ export default function ({ getService }) { }) .expect(200) .then((resp) => { - const objects = resp.text.split('\n').map(JSON.parse); + const objects = ndjsonToObject(resp.text); expect(objects).to.have.length(4); expect(objects[0]).to.have.property('id', '91200a00-9efd-11e7-acb3-3dab96693fab'); expect(objects[0]).to.have.property('type', 'index-pattern'); @@ -217,6 +221,51 @@ export default function ({ getService }) { }); }); }); + + it('should export object with circular refs', async () => { + const soWithCycliRefs = [ + { + type: 'dashboard', + id: 'dashboard-a', + attributes: { + title: 'dashboard-a', + }, + references: [ + { + name: 'circular-dashboard-ref', + id: 'dashboard-b', + type: 'dashboard', + }, + ], + }, + { + type: 'dashboard', + id: 'dashboard-b', + attributes: { + title: 'dashboard-b', + }, + references: [ + { + name: 'circular-dashboard-ref', + id: 'dashboard-a', + type: 'dashboard', + }, + ], + }, + ]; + await supertest.post('/api/saved_objects/_bulk_create').send(soWithCycliRefs).expect(200); + const resp = await supertest + .post('/api/saved_objects/_export') + .send({ + includeReferencesDeep: true, + type: ['dashboard'], + }) + .expect(200); + + const objects = ndjsonToObject(resp.text); + expect(objects.find((o) => o.id === 'dashboard-a')).to.be.ok(); + expect(objects.find((o) => o.id === 'dashboard-b')).to.be.ok(); + }); }); describe('10,000 objects', () => { @@ -245,11 +294,11 @@ export default function ({ getService }) { }) .expect(200) .then((resp) => { - expect(resp.headers['content-disposition']).to.eql( + expect(resp.header['content-disposition']).to.eql( 'attachment; filename="export.ndjson"' ); - expect(resp.headers['content-type']).to.eql('application/ndjson'); - const objects = resp.text.split('\n').map(JSON.parse); + expect(resp.header['content-type']).to.eql('application/ndjson'); + const objects = ndjsonToObject(resp.text); expect(objects).to.eql([ { attributes: { @@ -304,11 +353,11 @@ export default function ({ getService }) { }) .expect(200) .then((resp) => { - expect(resp.headers['content-disposition']).to.eql( + expect(resp.header['content-disposition']).to.eql( 'attachment; filename="export.ndjson"' ); - expect(resp.headers['content-type']).to.eql('application/ndjson'); - const objects = resp.text.split('\n').map(JSON.parse); + expect(resp.header['content-type']).to.eql('application/ndjson'); + const objects = ndjsonToObject(resp.text); expect(objects).to.eql([ { attributes: { @@ -368,11 +417,11 @@ export default function ({ getService }) { }) .expect(200) .then((resp) => { - expect(resp.headers['content-disposition']).to.eql( + expect(resp.header['content-disposition']).to.eql( 'attachment; filename="export.ndjson"' ); - expect(resp.headers['content-type']).to.eql('application/ndjson'); - const objects = resp.text.split('\n').map(JSON.parse); + expect(resp.header['content-type']).to.eql('application/ndjson'); + const objects = ndjsonToObject(resp.text); expect(objects).to.eql([ { attributes: { @@ -443,7 +492,7 @@ export default function ({ getService }) { }); describe('10,001 objects', () => { - let customVisId; + let customVisId: string; before(async () => { await esArchiver.load('saved_objects/10k'); await supertest diff --git a/test/api_integration/apis/saved_objects/import.js b/test/api_integration/apis/saved_objects/import.ts similarity index 78% rename from test/api_integration/apis/saved_objects/import.js rename to test/api_integration/apis/saved_objects/import.ts index 1666df2c83e5..bdb695ef20dd 100644 --- a/test/api_integration/apis/saved_objects/import.js +++ b/test/api_integration/apis/saved_objects/import.ts @@ -19,8 +19,19 @@ import expect from '@kbn/expect'; import { join } from 'path'; +import dedent from 'dedent'; +import type { SavedObjectsImportError } from 'src/core/server'; +import type { FtrProviderContext } from '../../ftr_provider_context'; -export default function ({ getService }) { +const createConflictError = ( + object: Omit +): SavedObjectsImportError => ({ + ...object, + title: object.meta.title, + error: { type: 'conflict' }, +}); + +export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); @@ -41,11 +52,6 @@ export default function ({ getService }) { id: 'be3733a0-9efe-11e7-acb3-3dab96693fab', meta: { title: 'Requests', icon: 'dashboardApp' }, }; - const createError = (object, type) => ({ - ...object, - title: object.meta.title, - error: { type }, - }); describe('with kibana index', () => { describe('with basic data existing', () => { @@ -75,9 +81,9 @@ export default function ({ getService }) { success: false, successCount: 0, errors: [ - createError(indexPattern, 'conflict'), - createError(visualization, 'conflict'), - createError(dashboard, 'conflict'), + createConflictError(indexPattern), + createConflictError(visualization), + createConflictError(dashboard), ], }); }); @@ -128,6 +134,43 @@ export default function ({ getService }) { }); }); + it('should return 200 when importing SO with circular refs', async () => { + const fileBuffer = Buffer.from( + dedent` + {"attributes":{"title":"dashboard-b"},"id":"dashboard-b","references":[{"id":"dashboard-a","name":"circular-dashboard-ref","type":"dashboard"}],"type":"dashboard"} + {"attributes":{"title":"dashboard-a"},"id":"dashboard-a","references":[{"id":"dashboard-b","name":"circular-dashboard-ref","type":"dashboard"}],"type":"dashboard"} + `, + 'utf8' + ); + const resp = await supertest + .post('/api/saved_objects/_import') + .attach('file', fileBuffer, 'export.ndjson') + .expect(200); + + expect(resp.body).to.eql({ + success: true, + successCount: 2, + successResults: [ + { + id: 'dashboard-b', + meta: { + icon: 'dashboardApp', + title: 'dashboard-b', + }, + type: 'dashboard', + }, + { + id: 'dashboard-a', + meta: { + icon: 'dashboardApp', + title: 'dashboard-a', + }, + type: 'dashboard', + }, + ], + }); + }); + it('should return 400 when trying to import more than 10,000 objects', async () => { const fileChunks = []; for (let i = 0; i < 10001; i++) { diff --git a/test/functional/apps/discover/_doc_table.ts b/test/functional/apps/discover/_doc_table.ts index 7fc120f9ea47..d3c0fe834958 100644 --- a/test/functional/apps/discover/_doc_table.ts +++ b/test/functional/apps/discover/_doc_table.ts @@ -88,7 +88,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await footer.getVisibleText()).to.have.string(rowsHardLimit); }); - describe('expand a document row', function () { + // FLAKY: https://github.com/elastic/kibana/issues/81632 + describe.skip('expand a document row', function () { const rowToInspect = 1; beforeEach(async function () { // close the toggle if open diff --git a/test/functional/apps/management/_import_objects.js b/test/functional/apps/management/_import_objects.ts similarity index 94% rename from test/functional/apps/management/_import_objects.js rename to test/functional/apps/management/_import_objects.ts index 3941b117e6ef..0b417d7d23e9 100644 --- a/test/functional/apps/management/_import_objects.js +++ b/test/functional/apps/management/_import_objects.ts @@ -20,10 +20,14 @@ import expect from '@kbn/expect'; import path from 'path'; import { keyBy } from 'lodash'; +import { FtrProviderContext } from '../../ftr_provider_context'; -const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); +const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); +function uniq(input: T[]): T[] { + return [...new Set(input)]; +} -export default function ({ getService, getPageObjects }) { +export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); const esArchiver = getService('esArchiver'); const PageObjects = getPageObjects(['common', 'settings', 'header', 'savedObjects']); @@ -67,6 +71,24 @@ export default function ({ getService, getPageObjects }) { expect(flyout['Log Agents'].relationship).to.eql('Parent'); }); + it('should import saved objects with circular refs', async function () { + await PageObjects.savedObjects.importFile( + path.join(__dirname, 'exports', '_import_objects_circular_refs.ndjson') + ); + await PageObjects.savedObjects.checkImportSucceeded(); + await PageObjects.savedObjects.clickImportDone(); + + await PageObjects.savedObjects.clickRelationshipsByTitle('dashboard-a'); + + const flyoutContent = await PageObjects.savedObjects.getRelationshipFlyout(); + + expect(uniq(flyoutContent.map(({ relationship }) => relationship).sort())).to.eql([ + 'Child', + 'Parent', + ]); + expect(uniq(flyoutContent.map(({ title }) => title))).to.eql(['dashboard-b']); + }); + it('should provide dialog to allow the importing of saved objects with index pattern conflicts', async function () { await PageObjects.savedObjects.importFile( path.join(__dirname, 'exports', '_import_objects_conflicts.ndjson') diff --git a/test/functional/apps/management/exports/_import_objects_circular_refs.ndjson b/test/functional/apps/management/exports/_import_objects_circular_refs.ndjson new file mode 100644 index 000000000000..44297e9e8f3e --- /dev/null +++ b/test/functional/apps/management/exports/_import_objects_circular_refs.ndjson @@ -0,0 +1,2 @@ +{"attributes":{"title":"dashboard-b"},"id":"dashboard-b","references":[{"id":"dashboard-a","name":"circular-dashboard-ref","type":"dashboard"}],"type":"dashboard"} +{"attributes":{"title":"dashboard-a"},"id":"dashboard-a","references":[{"id":"dashboard-b","name":"circular-dashboard-ref","type":"dashboard"}],"type":"dashboard"} diff --git a/test/functional/apps/management/index.js b/test/functional/apps/management/index.ts similarity index 94% rename from test/functional/apps/management/index.js rename to test/functional/apps/management/index.ts index d5f0c286af7a..7365f912ea4f 100644 --- a/test/functional/apps/management/index.js +++ b/test/functional/apps/management/index.ts @@ -16,8 +16,9 @@ * specific language governing permissions and limitations * under the License. */ +import { FtrProviderContext } from '../../ftr_provider_context'; -export default function ({ getService, loadTestFile }) { +export default function ({ getService, loadTestFile }: FtrProviderContext) { const esArchiver = getService('esArchiver'); describe('management', function () { diff --git a/test/tsconfig.json b/test/tsconfig.json index a6cc2d34639b..2949a764d4b1 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -2,29 +2,19 @@ "extends": "../tsconfig.base.json", "compilerOptions": { "tsBuildInfoFile": "../build/tsbuildinfo/test", - "types": [ - "node", - "mocha", - "flot" - ] + "types": ["node", "mocha", "flot"] }, - "include": [ - "**/*", - "../typings/elastic__node_crypto.d.ts", - "typings/**/*" - ], - "exclude": [ - "plugin_functional/plugins/**/*", - "interpreter_functional/plugins/**/*" - ], + "include": ["**/*", "../typings/elastic__node_crypto.d.ts", "typings/**/*"], + "exclude": ["plugin_functional/plugins/**/*", "interpreter_functional/plugins/**/*"], "references": [ { "path": "../src/core/tsconfig.json" }, - { "path": "../src/plugins/kibana_utils/tsconfig.json" }, + { "path": "../src/plugins/inspector/tsconfig.json" }, { "path": "../src/plugins/kibana_react/tsconfig.json" }, - { "path": "../src/plugins/usage_collection/tsconfig.json" }, + { "path": "../src/plugins/kibana_usage_collection/tsconfig.json" }, + { "path": "../src/plugins/kibana_utils/tsconfig.json" }, + { "path": "../src/plugins/newsfeed/tsconfig.json" }, { "path": "../src/plugins/telemetry_collection_manager/tsconfig.json" }, { "path": "../src/plugins/telemetry/tsconfig.json" }, - { "path": "../src/plugins/kibana_usage_collection/tsconfig.json" }, - { "path": "../src/plugins/newsfeed/tsconfig.json" } + { "path": "../src/plugins/usage_collection/tsconfig.json" } ] } diff --git a/tsconfig.json b/tsconfig.json index 49a45f370701..30b38d0fc2dd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,18 +6,18 @@ "include": ["kibana.d.ts", "src/**/*", "typings/**/*", "test_utils/**/*"], "exclude": [ "src/**/__fixtures__/**/*", - "src/test_utils/**/*", "src/core/**/*", + "src/plugins/inspector/**/*", "src/plugins/kibana_legacy/**/*", - "src/plugins/kibana_usage_collection/**/*", - "src/plugins/kibana_utils/**/*", "src/plugins/kibana_react/**/*", + "src/plugins/kibana_usage_collection/**/*", "src/plugins/kibana_utils/**/*", "src/plugins/newsfeed/**/*", - "src/plugins/telemetry/**/*", "src/plugins/telemetry_collection_manager/**/*", + "src/plugins/telemetry/**/*", "src/plugins/url_forwarding/**/*", - "src/plugins/usage_collection/**/*" + "src/plugins/usage_collection/**/*", + "src/test_utils/**/*" // In the build we actually exclude **/public/**/* from this config so that // we can run the TSC on both this and the .browser version of this config // file, but if we did it during development IDEs would not be able to find @@ -25,14 +25,15 @@ // "src/**/public/**/*" ], "references": [ - { "path": "./src/test_utils/tsconfig.json" }, { "path": "./src/core/tsconfig.json" }, - { "path": "./src/plugins/kibana_utils/tsconfig.json" }, + { "path": "./src/plugins/inspector/tsconfig.json" }, { "path": "./src/plugins/kibana_react/tsconfig.json" }, - { "path": "./src/plugins/usage_collection/tsconfig.json" }, + { "path": "./src/plugins/kibana_usage_collection/tsconfig.json" }, + { "path": "./src/plugins/kibana_utils/tsconfig.json" }, + { "path": "./src/plugins/newsfeed/tsconfig.json" }, { "path": "./src/plugins/telemetry_collection_manager/tsconfig.json" }, { "path": "./src/plugins/telemetry/tsconfig.json" }, - { "path": "./src/plugins/kibana_usage_collection/tsconfig.json" }, - { "path": "./src/plugins/newsfeed/tsconfig.json" } + { "path": "./src/plugins/usage_collection/tsconfig.json" }, + { "path": "./src/test_utils/tsconfig.json" } ] } diff --git a/tsconfig.refs.json b/tsconfig.refs.json index 624776181258..c16e7a5e1b0f 100644 --- a/tsconfig.refs.json +++ b/tsconfig.refs.json @@ -2,15 +2,16 @@ "include": [], "references": [ { "path": "./src/core/tsconfig.json" }, - { "path": "./src/test_utils/tsconfig.json" }, + { "path": "./src/plugins/inspector/tsconfig.json" }, { "path": "./src/plugins/kibana_legacy/tsconfig.json" }, { "path": "./src/plugins/kibana_react/tsconfig.json" }, { "path": "./src/plugins/kibana_usage_collection/tsconfig.json" }, { "path": "./src/plugins/kibana_utils/tsconfig.json" }, { "path": "./src/plugins/newsfeed/tsconfig.json" }, - { "path": "./src/plugins/telemetry/tsconfig.json" }, { "path": "./src/plugins/telemetry_collection_manager/tsconfig.json" }, + { "path": "./src/plugins/telemetry/tsconfig.json" }, { "path": "./src/plugins/url_forwarding/tsconfig.json" }, - { "path": "./src/plugins/usage_collection/tsconfig.json" } + { "path": "./src/plugins/usage_collection/tsconfig.json" }, + { "path": "./src/test_utils/tsconfig.json" } ] } diff --git a/typings/index.d.ts b/typings/index.d.ts index db6530d3f9e0..fc16aa32fe3f 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -34,22 +34,3 @@ declare module '*.svg' { // eslint-disable-next-line import/no-default-export export default content; } - -type MethodKeysOf = { - [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never; -}[keyof T]; - -type PublicMethodsOf = Pick>; - -type MockedKeys = { [P in keyof T]: jest.Mocked }; - -type DeeplyMockedKeys = { - [P in keyof T]: T[P] extends (...args: any[]) => any - ? jest.MockInstance, Parameters> - : DeeplyMockedKeys; -} & - T; - -type Writable = { - -readonly [K in keyof T]: T[K]; -}; diff --git a/vars/getCheckoutInfo.groovy b/vars/getCheckoutInfo.groovy index 32a7b054bfd1..f9d797f8127c 100644 --- a/vars/getCheckoutInfo.groovy +++ b/vars/getCheckoutInfo.groovy @@ -2,6 +2,7 @@ def call(branchOverride) { def repoInfo = [ branch: branchOverride ?: env.ghprbSourceBranch, targetBranch: env.ghprbTargetBranch, + targetsTrackedBranch: true ] if (repoInfo.branch == null) { @@ -35,6 +36,10 @@ def call(branchOverride) { label: "determining merge point with '${repoInfo.targetBranch}' at origin", returnStdout: true ).trim() + + def pkgJson = readFile("package.json") + def releaseBranch = toJSON(pkgJson).branch + repoInfo.targetsTrackedBranch = releaseBranch == repoInfo.targetBranch } print "repoInfo: ${repoInfo}" diff --git a/vars/githubPr.groovy b/vars/githubPr.groovy index fd5412c90568..546a6785ac2f 100644 --- a/vars/githubPr.groovy +++ b/vars/githubPr.groovy @@ -149,7 +149,7 @@ def getTestFailuresMessage() { def getBuildStatusIncludingMetrics() { def status = buildUtils.getBuildStatus() - if (status == 'SUCCESS' && !ciStats.getMetricsSuccess()) { + if (status == 'SUCCESS' && shouldCheckCiMetricSuccess() && !ciStats.getMetricsSuccess()) { return 'FAILURE' } @@ -297,3 +297,12 @@ def getFailedSteps() { step.displayName != 'Check out from version control' } } + +def shouldCheckCiMetricSuccess() { + // disable ciMetrics success check when a PR is targetting a non-tracked branch + if (buildState.has('checkoutInfo') && !buildState.get('checkoutInfo').targetsTrackedBranch) { + return false + } + + return true +} diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index 2b712a206bfc..8993213d91f2 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -27,7 +27,7 @@ "xpack.idxMgmt": "plugins/index_management", "xpack.indexLifecycleMgmt": "plugins/index_lifecycle_management", "xpack.infra": "plugins/infra", - "xpack.ingestManager": "plugins/ingest_manager", + "xpack.fleet": "plugins/ingest_manager", "xpack.ingestPipelines": "plugins/ingest_pipelines", "xpack.lens": "plugins/lens", "xpack.licenseMgmt": "plugins/license_management", @@ -56,9 +56,7 @@ "xpack.watcher": "plugins/watcher", "xpack.observability": "plugins/observability" }, - "exclude": [ - "examples" - ], + "exclude": ["examples"], "translations": [ "plugins/translations/translations/zh-CN.json", "plugins/translations/translations/ja-JP.json" diff --git a/x-pack/package.json b/x-pack/package.json index 65aa654745ce..fcf804a1fddd 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -183,6 +183,7 @@ "jest": "^26.4.2", "jest-circus": "^26.4.2", "jest-cli": "^26.4.2", + "jest-silent-reporter": "^0.2.1", "jest-styled-components": "^7.0.2", "js-search": "^1.4.3", "jsdom": "13.1.0", diff --git a/x-pack/plugins/actions/server/actions_client.mock.ts b/x-pack/plugins/actions/server/actions_client.mock.ts index 0c16c88ad7a8..2c2a818eb6eb 100644 --- a/x-pack/plugins/actions/server/actions_client.mock.ts +++ b/x-pack/plugins/actions/server/actions_client.mock.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ActionsClient } from './actions_client'; type ActionsClientContract = PublicMethodsOf; diff --git a/x-pack/plugins/actions/server/authorization/actions_authorization.mock.ts b/x-pack/plugins/actions/server/authorization/actions_authorization.mock.ts index 6b55c18241c5..59887f405a7d 100644 --- a/x-pack/plugins/actions/server/authorization/actions_authorization.mock.ts +++ b/x-pack/plugins/actions/server/authorization/actions_authorization.mock.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ActionsAuthorization } from './actions_authorization'; export type ActionsAuthorizationMock = jest.Mocked>; diff --git a/x-pack/plugins/actions/server/index.ts b/x-pack/plugins/actions/server/index.ts index bbe298c0585a..39bfe2c2820e 100644 --- a/x-pack/plugins/actions/server/index.ts +++ b/x-pack/plugins/actions/server/index.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { PluginInitializerContext, PluginConfigDescriptor } from '../../../../src/core/server'; import { ActionsPlugin } from './plugin'; import { configSchema } from './config'; diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index 0015b417d72c..af70fbf2ec89 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Logger, KibanaRequest } from 'src/core/server'; import { validateParams, validateConfig, validateSecrets } from './validate_with_schema'; import { diff --git a/x-pack/plugins/actions/server/lib/license_state.ts b/x-pack/plugins/actions/server/lib/license_state.ts index 902fadb3da17..e8cd0aa841cd 100644 --- a/x-pack/plugins/actions/server/lib/license_state.ts +++ b/x-pack/plugins/actions/server/lib/license_state.ts @@ -5,6 +5,7 @@ */ import { i18n } from '@kbn/i18n'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Observable, Subscription } from 'rxjs'; import { assertNever } from '@kbn/std'; import { ILicense } from '../../../licensing/common/types'; diff --git a/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts b/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts index 18cbd9f9c5fa..c8e268465159 100644 --- a/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts +++ b/x-pack/plugins/actions/server/lib/task_runner_factory.test.ts @@ -145,6 +145,12 @@ test('executes the task by calling the executor with proper parameters', async ( url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, }, }); }); @@ -271,6 +277,12 @@ test('uses API key when provided', async () => { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, }, }); }); @@ -310,6 +322,12 @@ test(`doesn't use API key when not provided`, async () => { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, }, }); }); diff --git a/x-pack/plugins/actions/server/lib/task_runner_factory.ts b/x-pack/plugins/actions/server/lib/task_runner_factory.ts index aeeeb4ed7d52..93ae5a2c807f 100644 --- a/x-pack/plugins/actions/server/lib/task_runner_factory.ts +++ b/x-pack/plugins/actions/server/lib/task_runner_factory.ts @@ -102,6 +102,12 @@ export class TaskRunnerFactory { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, } as unknown) as KibanaRequest; let executorResult: ActionTypeExecutorResult; diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index 668e8b849b8a..d0c7bf350504 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { first, map } from 'rxjs/operators'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { diff --git a/x-pack/plugins/actions/server/routes/_mock_handler_arguments.ts b/x-pack/plugins/actions/server/routes/_mock_handler_arguments.ts index 06f65ff23106..7b8b5f7b7f0e 100644 --- a/x-pack/plugins/actions/server/routes/_mock_handler_arguments.ts +++ b/x-pack/plugins/actions/server/routes/_mock_handler_arguments.ts @@ -6,6 +6,7 @@ import { RequestHandlerContext, KibanaRequest, KibanaResponseFactory } from 'kibana/server'; import { identity } from 'lodash'; +import type { MethodKeysOf } from '@kbn/utility-types'; import { httpServerMock } from '../../../../../src/core/server/mocks'; import { ActionType } from '../../common'; import { ActionsClientMock, actionsClientMock } from '../actions_client.mock'; diff --git a/x-pack/plugins/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts index a8db8bfd7344..1867815bd5f9 100644 --- a/x-pack/plugins/actions/server/types.ts +++ b/x-pack/plugins/actions/server/types.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ActionTypeRegistry } from './action_type_registry'; import { PluginSetupContract, PluginStartContract } from './plugin'; import { ActionsClient } from './actions_client'; diff --git a/x-pack/plugins/alerts/public/alert_navigation_registry/alert_navigation_registry.mock.ts b/x-pack/plugins/alerts/public/alert_navigation_registry/alert_navigation_registry.mock.ts index 792bd8e885ea..c800579fddff 100644 --- a/x-pack/plugins/alerts/public/alert_navigation_registry/alert_navigation_registry.mock.ts +++ b/x-pack/plugins/alerts/public/alert_navigation_registry/alert_navigation_registry.mock.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { AlertNavigationRegistry } from './alert_navigation_registry'; type Schema = PublicMethodsOf; diff --git a/x-pack/plugins/alerts/server/alert_type_registry.mock.ts b/x-pack/plugins/alerts/server/alert_type_registry.mock.ts index b6b36e4d4b7e..39d15eba014c 100644 --- a/x-pack/plugins/alerts/server/alert_type_registry.mock.ts +++ b/x-pack/plugins/alerts/server/alert_type_registry.mock.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { AlertTypeRegistry } from './alert_type_registry'; type Schema = PublicMethodsOf; diff --git a/x-pack/plugins/alerts/server/alerts_client.mock.ts b/x-pack/plugins/alerts/server/alerts_client.mock.ts index b28e9f805f72..c9063457fac8 100644 --- a/x-pack/plugins/alerts/server/alerts_client.mock.ts +++ b/x-pack/plugins/alerts/server/alerts_client.mock.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { AlertsClient } from './alerts_client'; type Schema = PublicMethodsOf; diff --git a/x-pack/plugins/alerts/server/alerts_client_factory.test.ts b/x-pack/plugins/alerts/server/alerts_client_factory.test.ts index 55c2f3ddd18a..4e457cdb12bd 100644 --- a/x-pack/plugins/alerts/server/alerts_client_factory.test.ts +++ b/x-pack/plugins/alerts/server/alerts_client_factory.test.ts @@ -60,6 +60,12 @@ const fakeRequest = ({ url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, getSavedObjectsClient: () => savedObjectsClient, } as unknown) as Request; diff --git a/x-pack/plugins/alerts/server/authorization/alerts_authorization.mock.ts b/x-pack/plugins/alerts/server/authorization/alerts_authorization.mock.ts index 3728daa946d5..171e3978d0d0 100644 --- a/x-pack/plugins/alerts/server/authorization/alerts_authorization.mock.ts +++ b/x-pack/plugins/alerts/server/authorization/alerts_authorization.mock.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { AlertsAuthorization } from './alerts_authorization'; type Schema = PublicMethodsOf; diff --git a/x-pack/plugins/alerts/server/index.ts b/x-pack/plugins/alerts/server/index.ts index 72d3a6522056..1e442c5196cf 100644 --- a/x-pack/plugins/alerts/server/index.ts +++ b/x-pack/plugins/alerts/server/index.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { AlertsClient as AlertsClientClass } from './alerts_client'; import { PluginInitializerContext } from '../../../../src/core/server'; import { AlertingPlugin } from './plugin'; diff --git a/x-pack/plugins/alerts/server/plugin.test.ts b/x-pack/plugins/alerts/server/plugin.test.ts index b13a1c62f660..ece7d31d2f7f 100644 --- a/x-pack/plugins/alerts/server/plugin.test.ts +++ b/x-pack/plugins/alerts/server/plugin.test.ts @@ -149,6 +149,12 @@ describe('Alerting Plugin', () => { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, getSavedObjectsClient: jest.fn(), } as unknown) as KibanaRequest; await startContract.getAlertsClientWithRequest(fakeRequest); diff --git a/x-pack/plugins/alerts/server/plugin.ts b/x-pack/plugins/alerts/server/plugin.ts index 03302d5e6e7d..565b2992b1f7 100644 --- a/x-pack/plugins/alerts/server/plugin.ts +++ b/x-pack/plugins/alerts/server/plugin.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { first, map } from 'rxjs/operators'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { SecurityPluginSetup } from '../../security/server'; diff --git a/x-pack/plugins/alerts/server/routes/_mock_handler_arguments.ts b/x-pack/plugins/alerts/server/routes/_mock_handler_arguments.ts index 548495866ec2..3d13fc65ab26 100644 --- a/x-pack/plugins/alerts/server/routes/_mock_handler_arguments.ts +++ b/x-pack/plugins/alerts/server/routes/_mock_handler_arguments.ts @@ -11,6 +11,7 @@ import { ILegacyClusterClient, } from 'kibana/server'; import { identity } from 'lodash'; +import type { MethodKeysOf } from '@kbn/utility-types'; import { httpServerMock } from '../../../../../src/core/server/mocks'; import { alertsClientMock, AlertsClientMock } from '../alerts_client.mock'; import { AlertType } from '../../common'; diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts index 8e345d6ff66a..17d5fcd31b74 100644 --- a/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerts/server/task_runner/task_runner.test.ts @@ -364,6 +364,12 @@ describe('Task Runner', () => { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, }); expect(actionsClient.enqueueExecution).toHaveBeenCalledTimes(1); expect(actionsClient.enqueueExecution.mock.calls[0]).toMatchInlineSnapshot(` @@ -662,6 +668,12 @@ describe('Task Runner', () => { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, }); }); @@ -694,6 +706,12 @@ describe('Task Runner', () => { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, }); }); diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner.ts b/x-pack/plugins/alerts/server/task_runner/task_runner.ts index 7da16717aef9..76125da20d55 100644 --- a/x-pack/plugins/alerts/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerts/server/task_runner/task_runner.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { pickBy, mapValues, without } from 'lodash'; import { Logger, KibanaRequest } from '../../../../../src/core/server'; import { TaskRunnerContext } from './task_runner_factory'; @@ -101,6 +101,12 @@ export class TaskRunner { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, } as unknown) as KibanaRequest; } diff --git a/x-pack/plugins/alerts/server/task_runner/task_runner_factory.ts b/x-pack/plugins/alerts/server/task_runner/task_runner_factory.ts index 944c4dc64ce7..df6f306c6ccc 100644 --- a/x-pack/plugins/alerts/server/task_runner/task_runner_factory.ts +++ b/x-pack/plugins/alerts/server/task_runner/task_runner_factory.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Logger, KibanaRequest, ISavedObjectsRepository } from '../../../../../src/core/server'; import { RunContext } from '../../../task_manager/server'; import { EncryptedSavedObjectsClient } from '../../../encrypted_saved_objects/server'; diff --git a/x-pack/plugins/alerts/server/types.ts b/x-pack/plugins/alerts/server/types.ts index 74153d1ca6b1..42eef9bba10e 100644 --- a/x-pack/plugins/alerts/server/types.ts +++ b/x-pack/plugins/alerts/server/types.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { AlertInstance } from './alert_instance'; import { AlertTypeRegistry as OrigAlertTypeRegistry } from './alert_type_registry'; import { PluginSetupContract, PluginStartContract } from './plugin'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/index.ts b/x-pack/plugins/apm/common/ui_settings_keys.ts similarity index 65% rename from x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/index.ts rename to x-pack/plugins/apm/common/ui_settings_keys.ts index fe97b85778a5..38922fa445a4 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/index.ts +++ b/x-pack/plugins/apm/common/ui_settings_keys.ts @@ -4,4 +4,5 @@ * you may not use this file except in compliance with the Elastic License. */ -export { serializePhaseWithAllocation } from './serialize_phase_with_allocation'; +export const enableCorrelations = 'apm:enableCorrelations'; +export const enableServiceOverview = 'apm:enableServiceOverview'; diff --git a/x-pack/plugins/apm/e2e/cypress/integration/snapshots.js b/x-pack/plugins/apm/e2e/cypress/integration/snapshots.js index c37326ee5b19..d77d3ba0bec0 100644 --- a/x-pack/plugins/apm/e2e/cypress/integration/snapshots.js +++ b/x-pack/plugins/apm/e2e/cypress/integration/snapshots.js @@ -1,3 +1,3 @@ module.exports = { - "__version": "4.9.0" + "__version": "5.5.0" } diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_dashboard.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_dashboard.ts index a8edf862ab25..d8540c3f3efd 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_dashboard.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_dashboard.ts @@ -26,7 +26,7 @@ Given(`a user browses the APM UI application for RUM Data`, () => { }); Then(`should have correct client metrics`, () => { - const metrics = ['4 ms', '58 ms', '55']; + const metrics = ['80 ms', '4 ms', '76 ms', '55']; verifyClientMetrics(metrics, true); }); diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_filters.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_filters.ts index 5c2109bb518c..88287286c66c 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_filters.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_filters.ts @@ -56,7 +56,9 @@ Then(/^it filters the client metrics "([^"]*)"$/, (filterName) => { cy.get('.euiStat__title-isLoading').should('not.be.visible'); const data = - filterName === 'os' ? ['5 ms', '64 ms', '8'] : ['4 ms', '55 ms', '28']; + filterName === 'os' + ? ['82 ms', '5 ms', '77 ms', '8'] + : ['75 ms', '4 ms', '71 ms', '28']; verifyClientMetrics(data, true); diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/js_errors.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/js_errors.ts index 0dbefb73e68c..9e10e2fd5991 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/js_errors.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/js_errors.ts @@ -12,12 +12,7 @@ Then(`it displays list of relevant js errors`, () => { cy.get('.euiBasicTable-loading').should('not.be.visible'); cy.get('.euiStat__title-isLoading').should('not.be.visible'); - getDataTestSubj('uxJsErrorsTotal').should('have.text', 'Total errors110'); - - getDataTestSubj('uxJsErrorRate').should( - 'have.text', - 'Error rate100 %Error rate 100 %' - ); + getDataTestSubj('uxJsErrorsTotal').should('have.text', 'Total errors112'); getDataTestSubj('uxJsErrorTable').within(() => { cy.get('tr.euiTableRow', DEFAULT_TIMEOUT) diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/percentile_select.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/percentile_select.ts index 314254883b2f..44802bbce620 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/percentile_select.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/percentile_select.ts @@ -16,7 +16,7 @@ When('the user changes the selected percentile', () => { }); Then(`it displays client metric related to that percentile`, () => { - const metrics = ['14 ms', '131 ms', '55']; + const metrics = ['165 ms', '14 ms', '151 ms', '55']; verifyClientMetrics(metrics, false); diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/service_name_filter.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/service_name_filter.ts index 20c6a3fb72aa..609d0d18f5bc 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/service_name_filter.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/service_name_filter.ts @@ -15,7 +15,7 @@ When('the user changes the selected service name', () => { }); Then(`it displays relevant client metrics`, () => { - const metrics = ['4 ms', '58 ms', '55']; + const metrics = ['80 ms', '4 ms', '76 ms', '55']; verifyClientMetrics(metrics, false); }); diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/url_search_filter.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/url_search_filter.ts index 75b9a9c80416..3dc98625baf8 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/url_search_filter.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/url_search_filter.ts @@ -24,8 +24,8 @@ Then(`it displays top pages in the suggestion popover`, () => { listOfUrls.should('have.length', 5); const actualUrlsText = [ - 'http://opbeans-node:3000/dashboardPage views: 17Page load duration: 109 ms', - 'http://opbeans-node:3000/ordersPage views: 14Page load duration: 72 ms', + 'http://opbeans-node:3000/dashboardTotal page views: 17Page load duration: 109 ms (median)', + 'http://opbeans-node:3000/ordersTotal page views: 14Page load duration: 72 ms (median)', ]; cy.get('li.euiSelectableListItem') @@ -55,7 +55,7 @@ Then(`it should filter results based on query`, () => { listOfUrls.should('have.length', 1); const actualUrlsText = [ - 'http://opbeans-node:3000/customersPage views: 10Page load duration: 76 ms', + 'http://opbeans-node:3000/customersTotal page views: 10Page load duration: 76 ms (median)', ]; cy.get('li.euiSelectableListItem') diff --git a/x-pack/plugins/apm/e2e/yarn.lock b/x-pack/plugins/apm/e2e/yarn.lock index fc63189e97ea..87331c72e802 100644 --- a/x-pack/plugins/apm/e2e/yarn.lock +++ b/x-pack/plugins/apm/e2e/yarn.lock @@ -689,14 +689,6 @@ "@babel/plugin-transform-react-jsx-self" "^7.0.0" "@babel/plugin-transform-react-jsx-source" "^7.0.0" -"@babel/runtime-corejs3@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.10.4.tgz#f29fc1990307c4c57b10dbd6ce667b27159d9e0d" - integrity sha512-BFlgP2SoLO9HJX9WBwN67gHWMBhDX/eDz64Jajd6mR/UAUzqrNMm99d4qHnVaKscAElZoFiPv+JpR/Siud5lXw== - dependencies: - core-js-pure "^3.0.0" - regenerator-runtime "^0.13.4" - "@babel/runtime@7.3.1": version "7.3.1" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.1.tgz#574b03e8e8a9898eaf4a872a92ea20b7846f6f2a" @@ -760,7 +752,7 @@ lodash.clonedeep "4.5.0" watchify "3.11.1" -"@cypress/listr-verbose-renderer@0.4.1": +"@cypress/listr-verbose-renderer@^0.4.1": version "0.4.1" resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a" integrity sha1-p3SS9LEdzHxEajSz4ochr9M8ZCo= @@ -770,7 +762,7 @@ date-fns "^1.27.2" figures "^1.7.0" -"@cypress/request@2.88.5": +"@cypress/request@^2.88.5": version "2.88.5" resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.5.tgz#8d7ecd17b53a849cfd5ab06d5abe7d84976375d7" integrity sha512-TzEC1XMi1hJkywWpRfD2clreTa/Z+lOrXDCxxBTBPEcY5azdPi56A6Xw+O4tWJnaJH3iIE7G5aDXZC6JgRZLcA== @@ -819,7 +811,7 @@ debug "4.1.1" lodash "4.17.15" -"@cypress/xvfb@1.2.4": +"@cypress/xvfb@^1.2.4": version "1.2.4" resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a" integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q== @@ -884,22 +876,22 @@ resolved "https://registry.yarnpkg.com/@types/cypress-cucumber-preprocessor/-/cypress-cucumber-preprocessor-1.14.1.tgz#9787f4e89553ebc6359ce157a26ad51ed14aa98b" integrity sha512-CpYsiQ49UrOmadhFg0G5RkokPUmGGctD01mOWjNxFxHw5VgIRv33L2RyFHL8klaAI4HaedGN3Tcj4HTQ65hn+A== -"@types/node@^14.0.14": - version "14.0.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.14.tgz#24a0b5959f16ac141aeb0c5b3cd7a15b7c64cbce" - integrity sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ== +"@types/node@>=10.17.17 <10.20.0": + version "10.17.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.43.tgz#af70c6de04841d9216fc2b58e427c8a823b83418" + integrity sha512-F7xV2kxZGb3seVP3UQt3msHcoDCtDi8WNO/UCzNLhRwaYVT4yJO1ndcV+vCTnY+jiAVqyLZq/VJbRE/AhwqEag== "@types/retry@^0.12.0": version "0.12.0" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== -"@types/sinonjs__fake-timers@6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.1.tgz#681df970358c82836b42f989188d133e218c458e" - integrity sha512-yYezQwGWty8ziyYLdZjwxyMb0CZR49h8JALHGrxjQHWlqGgc8kLdHEgWrgL0uZ29DMvEVBDnHU2Wg36zKSIUtA== +"@types/sinonjs__fake-timers@^6.0.1": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz#3a84cf5ec3249439015e14049bd3161419bf9eae" + integrity sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg== -"@types/sizzle@2.3.2": +"@types/sizzle@^2.3.2": version "2.3.2" resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.2.tgz#a811b8c18e2babab7d542b3365887ae2e4d9de47" integrity sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg== @@ -1189,15 +1181,23 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -arch@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.2.tgz#0c52bbe7344bb4fa260c443d2cbad9c00ff2f0bf" - integrity sha512-NTBIIbAfkJeIletyABbVtdPgeKfDafR+1mZV/AyyfC1UkVkp9iUjV+wwmqtUgphHYajbI86jejBJp5e+jkGTiQ== +arch@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== argparse@^1.0.7: version "1.0.10" @@ -1289,6 +1289,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -1376,6 +1381,11 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== +binary-extensions@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== + bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" @@ -1383,6 +1393,11 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +blob-util@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" + integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== + bluebird@3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" @@ -1393,7 +1408,7 @@ bluebird@3.7.1: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg== -bluebird@3.7.2, bluebird@^3.4.1, bluebird@^3.5.5: +bluebird@^3.4.1, bluebird@^3.5.5, bluebird@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -1427,7 +1442,7 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.1: +braces@^3.0.1, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1712,7 +1727,7 @@ cached-path-relative@^1.0.0, cached-path-relative@^1.0.2: resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.2.tgz#a13df4196d26776220cc3356eb147a52dba2c6db" integrity sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg== -cachedir@2.3.0: +cachedir@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== @@ -1744,15 +1759,6 @@ chai@^4.1.2: pathval "^1.1.0" type-detect "^4.0.5" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -1764,6 +1770,15 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chalk@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" @@ -1772,12 +1787,20 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= -check-more-types@2.24.0: +check-more-types@2.24.0, check-more-types@^2.24.0: version "2.24.0" resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= @@ -1801,6 +1824,21 @@ chokidar@^2.0.4, chokidar@^2.1.1, chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" +chokidar@^3.4.1: + version "3.4.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" + integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.1.2" + chownr@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" @@ -1862,13 +1900,13 @@ cli-spinners@^2.2.0: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" integrity sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ== -cli-table3@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" - integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== +cli-table3@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.0.tgz#b7b1bc65ca8e7b5cef9124e13dc2b21e2ce4faee" + integrity sha512-gnB85c3MGC7Nm9I/FkiasNBOKjOiO1RNuXXarQms37q4QMpWdlbBgD/VnOStA2faG1dpXMv31RFApjX1/QdgWQ== dependencies: object-assign "^4.1.0" - string-width "^2.1.1" + string-width "^4.2.0" optionalDependencies: colors "^1.1.2" @@ -1978,17 +2016,17 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== - commander@^2.19.0, commander@^2.20.0, commander@^2.9.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -common-tags@1.8.0: +commander@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +common-tags@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw== @@ -2073,11 +2111,6 @@ core-js-compat@^3.1.1: browserslist "^4.8.3" semver "7.0.0" -core-js-pure@^3.0.0: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" - integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== - core-js@^2.4.0: version "2.6.11" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" @@ -2129,16 +2162,14 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-spawn@^6.0.0: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== +cross-spawn@^7.0.0: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: version "3.12.0" @@ -2234,48 +2265,49 @@ cypress-cucumber-preprocessor@^2.5.2: minimist "^1.2.0" through "^2.3.8" -cypress@^4.9.0: - version "4.9.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-4.9.0.tgz#c188a3864ddf841c0fdc81a9e4eff5cf539cd1c1" - integrity sha512-qGxT5E0j21FPryzhb0OBjCdhoR/n1jXtumpFFSBPYWsaZZhNaBvc3XlBUDEZKkkXPsqUFYiyhWdHN/zo0t5FcA== - dependencies: - "@cypress/listr-verbose-renderer" "0.4.1" - "@cypress/request" "2.88.5" - "@cypress/xvfb" "1.2.4" - "@types/sinonjs__fake-timers" "6.0.1" - "@types/sizzle" "2.3.2" - arch "2.1.2" - bluebird "3.7.2" - cachedir "2.3.0" - chalk "2.4.2" - check-more-types "2.24.0" - cli-table3 "0.5.1" - commander "4.1.1" - common-tags "1.8.0" - debug "4.1.1" - eventemitter2 "6.4.2" - execa "1.0.0" - executable "4.1.1" - extract-zip "1.7.0" - fs-extra "8.1.0" - getos "3.2.1" - is-ci "2.0.0" - is-installed-globally "0.3.2" - lazy-ass "1.6.0" - listr "0.14.3" - lodash "4.17.15" - log-symbols "3.0.0" - minimist "1.2.5" - moment "2.26.0" - ospath "1.2.2" - pretty-bytes "5.3.0" - ramda "0.26.1" - request-progress "3.0.0" - supports-color "7.1.0" - tmp "0.1.0" - untildify "4.0.0" - url "0.11.0" - yauzl "2.10.0" +cypress@^5.0.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-5.5.0.tgz#1da0355794a43247f8a80cb7f505e83e1cf847cb" + integrity sha512-UHEiTca8AUTevbT2pWkHQlxoHtXmbq+h6Eiu/Mz8DqpNkF98zjTBLv/HFiKJUU5rQzp9EwSWtms33p5TWCJ8tQ== + dependencies: + "@cypress/listr-verbose-renderer" "^0.4.1" + "@cypress/request" "^2.88.5" + "@cypress/xvfb" "^1.2.4" + "@types/sinonjs__fake-timers" "^6.0.1" + "@types/sizzle" "^2.3.2" + arch "^2.1.2" + blob-util "2.0.2" + bluebird "^3.7.2" + cachedir "^2.3.0" + chalk "^4.1.0" + check-more-types "^2.24.0" + cli-table3 "~0.6.0" + commander "^4.1.1" + common-tags "^1.8.0" + debug "^4.1.1" + eventemitter2 "^6.4.2" + execa "^4.0.2" + executable "^4.1.1" + extract-zip "^1.7.0" + fs-extra "^9.0.1" + getos "^3.2.1" + is-ci "^2.0.0" + is-installed-globally "^0.3.2" + lazy-ass "^1.6.0" + listr "^0.14.3" + lodash "^4.17.19" + log-symbols "^4.0.0" + minimist "^1.2.5" + moment "^2.27.0" + ospath "^1.2.2" + pretty-bytes "^5.4.1" + ramda "~0.26.1" + request-progress "^3.0.0" + supports-color "^7.2.0" + tmp "~0.2.1" + untildify "^4.0.0" + url "^0.11.0" + yauzl "^2.10.0" d@1, d@^1.0.1: version "1.0.1" @@ -2330,18 +2362,18 @@ debug@^3.0.1, debug@^3.1.0: dependencies: ms "^2.1.1" +debug@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + dependencies: + ms "2.1.2" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= -decamelize@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-3.2.0.tgz#84b8e8f4f8c579f938e35e2cc7024907e0090851" - integrity sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw== - dependencies: - xregexp "^4.2.4" - decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -2542,7 +2574,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: +enhanced-resolve@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== @@ -2551,6 +2583,15 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: memory-fs "^0.5.0" tapable "^1.0.0" +enhanced-resolve@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" + integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" + errno@^0.1.3, errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" @@ -2633,10 +2674,10 @@ esutils@^2.0.0, esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -eventemitter2@6.4.2: - version "6.4.2" - resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.2.tgz#f31f8b99d45245f0edbc5b00797830ff3b388970" - integrity sha512-r/Pwupa5RIzxIHbEKCkNXqpEQIIT4uQDxmP4G/Lug/NokVUWj0joz/WzWl3OxRpC5kDrH/WdiUJoR+IrwvXJEw== +eventemitter2@^6.4.2: + version "6.4.3" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.3.tgz#35c563619b13f3681e7eb05cbdaf50f56ba58820" + integrity sha512-t0A2msp6BzOf+QAcI6z9XMktLj52OjGQg+8SJH6v5+3uxNpWYRR3wQmfA+6xtMU9kOC59qk9licus5dYcrYkMQ== events@^2.0.0: version "2.1.0" @@ -2656,20 +2697,22 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" +execa@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.0.3.tgz#0a34dabbad6d66100bd6f2c576c8669403f317f2" + integrity sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" -executable@4.1.1: +executable@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== @@ -2735,7 +2778,7 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-zip@1.7.0: +extract-zip@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== @@ -2911,14 +2954,15 @@ fs-extra@7.0.1: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== +fs-extra@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" + integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== dependencies: + at-least-node "^1.0.0" graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" + jsonfile "^6.0.1" + universalify "^1.0.0" fs-write-stream-atomic@^1.0.8: version "1.0.10" @@ -2943,6 +2987,11 @@ fsevents@^1.2.7: bindings "^1.5.0" nan "^2.12.1" +fsevents@~2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -2963,10 +3012,10 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= -get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== +get-stream@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" @@ -2975,7 +3024,7 @@ get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= -getos@3.2.1: +getos@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5" integrity sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q== @@ -3002,6 +3051,13 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" +glob-parent@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + glob@^7.0.0, glob@^7.1.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -3148,6 +3204,11 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" @@ -3257,12 +3318,19 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-buffer@^1.1.0, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-ci@2.0.0: +is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== @@ -3352,14 +3420,14 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== dependencies: is-extglob "^2.1.1" -is-installed-globally@0.3.2: +is-installed-globally@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== @@ -3413,6 +3481,11 @@ is-stream@^1.1.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -3557,6 +3630,15 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179" + integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg== + dependencies: + universalify "^1.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -3616,7 +3698,7 @@ labeled-stream-splicer@^2.0.0: inherits "^2.0.1" stream-splicer "^2.0.0" -lazy-ass@1.6.0: +lazy-ass@1.6.0, lazy-ass@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" integrity sha1-eZllXoZGwX8In90YfRUNMyTVRRM= @@ -3650,7 +3732,7 @@ listr-verbose-renderer@^0.5.0: date-fns "^1.27.2" figures "^2.0.0" -listr@0.14.3: +listr@^0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== @@ -3714,12 +3796,10 @@ lodash@4.17.15, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17. resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -log-symbols@3.0.0, log-symbols@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" - integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== - dependencies: - chalk "^2.4.2" +lodash@^4.17.19: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== log-symbols@^1.0.2: version "1.0.2" @@ -3728,6 +3808,20 @@ log-symbols@^1.0.2: dependencies: chalk "^1.0.0" +log-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== + dependencies: + chalk "^2.4.2" + +log-symbols@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== + dependencies: + chalk "^4.0.0" + log-update@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" @@ -3809,6 +3903,11 @@ memory-fs@^0.5.0: errno "^0.1.3" readable-stream "^2.0.1" +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -3888,16 +3987,16 @@ minimist@0.0.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@1.2.5, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" @@ -3964,10 +4063,10 @@ module-deps@^6.0.0: through2 "^2.0.0" xtend "^4.0.0" -moment@2.26.0: - version "2.26.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a" - integrity sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw== +moment@^2.27.0: + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== move-concurrently@^1.0.1: version "1.0.1" @@ -3986,7 +4085,7 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@^2.1.1: +ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -4037,11 +4136,6 @@ next-tick@~1.0.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - no-case@^2.2.0: version "2.3.2" resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" @@ -4100,17 +4194,17 @@ normalize-path@^2.1.1: dependencies: remove-trailing-separator "^1.0.1" -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: - path-key "^2.0.0" + path-key "^3.0.0" number-is-nan@^1.0.0: version "1.0.1" @@ -4228,7 +4322,7 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" -ospath@1.2.2: +ospath@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= @@ -4240,11 +4334,6 @@ outpipe@^1.1.0: dependencies: shell-quote "^1.4.2" -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - p-limit@^2.0.0, p-limit@^2.2.0: version "2.2.2" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" @@ -4369,10 +4458,10 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.6: version "1.0.6" @@ -4410,6 +4499,11 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + picomatch@^2.0.5: version "2.2.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" @@ -4437,10 +4531,10 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= -pretty-bytes@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" - integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== +pretty-bytes@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.4.1.tgz#cd89f79bbcef21e3d21eb0da68ffe93f803e884b" + integrity sha512-s1Iam6Gwz3JI5Hweaz4GoCD1WUNUIyzePFy5+Js2hjwGVt2Z79wNN+ZKOZ2vB6C+Xs6njyB84Z1IthQg8d9LxA== private@^0.1.6: version "0.1.8" @@ -4559,7 +4653,7 @@ ramda@0.25.0: resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.25.0.tgz#8fdf68231cffa90bc2f9460390a0cb74a29b29a9" integrity sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ== -ramda@0.26.1: +ramda@~0.26.1: version "0.26.1" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ== @@ -4617,6 +4711,13 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" @@ -4639,11 +4740,6 @@ regenerator-runtime@^0.12.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== -regenerator-runtime@^0.13.4: - version "0.13.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" - integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== - regenerator-transform@^0.14.0: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" @@ -4698,7 +4794,7 @@ repeat-string@^1.5.2, repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= -request-progress@3.0.0: +request-progress@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" integrity sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4= @@ -4778,6 +4874,13 @@ rimraf@^2.5.4, rimraf@^2.6.3: dependencies: glob "^7.1.3" +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -4911,17 +5014,17 @@ shasum@^1.0.0: json-stable-stringify "~0.0.0" sha.js "~2.4.4" -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: - shebang-regex "^1.0.0" + shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.4.2, shell-quote@^1.6.1: version "1.7.2" @@ -4933,7 +5036,7 @@ sigmund@^1.0.1: resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= -signal-exit@^3.0.0, signal-exit@^3.0.2: +signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= @@ -5253,10 +5356,10 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== subarg@^1.0.0: version "1.0.0" @@ -5265,13 +5368,6 @@ subarg@^1.0.0: dependencies: minimist "^1.1.0" -supports-color@7.1.0, supports-color@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" - integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== - dependencies: - has-flag "^4.0.0" - supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -5284,6 +5380,20 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + +supports-color@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + symbol-observable@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" @@ -5379,12 +5489,12 @@ title-case@^2.1.1: no-case "^2.2.0" upper-case "^1.0.3" -tmp@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" - integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== +tmp@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== dependencies: - rimraf "^2.6.3" + rimraf "^3.0.0" to-arraybuffer@^1.0.0: version "1.0.1" @@ -5567,6 +5677,11 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" + integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug== + unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -5575,7 +5690,7 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -untildify@4.0.0: +untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== @@ -5602,7 +5717,7 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= -url@0.11.0, url@^0.11.0, url@~0.11.0: +url@^0.11.0, url@~0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= @@ -5697,14 +5812,23 @@ watchify@3.11.1: through2 "^2.0.0" xtend "^4.0.0" -watchpack@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.1.tgz#280da0a8718592174010c078c7585a74cd8cd0e2" - integrity sha512-+IF9hfUFOrYOOaKyfaI7h7dquUIOgyEMoQMLA7OP5FxegKA2+XdXThAZ9TU2kucfhDH7rfMHs1oPYziVGWRnZA== +watchpack-chokidar2@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" + integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== dependencies: chokidar "^2.1.8" + +watchpack@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" + integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== + dependencies: graceful-fs "^4.1.2" neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.1" + watchpack-chokidar2 "^2.0.0" wcwidth@^1.0.1: version "1.0.1" @@ -5721,10 +5845,10 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.43.0: - version "4.43.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.43.0.tgz#c48547b11d563224c561dad1172c8aa0b8a678e6" - integrity sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g== +webpack@^4.41.5: + version "4.44.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.2.tgz#6bfe2b0af055c8b2d1e90ed2cd9363f841266b72" + integrity sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -5734,7 +5858,7 @@ webpack@^4.43.0: ajv "^6.10.2" ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^4.1.0" + enhanced-resolve "^4.3.0" eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" loader-runner "^2.4.0" @@ -5747,7 +5871,7 @@ webpack@^4.43.0: schema-utils "^1.0.0" tapable "^1.1.3" terser-webpack-plugin "^1.4.3" - watchpack "^1.6.1" + watchpack "^1.7.4" webpack-sources "^1.4.1" which-module@^2.0.0: @@ -5755,10 +5879,10 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" @@ -5791,13 +5915,6 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -xregexp@^4.2.4: - version "4.3.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50" - integrity sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g== - dependencies: - "@babel/runtime-corejs3" "^7.8.3" - xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -5826,13 +5943,13 @@ yargs-parser@^18.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@^15.4.0: - version "15.4.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.0.tgz#53949fb768309bac1843de9b17b80051e9805ec2" - integrity sha512-D3fRFnZwLWp8jVAAhPZBsmeIHY8tTsb8ItV9KaAaopmC6wde2u6Yw29JBIZHXw14kgkRnYmDgmQU4FVMDlIsWw== +yargs@^15.4.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: cliui "^6.0.0" - decamelize "^3.2.0" + decamelize "^1.2.0" find-up "^4.1.0" get-caller-file "^2.0.1" require-directory "^2.1.1" @@ -5843,7 +5960,7 @@ yargs@^15.4.0: y18n "^4.0.0" yargs-parser "^18.1.2" -yauzl@2.10.0, yauzl@^2.10.0: +yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= diff --git a/x-pack/plugins/apm/public/application/csmApp.tsx b/x-pack/plugins/apm/public/application/csmApp.tsx index 2baddbe572a5..d8f54c7bfc94 100644 --- a/x-pack/plugins/apm/public/application/csmApp.tsx +++ b/x-pack/plugins/apm/public/application/csmApp.tsx @@ -28,6 +28,7 @@ import { ConfigSchema } from '../index'; import { ApmPluginSetupDeps, ApmPluginStartDeps } from '../plugin'; import { createCallApmApi } from '../services/rest/createCallApmApi'; import { px, units } from '../style/variables'; +import { createStaticIndexPattern } from '../services/rest/index_pattern'; const CsmMainContainer = styled.div` padding: ${px(units.plus)}; @@ -114,6 +115,12 @@ export const renderApp = ( ) => { createCallApmApi(core.http); + // Automatically creates static index pattern and stores as saved object + createStaticIndexPattern().catch((e) => { + // eslint-disable-next-line no-console + console.log('Error creating static index pattern', e); + }); + ReactDOM.render( + + + {I18LABELS.totalPageLoad} + + + } + isLoading={status !== 'success'} + /> + + {I18LABELS.backEnd} + + + } isLoading={status !== 'success'} /> @@ -82,7 +112,15 @@ export function ClientMetrics() { + {I18LABELS.frontEnd} + + + } isLoading={status !== 'success'} /> diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx index 7a7c05181755..58f00604b8fd 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx @@ -15,7 +15,6 @@ import { EuiToolTip, } from '@elastic/eui'; import numeral from '@elastic/numeral'; -import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { useUrlParams } from '../../../../hooks/useUrlParams'; import { useFetcher } from '../../../../hooks/useFetcher'; @@ -102,11 +101,6 @@ export function JSErrors() { }); }; - const errorRate = - totalPageViews > 0 - ? ((data?.totalErrorPages ?? 0) / totalPageViews) * 100 - : 0; - const totalErrors = data?.totalErrors ?? 0; return ( @@ -133,20 +127,6 @@ export function JSErrors() { isLoading={status !== 'success'} /> - - - {' '} -

{I18LABELS.pageLoadDuration}

+

+ {I18LABELS.pageLoad} ({getPercentileLabel(percentile!)}) +

diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/RumHome.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/RumHome.tsx index d1cfe1d63f88..f25761bd8aba 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/RumHome.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/RumHome.tsx @@ -30,6 +30,7 @@ export function RumHome() { wrap style={{ flexWrap: 'wrap-reverse' }} justifyContent="flexEnd" + gutterSize="s" > diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/URLFilter/URLSearch/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/URLFilter/URLSearch/index.tsx index 02334be5f722..f9aeb484cbdf 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/URLFilter/URLSearch/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/URLFilter/URLSearch/index.tsx @@ -16,6 +16,7 @@ import { formatToSec } from '../../UXMetrics/KeyUXMetrics'; import { SelectableUrlList } from './SelectableUrlList'; import { UrlOption } from './RenderOption'; import { useUxQuery } from '../../hooks/useUxQuery'; +import { getPercentileLabel } from '../../UXMetrics/translations'; interface Props { onChange: (value: string[]) => void; @@ -26,7 +27,7 @@ export function URLSearch({ onChange: onFilterChange }: Props) { const { uiFilters, urlParams } = useUrlParams(); - const { searchTerm } = urlParams; + const { searchTerm, percentile } = urlParams; const [popoverIsOpen, setPopoverIsOpen] = useState(false); @@ -104,12 +105,17 @@ export function URLSearch({ onChange: onFilterChange }: Props) { setCheckedUrls(clickedItems.map((item) => item.url)); }; + const percTitle = getPercentileLabel(percentile!); + const items: UrlOption[] = (data?.items ?? []).map((item) => ({ label: item.url, key: item.url, meta: [ I18LABELS.pageViews + ': ' + item.count, - I18LABELS.pageLoadDuration + ': ' + formatToSec(item.pld), + I18LABELS.pageLoadDuration + + ': ' + + formatToSec(item.pld) + + ` (${percTitle})`, ], url: item.url, checked: checkedUrls?.includes(item.url) ? 'on' : undefined, diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/KeyUXMetrics.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/KeyUXMetrics.tsx index 793c9619edb3..c7fe8e885020 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/KeyUXMetrics.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/KeyUXMetrics.tsx @@ -5,15 +5,20 @@ */ import React from 'react'; -import { EuiFlexItem, EuiStat, EuiFlexGroup } from '@elastic/eui'; +import { EuiFlexItem, EuiStat, EuiFlexGroup, EuiIconTip } from '@elastic/eui'; import numeral from '@elastic/numeral'; import { DATA_UNDEFINED_LABEL, FCP_LABEL, + FCP_TOOLTIP, LONGEST_LONG_TASK, + LONGEST_LONG_TASK_TOOLTIP, NO_OF_LONG_TASK, + NO_OF_LONG_TASK_TOOLTIP, SUM_LONG_TASKS, + SUM_LONG_TASKS_TOOLTIP, TBT_LABEL, + TBT_TOOLTIP, } from './translations'; import { useFetcher } from '../../../../hooks/useFetcher'; import { useUxQuery } from '../hooks/useUxQuery'; @@ -37,8 +42,9 @@ interface Props { loading: boolean; } -function formatTitle(unit: string, value?: number) { - if (typeof value === 'undefined') return DATA_UNDEFINED_LABEL; +function formatTitle(unit: string, value?: number | null) { + if (typeof value === 'undefined' || value === null) + return DATA_UNDEFINED_LABEL; return formatToSec(value, unit); } @@ -69,7 +75,12 @@ export function KeyUXMetrics({ data, loading }: Props) { + {FCP_LABEL} + + + } isLoading={loading} /> @@ -77,7 +88,12 @@ export function KeyUXMetrics({ data, loading }: Props) { + {TBT_LABEL} + + + } isLoading={loading} />
@@ -85,11 +101,19 @@ export function KeyUXMetrics({ data, loading }: Props) { + {NO_OF_LONG_TASK} + + + } isLoading={status !== 'success'} /> @@ -97,7 +121,15 @@ export function KeyUXMetrics({ data, loading }: Props) { + {LONGEST_LONG_TASK} + + + } isLoading={status !== 'success'} /> @@ -105,7 +137,15 @@ export function KeyUXMetrics({ data, loading }: Props) { + {SUM_LONG_TASKS} + + + } isLoading={status !== 'success'} /> diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/__tests__/KeyUXMetrics.test.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/__tests__/KeyUXMetrics.test.tsx index cced16691b71..3a6323a747a7 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/__tests__/KeyUXMetrics.test.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/__tests__/KeyUXMetrics.test.tsx @@ -19,7 +19,7 @@ describe('KeyUXMetrics', () => { status: fetcherHook.FETCH_STATUS.SUCCESS, refetch: jest.fn(), }); - const { getByText } = render( + const { getAllByText } = render( { lcpRanks: [69, 17, 14], fidRanks: [83, 6, 11], clsRanks: [90, 7, 3], + coreVitalPages: 1000, }} /> ); - expect(getByText('Longest long task duration 271 ms')).toBeInTheDocument(); - expect(getByText('Total long tasks duration 520 ms')).toBeInTheDocument(); - expect(getByText('No. of long tasks 3')).toBeInTheDocument(); - expect(getByText('Total blocking time 271 ms')).toBeInTheDocument(); - expect(getByText('First contentful paint 1.27 s')).toBeInTheDocument(); + const checkText = (text: string) => { + return (content: any, node: any) => { + return node?.textContent?.includes(text); + }; + }; + + expect( + getAllByText(checkText('Longest long task duration271 ms'))[0] + ).toBeInTheDocument(); + expect( + getAllByText(checkText('Total long tasks duration520 ms'))[0] + ).toBeInTheDocument(); + expect( + getAllByText(checkText('No. of long tasks3'))[0] + ).toBeInTheDocument(); + expect( + getAllByText(checkText('Total blocking time271 ms'))[0] + ).toBeInTheDocument(); + expect( + getAllByText(checkText('First contentful paint1.27 s'))[0] + ).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/index.tsx index 9ff524db3036..983e3be1c21a 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/index.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; +import React, { useContext } from 'react'; import { EuiFlexGroup, EuiFlexItem, @@ -18,8 +18,15 @@ import { KeyUXMetrics } from './KeyUXMetrics'; import { useFetcher } from '../../../../hooks/useFetcher'; import { useUxQuery } from '../hooks/useUxQuery'; import { CoreVitals } from '../../../../../../observability/public'; +import { CsmSharedContext } from '../CsmSharedContext'; +import { useUrlParams } from '../../../../hooks/useUrlParams'; +import { getPercentileLabel } from './translations'; export function UXMetrics() { + const { + urlParams: { percentile }, + } = useUrlParams(); + const uxQuery = useUxQuery(); const { data, status } = useFetcher( @@ -37,12 +44,18 @@ export function UXMetrics() { [uxQuery] ); + const { + sharedData: { totalPageViews }, + } = useContext(CsmSharedContext); + return ( - -

{I18LABELS.userExperienceMetrics}

+ +

+ {I18LABELS.metrics} ({getPercentileLabel(percentile!)}) +

@@ -54,7 +67,12 @@ export function UXMetrics() { - +
diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/translations.ts b/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/translations.ts index 8f3a71f669ec..3795f2f10223 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/translations.ts +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/UXMetrics/translations.ts @@ -5,6 +5,7 @@ */ import { i18n } from '@kbn/i18n'; +import { I18LABELS } from '../translations'; export const DATA_UNDEFINED_LABEL = i18n.translate( 'xpack.apm.rum.coreVitals.dataUndefined', @@ -17,10 +18,26 @@ export const FCP_LABEL = i18n.translate('xpack.apm.rum.coreVitals.fcp', { defaultMessage: 'First contentful paint', }); +export const FCP_TOOLTIP = i18n.translate( + 'xpack.apm.rum.coreVitals.fcpTooltip', + { + defaultMessage: + 'First contentful paint (FCP) focusses on the initial rendering and measures the time from when the page starts loading to when any part of the page’s content is displayed on the screen.', + } +); + export const TBT_LABEL = i18n.translate('xpack.apm.rum.coreVitals.tbt', { defaultMessage: 'Total blocking time', }); +export const TBT_TOOLTIP = i18n.translate( + 'xpack.apm.rum.coreVitals.tbtTooltip', + { + defaultMessage: + 'Total blocking time (TBT) is the sum of the blocking time (duration above 50 ms) for each long task that occurs between the First contentful paint and the time when the transaction is completed.', + } +); + export const NO_OF_LONG_TASK = i18n.translate( 'xpack.apm.rum.uxMetrics.noOfLongTasks', { @@ -28,6 +45,14 @@ export const NO_OF_LONG_TASK = i18n.translate( } ); +export const NO_OF_LONG_TASK_TOOLTIP = i18n.translate( + 'xpack.apm.rum.uxMetrics.noOfLongTasksTooltip', + { + defaultMessage: + 'The number of long tasks, a long task is defined as any user activity or browser task that monopolizes the UI thread for extended periods (greater than 50 milliseconds) and blocks other critical tasks (frame rate or input latency) from being executed.', + } +); + export const LONGEST_LONG_TASK = i18n.translate( 'xpack.apm.rum.uxMetrics.longestLongTasks', { @@ -35,9 +60,36 @@ export const LONGEST_LONG_TASK = i18n.translate( } ); +export const LONGEST_LONG_TASK_TOOLTIP = i18n.translate( + 'xpack.apm.rum.uxMetrics.longestLongTasksTooltip', + { + defaultMessage: + 'The duration of the longest long task, a long task is defined as any user activity or browser task that monopolizes the UI thread for extended periods (greater than 50 milliseconds) and blocks other critical tasks (frame rate or input latency) from being executed.', + } +); + export const SUM_LONG_TASKS = i18n.translate( 'xpack.apm.rum.uxMetrics.sumLongTasks', { defaultMessage: 'Total long tasks duration', } ); + +export const SUM_LONG_TASKS_TOOLTIP = i18n.translate( + 'xpack.apm.rum.uxMetrics.sumLongTasksTooltip', + { + defaultMessage: + 'The total duration of long tasks, a long task is defined as any user activity or browser task that monopolizes the UI thread for extended periods (greater than 50 milliseconds) and blocks other critical tasks (frame rate or input latency) from being executed.', + } +); + +export const getPercentileLabel = (value: number) => { + if (value === 50) return I18LABELS.median; + + return i18n.translate('xpack.apm.ux.percentiles.label', { + defaultMessage: '{value}th Perc.', + values: { + value, + }, + }); +}; diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/UserPercentile/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/UserPercentile/index.tsx index 18cd7d79cc69..04c7e3cc0028 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/UserPercentile/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/UserPercentile/index.tsx @@ -45,13 +45,11 @@ export function UserPercentile() { { value: '50', text: I18LABELS.percentile50thMedian, - dropdownDisplay: I18LABELS.percentile50thMedian, 'data-test-subj': 'p50Percentile', }, { value: '75', text: I18LABELS.percentile75th, - dropdownDisplay: I18LABELS.percentile75th, 'data-test-subj': 'p75Percentile', }, { diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts b/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts index a8c4d67305c9..75df1381d8a1 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts @@ -10,6 +10,9 @@ export const I18LABELS = { dataMissing: i18n.translate('xpack.apm.rum.dashboard.dataMissing', { defaultMessage: 'N/A', }), + totalPageLoad: i18n.translate('xpack.apm.rum.dashboard.totalPageLoad', { + defaultMessage: 'Total', + }), backEnd: i18n.translate('xpack.apm.rum.dashboard.backend', { defaultMessage: 'Backend', }), @@ -17,7 +20,7 @@ export const I18LABELS = { defaultMessage: 'Frontend', }), pageViews: i18n.translate('xpack.apm.rum.dashboard.pageViews', { - defaultMessage: 'Page views', + defaultMessage: 'Total page views', }), percPageLoaded: i18n.translate('xpack.apm.rum.dashboard.pagesLoaded.label', { defaultMessage: 'Pages loaded', @@ -34,6 +37,9 @@ export const I18LABELS = { defaultMessage: 'Page load duration', } ), + pageLoad: i18n.translate('xpack.apm.rum.dashboard.pageLoad.label', { + defaultMessage: 'Page load', + }), pageLoadDistribution: i18n.translate( 'xpack.apm.rum.dashboard.pageLoadDistribution.label', { @@ -79,8 +85,11 @@ export const I18LABELS = { defaultMessage: 'Operating system', } ), - userExperienceMetrics: i18n.translate('xpack.apm.rum.userExperienceMetrics', { - defaultMessage: 'User experience metrics', + metrics: i18n.translate('xpack.apm.ux.metrics', { + defaultMessage: 'Metrics', + }), + median: i18n.translate('xpack.apm.ux.median', { + defaultMessage: 'median', }), avgPageLoadDuration: i18n.translate( 'xpack.apm.rum.visitorBreakdownMap.avgPageLoadDuration', @@ -153,6 +162,21 @@ export const I18LABELS = { noData: i18n.translate('xpack.apm.ux.visitorBreakdown.noData', { defaultMessage: 'No data.', }), + // Helper tooltips + totalPageLoadTooltip: i18n.translate( + 'xpack.apm.rum.dashboard.tooltips.totalPageLoad', + { + defaultMessage: 'Total represents the full page load duration', + } + ), + frontEndTooltip: i18n.translate('xpack.apm.rum.dashboard.tooltips.frontEnd', { + defaultMessage: + 'Frontend time represents the total page load duration minus the backend time', + }), + backEndTooltip: i18n.translate('xpack.apm.rum.dashboard.tooltips.backEnd', { + defaultMessage: + 'Backend time represents time to first byte (TTFB), which is when the first response packet is received after the request has been made', + }), }; export const VisitorBreakdownLabel = i18n.translate( diff --git a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx index cbb6d9a8fbe4..76c8a289b830 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx @@ -8,6 +8,7 @@ import { EuiTabs } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { isJavaAgentName, isRumAgentName } from '../../../../common/agent_name'; +import { enableServiceOverview } from '../../../../common/ui_settings_keys'; import { useAgentName } from '../../../hooks/useAgentName'; import { useApmPluginContext } from '../../../hooks/useApmPluginContext'; import { EuiTabLink } from '../../shared/EuiTabLink'; @@ -29,7 +30,19 @@ interface Props { export function ServiceDetailTabs({ serviceName, tab }: Props) { const { agentName } = useAgentName(); - const { serviceMapEnabled } = useApmPluginContext().config; + const { uiSettings } = useApmPluginContext().core; + + const overviewTab = { + link: ( + + {i18n.translate('xpack.apm.serviceDetails.overviewTabLabel', { + defaultMessage: 'Overview', + })} + + ), + render: () => <>, + name: 'overview', + }; const transactionsTab = { link: ( @@ -57,7 +70,23 @@ export function ServiceDetailTabs({ serviceName, tab }: Props) { name: 'errors', }; - const tabs = [transactionsTab, errorsTab]; + const serviceMapTab = { + link: ( + + {i18n.translate('xpack.apm.home.serviceMapTabLabel', { + defaultMessage: 'Service Map', + })} + + ), + render: () => , + name: 'service-map', + }; + + const tabs = [transactionsTab, errorsTab, serviceMapTab]; + + if (uiSettings.get(enableServiceOverview)) { + tabs.unshift(overviewTab); + } if (isJavaAgentName(agentName)) { const nodesListTab = { @@ -89,22 +118,6 @@ export function ServiceDetailTabs({ serviceName, tab }: Props) { tabs.push(metricsTab); } - const serviceMapTab = { - link: ( - - {i18n.translate('xpack.apm.home.serviceMapTabLabel', { - defaultMessage: 'Service Map', - })} - - ), - render: () => , - name: 'service-map', - }; - - if (serviceMapEnabled) { - tabs.push(serviceMapTab); - } - const selectedTab = tabs.find((serviceTab) => serviceTab.name === tab); return ( diff --git a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx index 8e32c55da916..dfc78028c359 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx @@ -3,7 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - import { EuiButton, EuiFlexGroup, @@ -37,6 +36,14 @@ export function AgentConfigurations() { return ( <> + +

+ {i18n.translate('xpack.apm.agentConfig.titleText', { + defaultMessage: 'Agent remote configuration', + })} +

+
+ @@ -44,7 +51,7 @@ export function AgentConfigurations() {

{i18n.translate( 'xpack.apm.agentConfig.configurationsPanelTitle', - { defaultMessage: 'Agent remote configuration' } + { defaultMessage: 'Configurations' } )}

diff --git a/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.test.tsx b/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.test.tsx index 68e75d595363..53794ca9965f 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.test.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.test.tsx @@ -24,11 +24,11 @@ describe('ApmIndices', () => { ); expect(getByText('Indices')).toMatchInlineSnapshot(` -

Indices -

+ `); expect(spy).toHaveBeenCalledTimes(2); diff --git a/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx index 145fb9683cb6..fac947b3ec68 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx @@ -163,23 +163,24 @@ export function ApmIndices() { }; return ( - - - - -

- {i18n.translate('xpack.apm.settings.apmIndices.title', { - defaultMessage: 'Indices', - })} -

-
- - -

- {i18n.translate('xpack.apm.settings.apmIndices.description', { - defaultMessage: `The APM UI uses index patterns to query your APM indices. If you've customized the index names that APM Server writes events to, you may need to update these patterns for the APM UI to work. Settings here take precedence over those set in kibana.yml.`, - })} -

+ <> + +

+ {i18n.translate('xpack.apm.settings.apmIndices.title', { + defaultMessage: 'Indices', + })} +

+
+ + + {i18n.translate('xpack.apm.settings.apmIndices.description', { + defaultMessage: `The APM UI uses index patterns to query your APM indices. If you've customized the index names that APM Server writes events to, you may need to update these patterns for the APM UI to work. Settings here take precedence over those set in kibana.yml.`, + })} + + + + + {APM_INDEX_LABELS.map(({ configurationName, label }) => { const matchedConfiguration = data.find( @@ -239,11 +240,10 @@ export function ApmIndices() { -
-
-
- - -
+
+
+ +
+ ); } diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx index 2e860ebe22c0..56b3eaf425af 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/CreateCustomLinkButton.tsx @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; export function CreateCustomLinkButton({ onClick }: { onClick: () => void }) { return ( - + {i18n.translate( 'xpack.apm.settings.customizeUI.customLink.createCustomLink', { defaultMessage: 'Create custom link' } diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/Title.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/Title.tsx index 22d8749d7883..2017aa42e1c5 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/Title.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/CustomLink/Title.tsx @@ -3,7 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { EuiFlexGroup, EuiFlexItem, EuiIconTip, EuiTitle } from '@elastic/eui'; + +import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; @@ -11,28 +12,14 @@ export function Title() { return ( - + -

+

{i18n.translate('xpack.apm.settings.customizeUI.customLink', { defaultMessage: 'Custom Links', })} -

-
- - - +
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 45a7fa2a118f..a7d7cf40ba84 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 @@ -4,19 +4,26 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiPanel, EuiSpacer, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiSpacer, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; import React, { useEffect, useState } from 'react'; import { INVALID_LICENSE } from '../../../../../../common/custom_link'; import { CustomLink } from '../../../../../../common/custom_link/custom_link_types'; +import { FETCH_STATUS, useFetcher } from '../../../../../hooks/useFetcher'; import { useLicense } from '../../../../../hooks/useLicense'; -import { useFetcher, FETCH_STATUS } from '../../../../../hooks/useFetcher'; +import { LicensePrompt } from '../../../../shared/LicensePrompt'; +import { CreateCustomLinkButton } from './CreateCustomLinkButton'; import { CustomLinkFlyout } from './CustomLinkFlyout'; import { CustomLinkTable } from './CustomLinkTable'; import { EmptyPrompt } from './EmptyPrompt'; import { Title } from './Title'; -import { CreateCustomLinkButton } from './CreateCustomLinkButton'; -import { LicensePrompt } from '../../../../shared/LicensePrompt'; export function CustomLinkOverview() { const license = useLicense(); @@ -82,8 +89,13 @@ export function CustomLinkOverview() {
)}
- - + + + {i18n.translate('xpack.apm.settings.customizeUI.customLink.info', { + defaultMessage: + 'These links will be shown in the Actions context menu for transactions.', + })} + {hasValidLicense ? ( showEmptyPrompt ? ( diff --git a/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/jobs_list.tsx b/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/jobs_list.tsx index 6e95df0dddd8..137dcfcdbb4f 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/jobs_list.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/jobs_list.tsx @@ -80,7 +80,7 @@ export function JobsList({ data, status, onAddEnvironments }: Props) { - + {i18n.translate( 'xpack.apm.settings.anomalyDetection.jobList.addEnvironments', { diff --git a/x-pack/plugins/apm/readme.md b/x-pack/plugins/apm/readme.md index d6fdb5f52291..0adfb99e7164 100644 --- a/x-pack/plugins/apm/readme.md +++ b/x-pack/plugins/apm/readme.md @@ -1,8 +1,8 @@ # Documentation for APM UI developers -### Setup local environment +## Local environment setup -#### Kibana +### Kibana ``` git clone git@github.com:elastic/kibana.git @@ -11,15 +11,15 @@ yarn kbn bootstrap yarn start --no-base-path ``` -#### APM Server, Elasticsearch and data +### APM Server, Elasticsearch and data To access an elasticsearch instance that has live data you have two options: -##### A. Connect to Elasticsearch on Cloud (internal devs only) +#### A. Connect to Elasticsearch on Cloud (internal devs only) Find the credentials for the cluster [here](https://github.com/elastic/apm-dev/blob/master/docs/credentials/apm-ui-clusters.md#apmelstcco) -##### B. Start Elastic Stack and APM data generators +#### B. Start Elastic Stack and APM data generators ``` git clone git@github.com:elastic/apm-integration-testing.git @@ -29,6 +29,8 @@ cd apm-integration-testing/ _Docker Compose is required_ +## Testing + ### E2E (Cypress) tests ```sh @@ -109,23 +111,23 @@ The API tests for "trial" are located in `x-pack/test/apm_api_integration/trial/ For debugging access Elasticsearch on http://localhost:9220` (elastic/changeme) -### Linting +## Linting _Note: Run the following commands from `kibana/`._ -#### Prettier +### Prettier ``` yarn prettier "./x-pack/plugins/apm/**/*.{tsx,ts,js}" --write ``` -#### ESLint +### ESLint ``` yarn eslint ./x-pack/plugins/apm --fix ``` -### Setup default APM users +## Setup default APM users APM behaves differently depending on which the role and permissions a logged in user has. For testing purposes APM uses 3 custom users: @@ -144,20 +146,35 @@ node x-pack/plugins/apm/scripts/setup-kibana-security.js --role-suffix Advanced Settings > Observability. + +## Further resources - [Cypress integration tests](./e2e/README.md) - [VSCode setup instructions](./dev_docs/vscode_setup.md) diff --git a/x-pack/plugins/apm/scripts/precommit.js b/x-pack/plugins/apm/scripts/precommit.js index 87da3c1db8b2..ec38ec88f550 100644 --- a/x-pack/plugins/apm/scripts/precommit.js +++ b/x-pack/plugins/apm/scripts/precommit.js @@ -25,7 +25,7 @@ const tasks = new Listr( [ resolve(__dirname, './jest.js'), '--reporters', - resolve(__dirname, './node_modules/jest-silent-reporter'), + resolve(__dirname, '../../../../node_modules/jest-silent-reporter'), '--collect-coverage', 'false', ], diff --git a/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap index 1fafa0808244..b89c46f6e3fc 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap @@ -9,31 +9,35 @@ Object { }, "body": Object { "aggs": Object { - "backEnd": Object { - "percentiles": Object { - "field": "transaction.marks.agent.timeToFirstByte", - "hdr": Object { - "number_of_significant_value_digits": 3, + "hasFetchStartField": Object { + "aggs": Object { + "backEnd": Object { + "percentiles": Object { + "field": "transaction.marks.agent.timeToFirstByte", + "hdr": Object { + "number_of_significant_value_digits": 3, + }, + "percents": Array [ + 50, + ], + }, }, - "percents": Array [ - 50, - ], - }, - }, - "domInteractive": Object { - "percentiles": Object { - "field": "transaction.marks.agent.domInteractive", - "hdr": Object { - "number_of_significant_value_digits": 3, + "totalPageLoadDuration": Object { + "percentiles": Object { + "field": "transaction.duration.us", + "hdr": Object { + "number_of_significant_value_digits": 3, + }, + "percents": Array [ + 50, + ], + }, }, - "percents": Array [ - 50, - ], }, - }, - "pageViews": Object { - "value_count": Object { - "field": "transaction.duration.us", + "filter": Object { + "exists": Object { + "field": "transaction.marks.navigationTiming.fetchStart", + }, }, }, }, @@ -54,11 +58,6 @@ Object { "transaction.type": "page-load", }, }, - Object { - "exists": Object { - "field": "transaction.marks.navigationTiming.fetchStart", - }, - }, Object { "term": Object { "service.environment": "test", @@ -68,6 +67,7 @@ Object { }, }, "size": 0, + "track_total_hits": true, }, } `; @@ -139,11 +139,6 @@ Object { "agent.name": "rum-js", }, }, - Object { - "term": Object { - "transaction.type": "page-load", - }, - }, Object { "term": Object { "service.language.name": "javascript", @@ -545,11 +540,6 @@ Object { "transaction.type": "page-load", }, }, - Object { - "exists": Object { - "field": "transaction.marks.navigationTiming.fetchStart", - }, - }, Object { "term": Object { "service.environment": "test", @@ -590,6 +580,13 @@ Object { ], }, }, + "coreVitalPages": Object { + "filter": Object { + "exists": Object { + "field": "transaction.experience", + }, + }, + }, "fcp": Object { "percentiles": Object { "field": "transaction.marks.agent.firstContentfulPaint", @@ -670,11 +667,6 @@ Object { "service.environment": "test", }, }, - Object { - "term": Object { - "user_agent.name": "Chrome", - }, - }, ], }, }, diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_client_metrics.ts b/x-pack/plugins/apm/server/lib/rum_client/get_client_metrics.ts index 6d596246d6af..6685a60f84f0 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_client_metrics.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_client_metrics.ts @@ -4,13 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { TRANSACTION_DURATION } from '../../../common/elasticsearch_fieldnames'; import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { - TRANSACTION_DOM_INTERACTIVE, TRANSACTION_TIME_TO_FIRST_BYTE, + TRANSACTION_DURATION, } from '../../../common/elasticsearch_fieldnames'; export async function getClientMetrics({ @@ -25,32 +24,36 @@ export async function getClientMetrics({ const projection = getRumPageLoadTransactionsProjection({ setup, urlQuery, + checkFetchStartFieldExists: false, }); const params = mergeProjection(projection, { body: { size: 0, + track_total_hits: true, aggs: { - pageViews: { - value_count: { - field: TRANSACTION_DURATION, + hasFetchStartField: { + filter: { + exists: { field: 'transaction.marks.navigationTiming.fetchStart' }, }, - }, - backEnd: { - percentiles: { - field: TRANSACTION_TIME_TO_FIRST_BYTE, - percents: [percentile], - hdr: { - number_of_significant_value_digits: 3, + aggs: { + totalPageLoadDuration: { + percentiles: { + field: TRANSACTION_DURATION, + percents: [percentile], + hdr: { + number_of_significant_value_digits: 3, + }, + }, }, - }, - }, - domInteractive: { - percentiles: { - field: TRANSACTION_DOM_INTERACTIVE, - percents: [percentile], - hdr: { - number_of_significant_value_digits: 3, + backEnd: { + percentiles: { + field: TRANSACTION_TIME_TO_FIRST_BYTE, + percents: [percentile], + hdr: { + number_of_significant_value_digits: 3, + }, + }, }, }, }, @@ -59,18 +62,21 @@ export async function getClientMetrics({ }); const { apmEventClient } = setup; - const response = await apmEventClient.search(params); - const { backEnd, domInteractive, pageViews } = response.aggregations!; + const { + hasFetchStartField: { backEnd, totalPageLoadDuration }, + } = response.aggregations!; const pkey = percentile.toFixed(1); - // Divide by 1000 to convert ms into seconds + const totalPageLoadDurationValue = totalPageLoadDuration.values[pkey] ?? 0; + const totalPageLoadDurationValueMs = totalPageLoadDurationValue / 1000; // Microseconds to milliseconds + const backendValue = backEnd.values[pkey] ?? 0; + return { - pageViews, - backEnd: { value: backEnd.values[pkey] || 0 }, - frontEnd: { - value: (domInteractive.values[pkey] || 0) - (backEnd.values[pkey] || 0), - }, + pageViews: { value: response.hits.total.value ?? 0 }, + totalPageLoadDuration: { value: totalPageLoadDurationValueMs }, + backEnd: { value: backendValue }, + frontEnd: { value: totalPageLoadDurationValueMs - backendValue }, }; } diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts b/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts index c1a602c33fea..f483acba4b93 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts @@ -20,6 +20,7 @@ export async function getPageViewTrends({ const projection = getRumPageLoadTransactionsProjection({ setup, urlQuery, + checkFetchStartFieldExists: false, }); let breakdownItem: BreakdownItem | null = null; if (breakdowns) { diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_web_core_vitals.ts b/x-pack/plugins/apm/server/lib/rum_client/get_web_core_vitals.ts index c5baf0b529eb..76a718bbb2a0 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_web_core_vitals.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_web_core_vitals.ts @@ -12,7 +12,6 @@ import { FCP_FIELD, FID_FIELD, LCP_FIELD, - USER_AGENT_NAME, TBT_FIELD, } from '../../../common/elasticsearch_fieldnames'; @@ -35,17 +34,17 @@ export async function getWebCoreVitals({ size: 0, query: { bool: { - filter: [ - ...projection.body.query.bool.filter, - { - term: { - [USER_AGENT_NAME]: 'Chrome', - }, - }, - ], + filter: [...projection.body.query.bool.filter], }, }, aggs: { + coreVitalPages: { + filter: { + exists: { + field: 'transaction.experience', + }, + }, + }, lcp: { percentiles: { field: LCP_FIELD, @@ -104,13 +103,22 @@ export async function getWebCoreVitals({ const { apmEventClient } = setup; const response = await apmEventClient.search(params); - const { lcp, cls, fid, tbt, fcp, lcpRanks, fidRanks, clsRanks } = - response.aggregations ?? {}; + const { + lcp, + cls, + fid, + tbt, + fcp, + lcpRanks, + fidRanks, + clsRanks, + coreVitalPages, + } = response.aggregations ?? {}; const getRanksPercentages = ( - ranks: Array<{ key: number; value: number }> + ranks?: Array<{ key: number; value: number }> ) => { - const ranksVal = ranks.map(({ value }) => value?.toFixed(0) ?? 0); + const ranksVal = ranks?.map(({ value }) => value?.toFixed(0) ?? 0) ?? []; return [ Number(ranksVal?.[0]), Number(ranksVal?.[1]) - Number(ranksVal?.[0]), @@ -118,23 +126,26 @@ export async function getWebCoreVitals({ ]; }; - const defaultRanks = [ - { value: 0, key: 0 }, - { value: 0, key: 0 }, - ]; + const defaultRanks = [100, 0, 0]; const pkey = percentile.toFixed(1); - // Divide by 1000 to convert ms into seconds return { - cls: String(cls?.values[pkey]?.toFixed(2) || 0), - fid: fid?.values[pkey] ?? 0, - lcp: lcp?.values[pkey] ?? 0, + coreVitalPages: coreVitalPages?.doc_count ?? 0, + cls: cls?.values[pkey]?.toFixed(3) || null, + fid: fid?.values[pkey], + lcp: lcp?.values[pkey], tbt: tbt?.values[pkey] ?? 0, - fcp: fcp?.values[pkey] ?? 0, + fcp: fcp?.values[pkey], - lcpRanks: getRanksPercentages(lcpRanks?.values ?? defaultRanks), - fidRanks: getRanksPercentages(fidRanks?.values ?? defaultRanks), - clsRanks: getRanksPercentages(clsRanks?.values ?? defaultRanks), + lcpRanks: lcp?.values[pkey] + ? getRanksPercentages(lcpRanks?.values) + : defaultRanks, + fidRanks: fid?.values[pkey] + ? getRanksPercentages(fidRanks?.values) + : defaultRanks, + clsRanks: cls?.values[pkey] + ? getRanksPercentages(clsRanks?.values) + : defaultRanks, }; } diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index b417f8689b22..d3341b6c1b16 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import { i18n } from '@kbn/i18n'; import { combineLatest, Observable } from 'rxjs'; import { map, take } from 'rxjs/operators'; @@ -36,6 +37,7 @@ import { createApmCustomLinkIndex } from './lib/settings/custom_link/create_cust import { createApmApi } from './routes/create_apm_api'; import { apmIndices, apmTelemetry } from './saved_objects'; import { createElasticCloudInstructions } from './tutorial/elastic_cloud'; +import { uiSettings } from './ui_settings'; export interface APMPluginSetup { config$: Observable; @@ -75,6 +77,8 @@ export class APMPlugin implements Plugin { core.savedObjects.registerType(apmIndices); core.savedObjects.registerType(apmTelemetry); + core.uiSettings.register(uiSettings); + if (plugins.actions && plugins.alerts) { registerApmAlerts({ alerts: plugins.alerts, diff --git a/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts b/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts index 530ca36b5dc9..9c33da227869 100644 --- a/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts +++ b/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts @@ -17,9 +17,11 @@ import { TRANSACTION_PAGE_LOAD } from '../../common/transaction_types'; export function getRumPageLoadTransactionsProjection({ setup, urlQuery, + checkFetchStartFieldExists = true, }: { setup: Setup & SetupTimeRange; urlQuery?: string; + checkFetchStartFieldExists?: boolean; }) { const { start, end, esFilter } = setup; @@ -27,13 +29,17 @@ export function getRumPageLoadTransactionsProjection({ filter: [ { range: rangeFilter(start, end) }, { term: { [TRANSACTION_TYPE]: TRANSACTION_PAGE_LOAD } }, - { - // Adding this filter to cater for some inconsistent rum data - // not available on aggregated transactions - exists: { - field: 'transaction.marks.navigationTiming.fetchStart', - }, - }, + ...(checkFetchStartFieldExists + ? [ + { + // Adding this filter to cater for some inconsistent rum data + // not available on aggregated transactions + exists: { + field: 'transaction.marks.navigationTiming.fetchStart', + }, + }, + ] + : []), ...(urlQuery ? [ { @@ -74,7 +80,6 @@ export function getRumErrorsProjection({ filter: [ { range: rangeFilter(start, end) }, { term: { [AGENT_NAME]: 'rum-js' } }, - { term: { [TRANSACTION_TYPE]: TRANSACTION_PAGE_LOAD } }, { term: { [SERVICE_LANGUAGE_NAME]: 'javascript', diff --git a/x-pack/plugins/apm/server/ui_settings.ts b/x-pack/plugins/apm/server/ui_settings.ts new file mode 100644 index 000000000000..fe5b11d89d71 --- /dev/null +++ b/x-pack/plugins/apm/server/ui_settings.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { schema } from '@kbn/config-schema'; +import { i18n } from '@kbn/i18n'; +import { UiSettingsParams } from '../../../../src/core/types'; +import { + enableCorrelations, + enableServiceOverview, +} from '../common/ui_settings_keys'; + +/** + * uiSettings definitions for APM. + */ +export const uiSettings: Record> = { + [enableCorrelations]: { + category: ['Observability'], + name: i18n.translate('xpack.apm.enableCorrelationsExperimentName', { + defaultMessage: 'APM Correlations', + }), + value: false, + description: i18n.translate( + 'xpack.apm.enableCorrelationsExperimentDescription', + { + defaultMessage: + 'Enable the experimental correlations UI and API endpoint in APM.', + } + ), + schema: schema.boolean(), + }, + [enableServiceOverview]: { + category: ['Observability'], + name: i18n.translate('xpack.apm.enableServiceOverviewExperimentName', { + defaultMessage: 'APM Service overview', + }), + value: false, + description: i18n.translate( + 'xpack.apm.enableServiceOverviewExperimentDescription', + { + defaultMessage: 'Enable the Overview tab for services in APM.', + } + ), + schema: schema.boolean(), + }, +}; diff --git a/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.test.ts b/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.test.ts index 67fc1a98ad4d..4b1e4b34da86 100644 --- a/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.test.ts +++ b/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.test.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { parse as parseUrl } from 'url'; import { OnPostAuthHandler, OnPostAuthToolkit, @@ -45,7 +46,7 @@ describe('DashboardOnlyModeRequestInterceptor', () => { test('should not redirects for not app/* requests', async () => { const request = ({ url: { - path: 'api/test', + pathname: 'api/test', }, } as unknown) as KibanaRequest; @@ -57,7 +58,7 @@ describe('DashboardOnlyModeRequestInterceptor', () => { test('should not redirects not authenticated users', async () => { const request = ({ url: { - path: '/app/home', + pathname: '/app/home', }, } as unknown) as KibanaRequest; @@ -70,10 +71,9 @@ describe('DashboardOnlyModeRequestInterceptor', () => { function testRedirectToDashboardModeApp(url: string) { describe(`requests to url:"${url}"`, () => { test('redirects to the dashboard_mode app instead', async () => { + const { pathname, search, hash } = parseUrl(url); const request = ({ - url: { - path: url, - }, + url: { pathname, search, hash }, credentials: { roles: [DASHBOARD_ONLY_MODE_ROLE], }, diff --git a/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.ts b/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.ts index 4378c818f087..9978d18142ff 100644 --- a/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.ts +++ b/x-pack/plugins/dashboard_mode/server/interceptors/dashboard_mode_request_interceptor.ts @@ -22,7 +22,7 @@ export const setupDashboardModeRequestInterceptor = ({ getUiSettingsClient, }: DashboardModeRequestInterceptorDependencies) => (async (request, response, toolkit) => { - const path = request.url.path || ''; + const path = request.url.pathname; const isAppRequest = path.startsWith('/app/'); if (!isAppRequest) { diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts index 3187b41a2c55..f47d2b39a89a 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { MockedKeys } from '@kbn/utility-types/jest'; import { coreMock } from '../../../../../src/core/public/mocks'; import { EnhancedSearchInterceptor } from './search_interceptor'; import { CoreSetup, CoreStart } from 'kibana/public'; diff --git a/x-pack/plugins/encrypted_saved_objects/server/crypto/encryption_key_rotation_service.ts b/x-pack/plugins/encrypted_saved_objects/server/crypto/encryption_key_rotation_service.ts index fb1b6db45e76..44b040d19909 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/crypto/encryption_key_rotation_service.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/crypto/encryption_key_rotation_service.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ISavedObjectTypeRegistry, KibanaRequest, diff --git a/x-pack/plugins/encrypted_saved_objects/server/routes/index.ts b/x-pack/plugins/encrypted_saved_objects/server/routes/index.ts index 72af8060de82..f68e920e14de 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/routes/index.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/routes/index.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { IRouter, Logger } from '../../../../../src/core/server'; import { ConfigType } from '../config'; import { EncryptionKeyRotationService } from '../crypto'; diff --git a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/index.ts b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/index.ts index 0e5be4e4eee5..0191c1fbb830 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/saved_objects/index.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/saved_objects/index.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { StartServicesAccessor, SavedObject, diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.tsx index 567c77792583..7af3a1d1272e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/error_connecting/error_connecting.tsx @@ -7,10 +7,12 @@ import React from 'react'; import { EuiPage, EuiPageContent } from '@elastic/eui'; +import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import { ErrorStatePrompt } from '../../../shared/error_state'; export const ErrorConnecting: React.FC = () => ( + diff --git a/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/telemetry.test.ts b/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/telemetry.test.ts index c3e2aff6551c..440f540ccc85 100644 --- a/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/telemetry.test.ts +++ b/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/telemetry.test.ts @@ -20,6 +20,8 @@ describe('Enterprise Search Telemetry Usage Collector', () => { get: () => ({ attributes: { 'ui_viewed.overview': 10, + 'ui_viewed.setup_guide': 5, + 'ui_error.cannot_connect': 1, 'ui_clicked.app_search': 2, 'ui_clicked.workplace_search': 3, }, @@ -53,6 +55,10 @@ describe('Enterprise Search Telemetry Usage Collector', () => { expect(savedObjectsCounts).toEqual({ ui_viewed: { overview: 10, + setup_guide: 5, + }, + ui_error: { + cannot_connect: 1, }, ui_clicked: { app_search: 2, @@ -74,6 +80,10 @@ describe('Enterprise Search Telemetry Usage Collector', () => { expect(savedObjectsCounts).toEqual({ ui_viewed: { overview: 0, + setup_guide: 0, + }, + ui_error: { + cannot_connect: 0, }, ui_clicked: { app_search: 0, diff --git a/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/telemetry.ts b/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/telemetry.ts index a124a185b9a3..d6bd8bd9305f 100644 --- a/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/telemetry.ts +++ b/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/telemetry.ts @@ -13,6 +13,10 @@ import { getSavedObjectAttributesFromRepo } from '../lib/telemetry'; interface ITelemetry { ui_viewed: { overview: number; + setup_guide: number; + }; + ui_error: { + cannot_connect: number; }; ui_clicked: { app_search: number; @@ -38,6 +42,10 @@ export const registerTelemetryUsageCollector = ( schema: { ui_viewed: { overview: { type: 'long' }, + setup_guide: { type: 'long' }, + }, + ui_error: { + cannot_connect: { type: 'long' }, }, ui_clicked: { app_search: { type: 'long' }, @@ -63,6 +71,10 @@ const fetchTelemetryMetrics = async (savedObjects: SavedObjectsServiceStart, log const defaultTelemetrySavedObject: ITelemetry = { ui_viewed: { overview: 0, + setup_guide: 0, + }, + ui_error: { + cannot_connect: 0, }, ui_clicked: { app_search: 0, @@ -78,6 +90,10 @@ const fetchTelemetryMetrics = async (savedObjects: SavedObjectsServiceStart, log return { ui_viewed: { overview: get(savedObjectAttributes, 'ui_viewed.overview', 0), + setup_guide: get(savedObjectAttributes, 'ui_viewed.setup_guide', 0), + }, + ui_error: { + cannot_connect: get(savedObjectAttributes, 'ui_error.cannot_connect', 0), }, ui_clicked: { app_search: get(savedObjectAttributes, 'ui_clicked.app_search', 0), diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts index 2bddc9f1c80b..5bd15ce41100 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts @@ -21,7 +21,6 @@ describe('callEnterpriseSearchConfigAPI', () => { accessCheckTimeoutWarning: 100, }; const mockRequest = { - url: { path: '/app/kibana' }, headers: { authorization: '==someAuth' }, }; const mockDependencies = { diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts index 8c3e6e11b75c..fa9f9c36052a 100644 --- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts @@ -6,6 +6,7 @@ import { reject, isUndefined } from 'lodash'; import { SearchResponse, Client } from 'elasticsearch'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Logger, LegacyClusterClient } from 'src/core/server'; import { IValidatedEvent, SAVED_OBJECT_REL_PRIMARY } from '../types'; diff --git a/x-pack/plugins/event_log/server/event_log_client.test.ts b/x-pack/plugins/event_log/server/event_log_client.test.ts index 3273fe847080..d9846428b948 100644 --- a/x-pack/plugins/event_log/server/event_log_client.test.ts +++ b/x-pack/plugins/event_log/server/event_log_client.test.ts @@ -114,7 +114,7 @@ describe('EventLogStart', () => { ).toEqual(result); expect(esContext.esAdapter.queryEventsBySavedObject).toHaveBeenCalledWith( - esContext.esNames.alias, + esContext.esNames.indexPattern, undefined, 'saved-object-type', 'saved-object-id', @@ -195,7 +195,7 @@ describe('EventLogStart', () => { ).toEqual(result); expect(esContext.esAdapter.queryEventsBySavedObject).toHaveBeenCalledWith( - esContext.esNames.alias, + esContext.esNames.indexPattern, undefined, 'saved-object-type', 'saved-object-id', @@ -322,6 +322,12 @@ function FakeRequest(): KibanaRequest { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, getSavedObjectsClient: () => savedObjectGetter, } as unknown) as KibanaRequest; } diff --git a/x-pack/plugins/event_log/server/event_log_client.ts b/x-pack/plugins/event_log/server/event_log_client.ts index 32fd99d17002..b7de4acb9428 100644 --- a/x-pack/plugins/event_log/server/event_log_client.ts +++ b/x-pack/plugins/event_log/server/event_log_client.ts @@ -92,7 +92,7 @@ export class EventLogClient implements IEventLogClient { await this.savedObjectGetter(type, id); return await this.esContext.esAdapter.queryEventsBySavedObject( - this.esContext.esNames.alias, + this.esContext.esNames.indexPattern, namespace, type, id, diff --git a/x-pack/plugins/event_log/server/event_log_start_service.test.ts b/x-pack/plugins/event_log/server/event_log_start_service.test.ts index 0a5b169e87d4..db6f4a1ad0f2 100644 --- a/x-pack/plugins/event_log/server/event_log_start_service.test.ts +++ b/x-pack/plugins/event_log/server/event_log_start_service.test.ts @@ -56,6 +56,12 @@ function fakeRequest(): KibanaRequest { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, getSavedObjectsClient: () => savedObjectsClient, } as unknown) as KibanaRequest; } diff --git a/x-pack/plugins/event_log/server/routes/_mock_handler_arguments.ts b/x-pack/plugins/event_log/server/routes/_mock_handler_arguments.ts index b0ce5605d0e5..0ea5419b113d 100644 --- a/x-pack/plugins/event_log/server/routes/_mock_handler_arguments.ts +++ b/x-pack/plugins/event_log/server/routes/_mock_handler_arguments.ts @@ -6,6 +6,7 @@ import { identity, merge } from 'lodash'; import { RequestHandlerContext, KibanaRequest, KibanaResponseFactory } from 'src/core/server'; +import type { MethodKeysOf } from '@kbn/utility-types'; import { httpServerMock } from 'src/core/server/mocks'; import { IEventLogClient } from '../types'; diff --git a/x-pack/plugins/event_log/server/saved_object_provider_registry.test.ts b/x-pack/plugins/event_log/server/saved_object_provider_registry.test.ts index 6a02d54c8751..076260ab2fe5 100644 --- a/x-pack/plugins/event_log/server/saved_object_provider_registry.test.ts +++ b/x-pack/plugins/event_log/server/saved_object_provider_registry.test.ts @@ -93,6 +93,12 @@ function fakeRequest(): KibanaRequest { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, getSavedObjectsClient: () => savedObjectsClient, } as unknown) as KibanaRequest; } diff --git a/x-pack/plugins/features/server/ui_capabilities_for_features.ts b/x-pack/plugins/features/server/ui_capabilities_for_features.ts index d582dbfdab50..03773a4d8f61 100644 --- a/x-pack/plugins/features/server/ui_capabilities_for_features.ts +++ b/x-pack/plugins/features/server/ui_capabilities_for_features.ts @@ -5,7 +5,7 @@ */ import _ from 'lodash'; -import { RecursiveReadonly } from '@kbn/utility-types'; +import type { RecursiveReadonly, Writable } from '@kbn/utility-types'; import { Capabilities as UICapabilities } from '../../../../src/core/server'; import { ElasticsearchFeature, KibanaFeature } from '../common'; diff --git a/x-pack/plugins/global_search/common/license_checker.ts b/x-pack/plugins/global_search/common/license_checker.ts index d201b31802b3..7524d0ad52e4 100644 --- a/x-pack/plugins/global_search/common/license_checker.ts +++ b/x-pack/plugins/global_search/common/license_checker.ts @@ -5,6 +5,7 @@ */ import { Observable, Subscription } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ILicense } from '../../licensing/common/types'; export type LicenseState = { valid: false; message: string } | { valid: true }; diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts index 0a96146339a5..3d430cf31621 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts @@ -30,6 +30,31 @@ export const DEFAULT_POLICY: PolicyFromES = { name: 'my_policy', }; +export const POLICY_WITH_MIGRATE_OFF: PolicyFromES = { + version: 1, + modified_date: Date.now().toString(), + policy: { + name: 'my_policy', + phases: { + hot: { + min_age: '0ms', + actions: { + rollover: { + max_age: '30d', + max_size: '50gb', + }, + }, + }, + warm: { + actions: { + migrate: { enabled: false }, + }, + }, + }, + }, + name: 'my_policy', +}; + export const POLICY_WITH_INCLUDE_EXCLUDE: PolicyFromES = { version: 1, modified_date: Date.now().toString(), diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx index 1716f124b0c8..ad61641ea1e3 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx @@ -154,12 +154,12 @@ export const setup = async () => { component.update(); }; - const setSelectedNodeAttribute = (phase: string) => + const setSelectedNodeAttribute = (phase: Phases) => createFormSetValueAction(`${phase}-selectedNodeAttrs`); - const setReplicas = async (value: string) => { - await createFormToggleAction('warm-setReplicasSwitch')(true); - await createFormSetValueAction('warm-selectedReplicaCount')(value); + const setReplicas = (phase: Phases) => async (value: string) => { + await createFormToggleAction(`${phase}-setReplicasSwitch`)(true); + await createFormSetValueAction(`${phase}-selectedReplicaCount`)(value); }; const setShrink = async (value: string) => { @@ -167,6 +167,8 @@ export const setup = async () => { await createFormSetValueAction('warm-selectedPrimaryShardCount')(value); }; + const setFreeze = createFormToggleAction('freezeSwitch'); + return { ...testBed, actions: { @@ -189,13 +191,23 @@ export const setup = async () => { setMinAgeUnits: setMinAgeUnits('warm'), setDataAllocation: setDataAllocation('warm'), setSelectedNodeAttribute: setSelectedNodeAttribute('warm'), - setReplicas, + setReplicas: setReplicas('warm'), setShrink, toggleForceMerge: toggleForceMerge('warm'), setForcemergeSegments: setForcemergeSegmentsCount('warm'), setBestCompression: setBestCompression('warm'), setIndexPriority: setIndexPriority('warm'), }, + cold: { + enable: enable('cold'), + setMinAgeValue: setMinAgeValue('cold'), + setMinAgeUnits: setMinAgeUnits('cold'), + setDataAllocation: setDataAllocation('cold'), + setSelectedNodeAttribute: setSelectedNodeAttribute('cold'), + setReplicas: setReplicas('cold'), + setFreeze, + setIndexPriority: setIndexPriority('cold'), + }, }, }; }; diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts index fccffde3f793..11fadf51f27f 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts @@ -15,6 +15,7 @@ import { NEW_SNAPSHOT_POLICY_NAME, SNAPSHOT_POLICY_NAME, DEFAULT_POLICY, + POLICY_WITH_MIGRATE_OFF, POLICY_WITH_INCLUDE_EXCLUDE, POLICY_WITH_NODE_ATTR_AND_OFF_ALLOCATION, POLICY_WITH_NODE_ROLE_ALLOCATION, @@ -199,26 +200,6 @@ describe('', () => { `); }); - test('default allocation with replicas set', async () => { - const { actions } = testBed; - await actions.warm.enable(true); - await actions.warm.setReplicas('123'); - await actions.savePolicy(); - const latestRequest = server.requests[server.requests.length - 1]; - const warmPhaseActions = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm - .actions; - expect(warmPhaseActions).toMatchInlineSnapshot(` - Object { - "allocate": Object { - "number_of_replicas": 123, - }, - "set_priority": Object { - "priority": 50, - }, - } - `); - }); - test('setting warm phase on rollover to "true"', async () => { const { actions } = testBed; await actions.warm.enable(true); @@ -252,6 +233,7 @@ describe('', () => { test('preserves include, exclude allocation settings', async () => { const { actions } = testBed; await actions.warm.setDataAllocation('node_attrs'); + await actions.warm.setSelectedNodeAttribute('test:123'); await actions.savePolicy(); const latestRequest = server.requests[server.requests.length - 1]; const warmPhaseAllocate = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm @@ -264,6 +246,101 @@ describe('', () => { "include": Object { "abc": "123", }, + "require": Object { + "test": "123", + }, + } + `); + }); + }); + }); + + describe('cold phase', () => { + describe('serialization', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadPolicies([DEFAULT_POLICY]); + httpRequestsMockHelpers.setListNodes({ + nodesByRoles: {}, + nodesByAttributes: { test: ['123'] }, + isUsingDeprecatedDataRoleConfig: false, + }); + httpRequestsMockHelpers.setLoadSnapshotPolicies([]); + + await act(async () => { + testBed = await setup(); + }); + + const { component } = testBed; + component.update(); + }); + + test('default values', async () => { + const { actions } = testBed; + + await actions.cold.enable(true); + await actions.savePolicy(); + const latestRequest = server.requests[server.requests.length - 1]; + const entirePolicy = JSON.parse(JSON.parse(latestRequest.requestBody).body); + expect(entirePolicy.phases.cold).toMatchInlineSnapshot(` + Object { + "actions": Object { + "set_priority": Object { + "priority": 0, + }, + }, + "min_age": "0d", + } + `); + }); + + test('setting all values', async () => { + const { actions } = testBed; + + await actions.cold.enable(true); + await actions.cold.setMinAgeValue('123'); + await actions.cold.setMinAgeUnits('s'); + await actions.cold.setDataAllocation('node_attrs'); + await actions.cold.setSelectedNodeAttribute('test:123'); + await actions.cold.setReplicas('123'); + await actions.cold.setFreeze(true); + await actions.cold.setIndexPriority('123'); + + await actions.savePolicy(); + const latestRequest = server.requests[server.requests.length - 1]; + const entirePolicy = JSON.parse(JSON.parse(latestRequest.requestBody).body); + + expect(entirePolicy).toMatchInlineSnapshot(` + Object { + "name": "my_policy", + "phases": Object { + "cold": Object { + "actions": Object { + "allocate": Object { + "number_of_replicas": 123, + "require": Object { + "test": "123", + }, + }, + "freeze": Object {}, + "set_priority": Object { + "priority": 123, + }, + }, + "min_age": "123s", + }, + "hot": Object { + "actions": Object { + "rollover": Object { + "max_age": "30d", + "max_size": "50gb", + }, + "set_priority": Object { + "priority": 100, + }, + }, + "min_age": "0ms", + }, + }, } `); }); @@ -385,6 +462,33 @@ describe('', () => { }); describe('data allocation', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadPolicies([POLICY_WITH_MIGRATE_OFF]); + httpRequestsMockHelpers.setListNodes({ + nodesByRoles: {}, + nodesByAttributes: { test: ['123'] }, + isUsingDeprecatedDataRoleConfig: false, + }); + httpRequestsMockHelpers.setLoadSnapshotPolicies([]); + + await act(async () => { + testBed = await setup(); + }); + + const { component } = testBed; + component.update(); + }); + + test('setting node_attr based allocation, but not selecting node attribute', async () => { + const { actions } = testBed; + await actions.warm.setDataAllocation('node_attrs'); + await actions.savePolicy(); + const latestRequest = server.requests[server.requests.length - 1]; + const warmPhase = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm; + + expect(warmPhase.actions.migrate).toEqual({ enabled: false }); + }); + describe('node roles', () => { beforeEach(async () => { httpRequestsMockHelpers.setLoadPolicies([POLICY_WITH_NODE_ROLE_ALLOCATION]); @@ -401,15 +505,32 @@ describe('', () => { const { component } = testBed; component.update(); }); - test('showing "default" type', () => { + + test('detecting use of the recommended allocation type', () => { const { find } = testBed; - expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).toContain( - 'recommended' - ); - expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).not.toContain( - 'Custom' - ); - expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).not.toContain('Off'); + const selectedDataAllocation = find( + 'warm-dataTierAllocationControls.dataTierSelect' + ).text(); + expect(selectedDataAllocation).toBe('Use warm nodes (recommended)'); + }); + + test('setting replicas serialization', async () => { + const { actions } = testBed; + await actions.warm.setReplicas('123'); + await actions.savePolicy(); + const latestRequest = server.requests[server.requests.length - 1]; + const warmPhaseActions = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm + .actions; + expect(warmPhaseActions).toMatchInlineSnapshot(` + Object { + "allocate": Object { + "number_of_replicas": 123, + }, + "set_priority": Object { + "priority": 50, + }, + } + `); }); }); describe('node attr and none', () => { @@ -429,9 +550,12 @@ describe('', () => { component.update(); }); - test('showing "custom" and "off" types', () => { + test('detecting use of the custom allocation type', () => { + const { find } = testBed; + expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).toBe('Custom'); + }); + test('detecting use of the "off" allocation type', () => { const { find } = testBed; - expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).toContain('Custom'); expect(find('cold-dataTierAllocationControls.dataTierSelect').text()).toContain('Off'); }); }); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts index c6d27ca890b5..e8ebc2963d16 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts @@ -17,4 +17,5 @@ export type TestSubjects = | 'hot-selectedMaxDocuments' | 'hot-selectedMaxAge' | 'hot-selectedMaxAgeUnits' + | 'freezeSwitch' | string; diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx index 4ba6cee7b027..4a3fedfb264a 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx @@ -119,9 +119,6 @@ const noRollover = async (rendered: ReactWrapper) => { }); rendered.update(); }; -const getNodeAttributeSelectLegacy = (rendered: ReactWrapper, phase: string) => { - return rendered.find(`select#${phase}-selectedNodeAttrs`); -}; const getNodeAttributeSelect = (rendered: ReactWrapper, phase: string) => { return findTestSubject(rendered, `${phase}-selectedNodeAttrs`); }; @@ -142,15 +139,6 @@ const setPhaseAfter = async (rendered: ReactWrapper, phase: string, after: strin }); rendered.update(); }; -const setPhaseIndexPriorityLegacy = ( - rendered: ReactWrapper, - phase: string, - priority: string | number -) => { - const priorityInput = rendered.find(`input#${phase}-phaseIndexPriority`); - priorityInput.simulate('change', { target: { value: priority } }); - rendered.update(); -}; const setPhaseIndexPriority = async ( rendered: ReactWrapper, phase: string, @@ -184,7 +172,7 @@ describe('edit policy', () => { */ const waitForFormLibValidation = (rendered: ReactWrapper) => { act(() => { - jest.advanceTimersByTime(1000); + jest.runAllTimers(); }); rendered.update(); }; @@ -394,7 +382,7 @@ describe('edit policy', () => { setPolicyName(rendered, 'mypolicy'); await setPhaseIndexPriority(rendered, 'hot', '-1'); waitForFormLibValidation(rendered); - expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]); + expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]); }); }); describe('warm phase', () => { @@ -519,7 +507,7 @@ describe('edit policy', () => { await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeTruthy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy(); - expect(getNodeAttributeSelectLegacy(rendered, 'warm').exists()).toBeFalsy(); + expect(getNodeAttributeSelect(rendered, 'warm').exists()).toBeFalsy(); }); test('should show warning instead of node attributes input when none exist', async () => { http.setupNodeListResponse({ @@ -534,7 +522,7 @@ describe('edit policy', () => { expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'warm'); expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeTruthy(); - expect(getNodeAttributeSelectLegacy(rendered, 'warm').exists()).toBeFalsy(); + expect(getNodeAttributeSelect(rendered, 'warm').exists()).toBeFalsy(); }); test('should show node attributes input when attributes exist', async () => { const rendered = mountWithIntl(component); @@ -625,8 +613,9 @@ describe('edit policy', () => { await noRollover(rendered); setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); - setPhaseAfterLegacy(rendered, 'cold', '0'); - await save(rendered); + await setPhaseAfter(rendered, 'cold', '0'); + waitForFormLibValidation(rendered); + rendered.update(); expectedErrorMessages(rendered, []); }); test('should show positive number required error when trying to save cold phase with -1 for after', async () => { @@ -634,9 +623,9 @@ describe('edit policy', () => { await noRollover(rendered); setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); - setPhaseAfterLegacy(rendered, 'cold', '-1'); - await save(rendered); - expectedErrorMessages(rendered, [positiveNumberRequiredMessage]); + await setPhaseAfter(rendered, 'cold', '-1'); + waitForFormLibValidation(rendered); + expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]); }); test('should show spinner for node attributes input when loading', async () => { server.respondImmediately = false; @@ -646,7 +635,7 @@ describe('edit policy', () => { await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeTruthy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy(); - expect(getNodeAttributeSelectLegacy(rendered, 'cold').exists()).toBeFalsy(); + expect(getNodeAttributeSelect(rendered, 'cold').exists()).toBeFalsy(); }); test('should show warning instead of node attributes input when none exist', async () => { http.setupNodeListResponse({ @@ -661,7 +650,7 @@ describe('edit policy', () => { expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'cold'); expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeTruthy(); - expect(getNodeAttributeSelectLegacy(rendered, 'cold').exists()).toBeFalsy(); + expect(getNodeAttributeSelect(rendered, 'cold').exists()).toBeFalsy(); }); test('should show node attributes input when attributes exist', async () => { const rendered = mountWithIntl(component); @@ -671,7 +660,7 @@ describe('edit policy', () => { expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'cold'); expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeFalsy(); - const nodeAttributesSelect = getNodeAttributeSelectLegacy(rendered, 'cold'); + const nodeAttributesSelect = getNodeAttributeSelect(rendered, 'cold'); expect(nodeAttributesSelect.exists()).toBeTruthy(); expect(nodeAttributesSelect.find('option').length).toBe(2); }); @@ -683,7 +672,7 @@ describe('edit policy', () => { expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'cold'); expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeFalsy(); - const nodeAttributesSelect = getNodeAttributeSelectLegacy(rendered, 'cold'); + const nodeAttributesSelect = getNodeAttributeSelect(rendered, 'cold'); expect(nodeAttributesSelect.exists()).toBeTruthy(); expect(findTestSubject(rendered, 'cold-viewNodeDetailsFlyoutButton').exists()).toBeFalsy(); expect(nodeAttributesSelect.find('option').length).toBe(2); @@ -702,10 +691,10 @@ describe('edit policy', () => { await noRollover(rendered); setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); - setPhaseAfterLegacy(rendered, 'cold', '1'); - setPhaseIndexPriorityLegacy(rendered, 'cold', '-1'); - await save(rendered); - expectedErrorMessages(rendered, [positiveNumberRequiredMessage]); + await setPhaseAfter(rendered, 'cold', '1'); + await setPhaseIndexPriority(rendered, 'cold', '-1'); + waitForFormLibValidation(rendered); + expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]); }); test('should show default allocation warning when no node roles are found', async () => { http.setupNodeListResponse({ diff --git a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts index 813fcd9c253f..5692decbbf7a 100644 --- a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts +++ b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts @@ -116,7 +116,6 @@ export interface ForcemergeAction { export interface LegacyPolicy { name: string; phases: { - cold: ColdPhase; delete: DeletePhase; }; } @@ -159,14 +158,6 @@ export interface PhaseWithForcemergeAction { bestCompressionEnabled: boolean; } -export interface ColdPhase - extends CommonPhaseSettings, - PhaseWithMinAge, - PhaseWithAllocationAction, - PhaseWithIndexPriority { - freezeEnabled: boolean; -} - export interface DeletePhase extends CommonPhaseSettings, PhaseWithMinAge { waitForSnapshotPolicy: string; } diff --git a/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts b/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts index 136b68727672..23d7387aa707 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SerializedPhase, ColdPhase, DeletePhase, SerializedPolicy } from '../../../common/types'; +import { SerializedPhase, DeletePhase, SerializedPolicy } from '../../../common/types'; export const defaultSetPriority: string = '100'; @@ -24,17 +24,6 @@ export const defaultPolicy: SerializedPolicy = { }, }; -export const defaultNewColdPhase: ColdPhase = { - phaseEnabled: false, - selectedMinimumAge: '0', - selectedMinimumAgeUnits: 'd', - selectedNodeAttrs: '', - selectedReplicaCount: '', - freezeEnabled: false, - phaseIndexPriority: '0', - dataTierAllocationType: 'default', -}; - export const defaultNewDeletePhase: DeletePhase = { phaseEnabled: false, selectedMinimumAge: '0', diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/cloud_data_tier_callout.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/cloud_data_tier_callout.tsx deleted file mode 100644 index fc87b553ba52..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/cloud_data_tier_callout.tsx +++ /dev/null @@ -1,54 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import React, { FunctionComponent } from 'react'; -import { EuiCallOut, EuiLink } from '@elastic/eui'; - -import { useKibana } from '../../../../../shared_imports'; - -const deployment = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.body.elasticDeploymentLink', - { - defaultMessage: 'deployment', - } -); - -const i18nTexts = { - title: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.coldTierTitle', { - defaultMessage: 'Create a cold tier', - }), - body: (deploymentUrl?: string) => { - return ( - - {deployment} - - ) : ( - deployment - ), - }} - /> - ); - }, -}; - -export const CloudDataTierCallout: FunctionComponent = () => { - const { - services: { cloud }, - } = useKibana(); - - return ( - - {i18nTexts.body(cloud?.cloudDeploymentUrl)} - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.scss b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.scss deleted file mode 100644 index 62ec3f303e1e..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.scss +++ /dev/null @@ -1,9 +0,0 @@ -.indexLifecycleManagement__phase__dataTierAllocation { - &__controlSection { - background-color: $euiColorLightestShade; - padding-top: $euiSizeM; - padding-left: $euiSizeM; - padding-right: $euiSizeM; - padding-bottom: $euiSizeM; - } -} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.tsx deleted file mode 100644 index f58f36fc45a0..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.tsx +++ /dev/null @@ -1,184 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { FunctionComponent, useEffect } from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiText, EuiFormRow, EuiSpacer, EuiSuperSelect, EuiSuperSelectOption } from '@elastic/eui'; - -import { DataTierAllocationType } from '../../../../../../common/types'; -import { NodeAllocation } from './node_allocation'; -import { SharedProps } from './types'; - -import './data_tier_allocation.scss'; - -type SelectOptions = EuiSuperSelectOption; - -const i18nTexts = { - allocationFieldLabel: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.allocationFieldLabel', - { defaultMessage: 'Data tier options' } - ), - allocationOptions: { - warm: { - default: { - input: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.defaultOption.input', - { defaultMessage: 'Use warm nodes (recommended)' } - ), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.defaultOption.helpText', - { defaultMessage: 'Move data to nodes in the warm tier.' } - ), - }, - none: { - inputDisplay: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.noneOption.input', - { defaultMessage: 'Off' } - ), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.noneOption.helpText', - { defaultMessage: 'Do not move data in the warm phase.' } - ), - }, - custom: { - inputDisplay: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.customOption.input', - { defaultMessage: 'Custom' } - ), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.customOption.helpText', - { defaultMessage: 'Move data based on node attributes.' } - ), - }, - }, - cold: { - default: { - input: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.input', - { defaultMessage: 'Use cold nodes (recommended)' } - ), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.helpText', - { defaultMessage: 'Move data to nodes in the cold tier.' } - ), - }, - none: { - inputDisplay: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.noneOption.input', - { defaultMessage: 'Off' } - ), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.noneOption.helpText', - { defaultMessage: 'Do not move data in the cold phase.' } - ), - }, - custom: { - inputDisplay: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.input', - { defaultMessage: 'Custom' } - ), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.helpText', - { defaultMessage: 'Move data based on node attributes.' } - ), - }, - }, - }, -}; - -export const DataTierAllocation: FunctionComponent = (props) => { - const { phaseData, setPhaseData, phase, hasNodeAttributes, disableDataTierOption } = props; - - useEffect(() => { - if (disableDataTierOption && phaseData.dataTierAllocationType === 'default') { - /** - * @TODO - * This is a slight hack because we only know we should disable the "default" option further - * down the component tree (i.e., after the policy has been deserialized). - * - * We reset the value to "custom" if we deserialized to "default". - * - * It would be better if we had all the information we needed before deserializing and - * were able to handle this at the deserialization step instead of patching further down - * the component tree - this should be a future refactor. - */ - setPhaseData('dataTierAllocationType', 'custom'); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return ( -
- - setPhaseData('dataTierAllocationType', value)} - options={ - [ - disableDataTierOption - ? undefined - : { - 'data-test-subj': 'defaultDataAllocationOption', - value: 'default', - inputDisplay: i18nTexts.allocationOptions[phase].default.input, - dropdownDisplay: ( - <> - {i18nTexts.allocationOptions[phase].default.input} - -

- {i18nTexts.allocationOptions[phase].default.helpText} -

-
- - ), - }, - { - 'data-test-subj': 'customDataAllocationOption', - value: 'custom', - inputDisplay: i18nTexts.allocationOptions[phase].custom.inputDisplay, - dropdownDisplay: ( - <> - {i18nTexts.allocationOptions[phase].custom.inputDisplay} - -

- {i18nTexts.allocationOptions[phase].custom.helpText} -

-
- - ), - }, - { - 'data-test-subj': 'noneDataAllocationOption', - value: 'none', - inputDisplay: i18nTexts.allocationOptions[phase].none.inputDisplay, - dropdownDisplay: ( - <> - {i18nTexts.allocationOptions[phase].none.inputDisplay} - -

- {i18nTexts.allocationOptions[phase].none.helpText} -

-
- - ), - }, - ].filter(Boolean) as SelectOptions[] - } - /> -
- {phaseData.dataTierAllocationType === 'custom' && hasNodeAttributes && ( - <> - -
- -
- - )} -
- ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/default_allocation_notice.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/default_allocation_notice.tsx deleted file mode 100644 index 3d0052c69607..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/default_allocation_notice.tsx +++ /dev/null @@ -1,106 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import React, { FunctionComponent } from 'react'; -import { EuiCallOut } from '@elastic/eui'; - -import { PhaseWithAllocation, DataTierRole } from '../../../../../../common/types'; - -import { AllocationNodeRole } from '../../../../lib'; - -const i18nTextsNodeRoleToDataTier: Record = { - data_hot: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.dataTierHotLabel', { - defaultMessage: 'hot', - }), - data_warm: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.dataTierWarmLabel', { - defaultMessage: 'warm', - }), - data_cold: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.dataTierColdLabel', { - defaultMessage: 'cold', - }), -}; - -const i18nTexts = { - notice: { - warm: { - title: i18n.translate( - 'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm.title', - { defaultMessage: 'No nodes assigned to the warm tier' } - ), - body: (nodeRole: DataTierRole) => - i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm', { - defaultMessage: - 'This policy will move data in the warm phase to {tier} tier nodes instead.', - values: { tier: i18nTextsNodeRoleToDataTier[nodeRole] }, - }), - }, - cold: { - title: i18n.translate( - 'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold.title', - { defaultMessage: 'No nodes assigned to the cold tier' } - ), - body: (nodeRole: DataTierRole) => - i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold', { - defaultMessage: - 'This policy will move data in the cold phase to {tier} tier nodes instead.', - values: { tier: i18nTextsNodeRoleToDataTier[nodeRole] }, - }), - }, - }, - warning: { - warm: { - title: i18n.translate( - 'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableTitle', - { defaultMessage: 'No nodes assigned to the warm tier' } - ), - body: i18n.translate( - 'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableBody', - { - defaultMessage: - 'Assign at least one node to the warm or hot tier to use role-based allocation. The policy will fail to complete allocation if there are no available nodes.', - } - ), - }, - cold: { - title: i18n.translate( - 'xpack.indexLifecycleMgmt.coldPhase.dataTier.defaultAllocationNotAvailableTitle', - { defaultMessage: 'No nodes assigned to the cold tier' } - ), - body: i18n.translate( - 'xpack.indexLifecycleMgmt.coldPhase.dataTier.defaultAllocationNotAvailableBody', - { - defaultMessage: - 'Assign at least one node to the cold, warm, or hot tier to use role-based allocation. The policy will fail to complete allocation if there are no available nodes.', - } - ), - }, - }, -}; - -interface Props { - phase: PhaseWithAllocation; - targetNodeRole: AllocationNodeRole; -} - -export const DefaultAllocationNotice: FunctionComponent = ({ phase, targetNodeRole }) => { - const content = - targetNodeRole === 'none' ? ( - - {i18nTexts.warning[phase].body} - - ) : ( - - {i18nTexts.notice[phase].body(targetNodeRole)} - - ); - - return content; -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/index.ts deleted file mode 100644 index 937e3dd28da9..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/index.ts +++ /dev/null @@ -1,13 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export { NodesDataProvider } from './node_data_provider'; -export { NodeAllocation } from './node_allocation'; -export { NodeAttrsDetails } from './node_attrs_details'; -export { DataTierAllocation } from './data_tier_allocation'; -export { DefaultAllocationNotice } from './default_allocation_notice'; -export { NoNodeAttributesWarning } from './no_node_attributes_warning'; -export { CloudDataTierCallout } from './cloud_data_tier_callout'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/no_node_attributes_warning.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/no_node_attributes_warning.tsx deleted file mode 100644 index 69185277f64c..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/no_node_attributes_warning.tsx +++ /dev/null @@ -1,50 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { FunctionComponent } from 'react'; -import { EuiCallOut } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { PhaseWithAllocation } from '../../../../../../common/types'; - -const i18nTexts = { - title: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingLabel', { - defaultMessage: 'No custom node attributes configured', - }), - warm: { - body: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.warm.nodeAttributesMissingDescription', - { - defaultMessage: - 'Define custom node attributes in elasticsearch.yml to use attribute-based allocation. Warm nodes will be used instead.', - } - ), - }, - cold: { - body: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.cold.nodeAttributesMissingDescription', - { - defaultMessage: - 'Define custom node attributes in elasticsearch.yml to use attribute-based allocation. Cold nodes will be used instead.', - } - ), - }, -}; - -export const NoNodeAttributesWarning: FunctionComponent<{ phase: PhaseWithAllocation }> = ({ - phase, -}) => { - return ( - - {i18nTexts[phase].body} - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_allocation.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_allocation.tsx deleted file mode 100644 index a57a6ba4ff2c..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_allocation.tsx +++ /dev/null @@ -1,121 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useState, FunctionComponent } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; -import { EuiSelect, EuiButtonEmpty, EuiText, EuiSpacer } from '@elastic/eui'; - -import { PhaseWithAllocationAction } from '../../../../../../common/types'; -import { propertyof } from '../../../../services/policies/policy_validation'; - -import { ErrableFormRow } from '../form_errors'; - -import { NodeAttrsDetails } from './node_attrs_details'; -import { SharedProps } from './types'; -import { LearnMoreLink } from '../learn_more_link'; - -const learnMoreLink = ( - - } - docPath="modules-cluster.html#cluster-shard-allocation-settings" - /> -); - -const i18nTexts = { - doNotModifyAllocationOption: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption', - { defaultMessage: 'Do not modify allocation configuration' } - ), -}; - -export const NodeAllocation: FunctionComponent = ({ - phase, - setPhaseData, - errors, - phaseData, - isShowingErrors, - nodes, -}) => { - const [selectedNodeAttrsForDetails, setSelectedNodeAttrsForDetails] = useState( - null - ); - - const nodeOptions = Object.keys(nodes).map((attrs) => ({ - text: `${attrs} (${nodes[attrs].length})`, - value: attrs, - })); - - nodeOptions.sort((a, b) => a.value.localeCompare(b.value)); - - // check that this string is a valid property - const nodeAttrsProperty = propertyof('selectedNodeAttrs'); - - return ( - <> - -

- -

-
- - - {/* - TODO: this field component must be revisited to support setting multiple require values and to support - setting `include and exclude values on ILM policies. See https://github.com/elastic/kibana/issues/77344 - */} - setSelectedNodeAttrsForDetails(phaseData.selectedNodeAttrs)} - > - - - ) : null - } - > - { - setPhaseData(nodeAttrsProperty, e.target.value); - }} - /> - - - {selectedNodeAttrsForDetails ? ( - setSelectedNodeAttrsForDetails(null)} - /> - ) : null} - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_attrs_details.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_attrs_details.tsx deleted file mode 100644 index c29495d13eb8..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_attrs_details.tsx +++ /dev/null @@ -1,106 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { - EuiFlyoutBody, - EuiFlyout, - EuiTitle, - EuiInMemoryTable, - EuiSpacer, - EuiPortal, - EuiLoadingContent, - EuiCallOut, - EuiButton, -} from '@elastic/eui'; - -import { useLoadNodeDetails } from '../../../../services/api'; - -interface Props { - close: () => void; - selectedNodeAttrs: string; -} - -export const NodeAttrsDetails: React.FunctionComponent = ({ close, selectedNodeAttrs }) => { - const { data, isLoading, error, resendRequest } = useLoadNodeDetails(selectedNodeAttrs); - let content; - if (isLoading) { - content = ; - } else if (error) { - const { statusCode, message } = error; - content = ( - - } - color="danger" - > -

- {message} ({statusCode}) -

- - - -
- ); - } else { - content = ( - - ); - } - return ( - - - - -

- -

-
- - {content} -
-
-
- ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_data_provider.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_data_provider.tsx deleted file mode 100644 index a7c0f3ec7c86..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_data_provider.tsx +++ /dev/null @@ -1,70 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { EuiButton, EuiCallOut, EuiLoadingSpinner, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { ListNodesRouteResponse } from '../../../../../../common/types'; -import { useLoadNodes } from '../../../../services/api'; - -interface Props { - children: (data: ListNodesRouteResponse) => JSX.Element; -} - -export const NodesDataProvider = ({ children }: Props): JSX.Element => { - const { isLoading, data, error, resendRequest } = useLoadNodes(); - - if (isLoading) { - return ( - <> - - - - ); - } - - const renderError = () => { - if (error) { - const { statusCode, message } = error; - return ( - <> - - } - color="danger" - > -

- {message} ({statusCode}) -

- - - -
- - - - ); - } - return null; - }; - - return ( - <> - {renderError()} - {/* `data` will always be defined because we use an initial value when loading */} - {children(data!)} - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/types.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/types.ts deleted file mode 100644 index d3dd536d97df..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/types.ts +++ /dev/null @@ -1,28 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - ListNodesRouteResponse, - PhaseWithAllocation, - PhaseWithAllocationAction, -} from '../../../../../../common/types'; -import { PhaseValidationErrors } from '../../../../services/policies/policy_validation'; - -export interface SharedProps { - phase: PhaseWithAllocation; - errors?: PhaseValidationErrors; - phaseData: PhaseWithAllocationAction; - setPhaseData: (dataKey: keyof PhaseWithAllocationAction, value: string) => void; - isShowingErrors: boolean; - nodes: ListNodesRouteResponse['nodesByAttributes']; - hasNodeAttributes: boolean; - /** - * When on Cloud we want to disable the data tier allocation option when we detect that we are not - * using node roles in our Node config yet. See {@link ListNodesRouteResponse} for information about how this is - * detected. - */ - disableDataTierOption: boolean; -} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/forcemerge_legacy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/forcemerge_legacy.tsx deleted file mode 100644 index 0b0dbe273c02..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/forcemerge_legacy.tsx +++ /dev/null @@ -1,131 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -/** - * PLEASE NOTE: This component is currently duplicated. A version of this component wired up with - * the form lib lives in ./phases/shared - */ - -import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiDescribedFormGroup, - EuiFieldNumber, - EuiFormRow, - EuiSpacer, - EuiSwitch, - EuiTextColor, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React from 'react'; -import { LearnMoreLink } from './learn_more_link'; -import { ErrableFormRow } from './form_errors'; -import { Phases, PhaseWithForcemergeAction } from '../../../../../common/types'; -import { PhaseValidationErrors } from '../../../services/policies/policy_validation'; - -const forcemergeLabel = i18n.translate('xpack.indexLifecycleMgmt.forcemerge.enableLabel', { - defaultMessage: 'Force merge data', -}); - -const bestCompressionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.forcemerge.bestCompressionLabel', - { - defaultMessage: 'Compress stored fields', - } -); - -interface Props { - errors?: PhaseValidationErrors; - phase: keyof Phases & string; - phaseData: PhaseWithForcemergeAction; - setPhaseData: (dataKey: keyof PhaseWithForcemergeAction, value: boolean | string) => void; - isShowingErrors: boolean; -} - -export const Forcemerge: React.FunctionComponent = ({ - errors, - phaseData, - phase, - setPhaseData, - isShowingErrors, -}) => { - return ( - - - - } - description={ - - {' '} - - - } - titleSize="xs" - fullWidth - > - { - setPhaseData('forceMergeEnabled', e.target.checked); - }} - aria-controls="forcemergeContent" - /> - - -
- {phaseData.forceMergeEnabled ? ( - <> - - { - setPhaseData('selectedForceMergeSegments', e.target.value); - }} - min={1} - /> - - - } - > - { - setPhaseData('bestCompressionEnabled', e.target.checked); - }} - /> - - - ) : null} -
-
- ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts index 2b774b00b98a..a04608338718 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts @@ -11,16 +11,7 @@ export { MinAgeInput } from './min_age_input_legacy'; export { OptionalLabel } from './optional_label'; export { PhaseErrorMessage } from './phase_error_message'; export { PolicyJsonFlyout } from './policy_json_flyout'; -export { SetPriorityInput } from './set_priority_input_legacy'; export { SnapshotPolicies } from './snapshot_policies'; -export { - DataTierAllocation, - NodeAllocation, - NodeAttrsDetails, - NodesDataProvider, - DefaultAllocationNotice, -} from './data_tier_allocation'; export { DescribedFormField } from './described_form_field'; -export { Forcemerge } from './forcemerge_legacy'; export * from './phases'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase.tsx deleted file mode 100644 index da6c358aa67c..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase.tsx +++ /dev/null @@ -1,233 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { FunctionComponent, Fragment } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; -import { get } from 'lodash'; - -import { EuiFieldNumber, EuiDescribedFormGroup, EuiSwitch, EuiTextColor } from '@elastic/eui'; - -import { ColdPhase as ColdPhaseInterface, Phases } from '../../../../../../common/types'; - -import { useFormData } from '../../../../../shared_imports'; - -import { PhaseValidationErrors } from '../../../../services/policies/policy_validation'; - -import { - LearnMoreLink, - ActiveBadge, - PhaseErrorMessage, - OptionalLabel, - ErrableFormRow, - SetPriorityInput, - MinAgeInput, - DescribedFormField, -} from '../'; - -import { DataTierAllocationFieldLegacy, useRolloverPath } from './shared'; - -const i18nTexts = { - freezeLabel: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.freezeIndexLabel', { - defaultMessage: 'Freeze index', - }), - dataTierAllocation: { - description: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.dataTier.description', { - defaultMessage: - 'Move data to nodes optimized for less frequent, read-only access. Store data in the cold phase on less-expensive hardware.', - }), - }, -}; - -const coldProperty: keyof Phases = 'cold'; -const phaseProperty = (propertyName: keyof ColdPhaseInterface) => propertyName; - -interface Props { - setPhaseData: (key: keyof ColdPhaseInterface & string, value: string | boolean) => void; - phaseData: ColdPhaseInterface; - isShowingErrors: boolean; - errors?: PhaseValidationErrors; -} -export const ColdPhase: FunctionComponent = ({ - setPhaseData, - phaseData, - errors, - isShowingErrors, -}) => { - const [formData] = useFormData({ - watch: [useRolloverPath], - }); - - const hotPhaseRolloverEnabled = get(formData, useRolloverPath); - - return ( -
- <> - {/* Section title group; containing min age */} - -

- -

{' '} - {phaseData.phaseEnabled && !isShowingErrors ? : null} - -
- } - titleSize="s" - description={ - -

- -

- - } - id={`${coldProperty}-${phaseProperty('phaseEnabled')}`} - checked={phaseData.phaseEnabled} - onChange={(e) => { - setPhaseData(phaseProperty('phaseEnabled'), e.target.checked); - }} - aria-controls="coldPhaseContent" - /> -
- } - fullWidth - > - {phaseData.phaseEnabled ? ( - - errors={errors} - phaseData={phaseData} - phase={coldProperty} - isShowingErrors={isShowingErrors} - setPhaseData={setPhaseData} - rolloverEnabled={hotPhaseRolloverEnabled} - /> - ) : null} - - {phaseData.phaseEnabled ? ( - - {/* Data tier allocation section */} - - - {/* Replicas section */} - - {i18n.translate('xpack.indexLifecycleMgmt.coldPhase.replicasTitle', { - defaultMessage: 'Replicas', - })} - - } - description={i18n.translate( - 'xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasDescription', - { - defaultMessage: - 'Set the number of replicas. Remains the same as the previous phase by default.', - } - )} - switchProps={{ - label: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel', - { defaultMessage: 'Set replicas' } - ), - initialValue: Boolean(phaseData.selectedReplicaCount), - onChange: (v) => { - if (!v) { - setPhaseData('selectedReplicaCount', ''); - } - }, - }} - fullWidth - > - - - - - } - isShowingErrors={isShowingErrors} - errors={errors?.selectedReplicaCount} - > - { - setPhaseData(phaseProperty('selectedReplicaCount'), e.target.value); - }} - min={0} - /> - - - {/* Freeze section */} - - - - } - description={ - - {' '} - - - } - fullWidth - titleSize="xs" - > - { - setPhaseData(phaseProperty('freezeEnabled'), e.target.checked); - }} - label={i18nTexts.freezeLabel} - aria-label={i18nTexts.freezeLabel} - /> - - - errors={errors} - phaseData={phaseData} - phase={coldProperty} - isShowingErrors={isShowingErrors} - setPhaseData={setPhaseData} - /> - - ) : null} - -
- ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx new file mode 100644 index 000000000000..84e955a91ad7 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx @@ -0,0 +1,187 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FunctionComponent } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { get } from 'lodash'; + +import { EuiDescribedFormGroup, EuiTextColor } from '@elastic/eui'; + +import { Phases } from '../../../../../../../common/types'; + +import { + useFormData, + useFormContext, + UseField, + ToggleField, + NumericField, +} from '../../../../../../shared_imports'; + +import { useEditPolicyContext } from '../../../edit_policy_context'; + +import { LearnMoreLink, ActiveBadge, PhaseErrorMessage, DescribedFormField } from '../../'; + +import { MinAgeInputField, DataTierAllocationField, SetPriorityInput } from '../shared'; + +const i18nTexts = { + dataTierAllocation: { + description: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.dataTier.description', { + defaultMessage: + 'Move data to nodes optimized for less frequent, read-only access. Store data in the cold phase on less-expensive hardware.', + }), + }, +}; + +const coldProperty: keyof Phases = 'cold'; + +const formFieldPaths = { + enabled: '_meta.cold.enabled', +}; + +export const ColdPhase: FunctionComponent = () => { + const { originalPolicy } = useEditPolicyContext(); + const form = useFormContext(); + + const [formData] = useFormData({ + watch: [formFieldPaths.enabled], + }); + + const enabled = get(formData, formFieldPaths.enabled); + const isShowingErrors = form.isValid === false; + + return ( +
+ <> + {/* Section title group; containing min age */} + +

+ +

{' '} + {enabled && !isShowingErrors ? : null} + +
+ } + titleSize="s" + description={ + <> +

+ +

+ + + } + fullWidth + > + {enabled && } + + {enabled && ( + <> + {/* Data tier allocation section */} + + + {/* Replicas section */} + + {i18n.translate('xpack.indexLifecycleMgmt.coldPhase.replicasTitle', { + defaultMessage: 'Replicas', + })} + + } + description={i18n.translate( + 'xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasDescription', + { + defaultMessage: + 'Set the number of replicas. Remains the same as the previous phase by default.', + } + )} + switchProps={{ + 'data-test-subj': 'cold-setReplicasSwitch', + label: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel', + { defaultMessage: 'Set replicas' } + ), + initialValue: Boolean( + originalPolicy.phases.cold?.actions?.allocate?.number_of_replicas + ), + }} + fullWidth + > + + + {/* Freeze section */} + + + + } + description={ + + {' '} + + + } + fullWidth + titleSize="xs" + > + + + + + )} + +
+ ); +}; diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/shared/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/index.ts similarity index 79% rename from x-pack/plugins/ingest_pipelines/public/application/sections/shared/index.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/index.ts index 9326d1385138..df79607f33db 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/shared/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { attemptToURIDecode } from './attempt_to_uri_decode'; +export { ColdPhase } from './cold_phase'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx index 338e5367a1d0..56a59270b18a 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx @@ -19,7 +19,7 @@ const i18nTexts = { 'xpack.indexLifecycleMgmt.editPolicy.warm.nodeAttributesMissingDescription', { defaultMessage: - 'Define custom node attributes in elasticsearch.yml to use attribute-based allocation. Warm nodes will be used instead.', + 'Define custom node attributes in elasticsearch.yml to use attribute-based allocation.', } ), }, @@ -28,7 +28,7 @@ const i18nTexts = { 'xpack.indexLifecycleMgmt.editPolicy.cold.nodeAttributesMissingDescription', { defaultMessage: - 'Define custom node attributes in elasticsearch.yml to use attribute-based allocation. Cold nodes will be used instead.', + 'Define custom node attributes in elasticsearch.yml to use attribute-based allocation.', } ), }, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_legacy_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_legacy_field.tsx deleted file mode 100644 index d64df468620e..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_legacy_field.tsx +++ /dev/null @@ -1,141 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { FunctionComponent } from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiDescribedFormGroup, EuiFormRow, EuiSpacer } from '@elastic/eui'; - -import { useKibana } from '../../../../../../shared_imports'; -import { PhaseWithAllocationAction, PhaseWithAllocation } from '../../../../../../../common/types'; -import { PhaseValidationErrors } from '../../../../../services/policies/policy_validation'; -import { getAvailableNodeRoleForPhase, isNodeRoleFirstPreference } from '../../../../../lib'; - -import { - DataTierAllocation, - DefaultAllocationNotice, - NoNodeAttributesWarning, - NodesDataProvider, - CloudDataTierCallout, -} from '../../data_tier_allocation'; - -const i18nTexts = { - title: i18n.translate('xpack.indexLifecycleMgmt.common.dataTier.title', { - defaultMessage: 'Data allocation', - }), -}; - -interface Props { - description: React.ReactNode; - phase: PhaseWithAllocation; - setPhaseData: (dataKey: keyof PhaseWithAllocationAction, value: string) => void; - isShowingErrors: boolean; - errors?: PhaseValidationErrors; - phaseData: PhaseWithAllocationAction; -} - -/** - * Top-level layout control for the data tier allocation field. - */ -export const DataTierAllocationFieldLegacy: FunctionComponent = ({ - description, - phase, - phaseData, - setPhaseData, - isShowingErrors, - errors, -}) => { - const { - services: { cloud }, - } = useKibana(); - - return ( - - {({ nodesByRoles, nodesByAttributes, isUsingDeprecatedDataRoleConfig }) => { - const hasDataNodeRoles = Object.keys(nodesByRoles).some((nodeRole) => - // match any of the "data_" roles, including data_content. - nodeRole.trim().startsWith('data_') - ); - const hasNodeAttrs = Boolean(Object.keys(nodesByAttributes ?? {}).length); - - const renderNotice = () => { - switch (phaseData.dataTierAllocationType) { - case 'default': - const isCloudEnabled = cloud?.isCloudEnabled ?? false; - if (isCloudEnabled && phase === 'cold') { - const isUsingNodeRolesAllocation = - !isUsingDeprecatedDataRoleConfig && hasDataNodeRoles; - const hasNoNodesWithNodeRole = !nodesByRoles.data_cold?.length; - - if (isUsingNodeRolesAllocation && hasNoNodesWithNodeRole) { - // Tell cloud users they can deploy nodes on cloud. - return ( - <> - - - - ); - } - } - - const allocationNodeRole = getAvailableNodeRoleForPhase(phase, nodesByRoles); - if ( - allocationNodeRole === 'none' || - !isNodeRoleFirstPreference(phase, allocationNodeRole) - ) { - return ( - <> - - - - ); - } - break; - case 'custom': - if (!hasNodeAttrs) { - return ( - <> - - - - ); - } - break; - default: - return null; - } - }; - - return ( - {i18nTexts.title}} - description={description} - fullWidth - > - - <> - - - {/* Data tier related warnings and call-to-action notices */} - {renderNotice()} - - - - ); - }} - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/index.ts index 0cae3eea6316..6355dab89771 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/index.ts @@ -6,8 +6,6 @@ export { useRolloverPath } from '../../../constants'; -export { DataTierAllocationFieldLegacy } from './data_tier_allocation_legacy_field'; - export { DataTierAllocationField } from './data_tier_allocation_field'; export { Forcemerge } from './forcemerge_field'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx index 7b1a4f44b5de..06c16e8bdd5a 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx @@ -48,16 +48,21 @@ const i18nTexts = { const warmProperty: keyof Phases = 'warm'; +const formFieldPaths = { + enabled: '_meta.warm.enabled', + warmPhaseOnRollover: '_meta.warm.warmPhaseOnRollover', +}; + export const WarmPhase: FunctionComponent = () => { const { originalPolicy } = useEditPolicyContext(); const form = useFormContext(); const [formData] = useFormData({ - watch: [useRolloverPath, '_meta.warm.enabled', '_meta.warm.warmPhaseOnRollover'], + watch: [useRolloverPath, formFieldPaths.enabled, formFieldPaths.warmPhaseOnRollover], }); - const enabled = get(formData, '_meta.warm.enabled'); + const enabled = get(formData, formFieldPaths.enabled); const hotPhaseRolloverEnabled = get(formData, useRolloverPath); - const warmPhaseOnRollover = get(formData, '_meta.warm.warmPhaseOnRollover'); + const warmPhaseOnRollover = get(formData, formFieldPaths.warmPhaseOnRollover); const isShowingErrors = form.isValid === false; return ( @@ -88,7 +93,7 @@ export const WarmPhase: FunctionComponent = () => { />

{ {hotPhaseRolloverEnabled && ( = ({ ...legacyPolicy.phases, hot: p.phases.hot, warm: p.phases.warm, + cold: p.phases.cold, }, }); } else { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input_legacy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input_legacy.tsx deleted file mode 100644 index 5efbfabdf093..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input_legacy.tsx +++ /dev/null @@ -1,85 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -/** - * PLEASE NOTE: This component is currently duplicated. A version of this component wired up with - * the form lib lives in ./phases/shared - */ - -import React, { Fragment } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiFieldNumber, EuiTextColor, EuiDescribedFormGroup } from '@elastic/eui'; - -import { LearnMoreLink } from './'; -import { OptionalLabel } from './'; -import { ErrableFormRow } from './'; -import { PhaseWithIndexPriority, Phases } from '../../../../../common/types'; -import { PhaseValidationErrors, propertyof } from '../../../services/policies/policy_validation'; - -interface Props { - errors?: PhaseValidationErrors; - phase: keyof Phases & string; - phaseData: T; - setPhaseData: (dataKey: keyof T & string, value: any) => void; - isShowingErrors: boolean; -} -export const SetPriorityInput = ({ - errors, - phaseData, - phase, - setPhaseData, - isShowingErrors, -}: React.PropsWithChildren>) => { - const phaseIndexPriorityProperty = propertyof('phaseIndexPriority'); - return ( - - - - } - description={ - - {' '} - - - } - titleSize="xs" - fullWidth - > - - - - - } - isShowingErrors={isShowingErrors} - errors={errors?.phaseIndexPriority} - > - { - setPhaseData(phaseIndexPriorityProperty, e.target.value); - }} - min={0} - /> - - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts index 760c6ad713ea..f0294a5391d2 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts @@ -15,18 +15,27 @@ import { determineDataTierAllocationType } from '../../lib'; import { FormInternal } from './types'; export const deserializer = (policy: SerializedPolicy): FormInternal => { + const { + phases: { hot, warm, cold }, + } = policy; + const _meta: FormInternal['_meta'] = { hot: { - useRollover: Boolean(policy.phases.hot?.actions?.rollover), - forceMergeEnabled: Boolean(policy.phases.hot?.actions?.forcemerge), - bestCompression: policy.phases.hot?.actions?.forcemerge?.index_codec === 'best_compression', + useRollover: Boolean(hot?.actions?.rollover), + forceMergeEnabled: Boolean(hot?.actions?.forcemerge), + bestCompression: hot?.actions?.forcemerge?.index_codec === 'best_compression', }, warm: { - enabled: Boolean(policy.phases.warm), - warmPhaseOnRollover: Boolean(policy.phases.warm?.min_age === '0ms'), - forceMergeEnabled: Boolean(policy.phases.warm?.actions?.forcemerge), - bestCompression: policy.phases.warm?.actions?.forcemerge?.index_codec === 'best_compression', - dataTierAllocationType: determineDataTierAllocationType(policy.phases.warm?.actions), + enabled: Boolean(warm), + warmPhaseOnRollover: Boolean(warm?.min_age === '0ms'), + forceMergeEnabled: Boolean(warm?.actions?.forcemerge), + bestCompression: warm?.actions?.forcemerge?.index_codec === 'best_compression', + dataTierAllocationType: determineDataTierAllocationType(warm?.actions), + }, + cold: { + enabled: Boolean(cold), + dataTierAllocationType: determineDataTierAllocationType(cold?.actions), + freezeEnabled: Boolean(cold?.actions?.freeze), }, }; @@ -63,6 +72,20 @@ export const deserializer = (policy: SerializedPolicy): FormInternal => { draft._meta.warm.minAgeUnit = minAge.units; } } + + if (draft.phases.cold) { + if (draft.phases.cold.actions?.allocate?.require) { + Object.entries(draft.phases.cold.actions.allocate.require).forEach((entry) => { + draft._meta.cold.allocationNodeAttribute = entry.join(':'); + }); + } + + if (draft.phases.cold.min_age) { + const minAge = splitSizeAndUnits(draft.phases.cold.min_age); + draft.phases.cold.min_age = minAge.size; + draft._meta.cold.minAgeUnit = minAge.units; + } + } } ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx index eecdfb4871a6..5397f5da2d6b 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx @@ -92,6 +92,7 @@ const mergeAllSerializedPolicies = ( ...legacySerializedPolicy.phases, hot: serializedPolicy.phases.hot, warm: serializedPolicy.phases.warm, + cold: serializedPolicy.phases.cold, }, }; }; @@ -195,10 +196,6 @@ export const EditPolicy: React.FunctionComponent = ({ [setPolicy] ); - const setColdPhaseData = useCallback( - (key: string, value: any) => setPhaseData('cold', key, value), - [setPhaseData] - ); const setDeletePhaseData = useCallback( (key: string, value: any) => setPhaseData('delete', key, value), [setPhaseData] @@ -342,14 +339,7 @@ export const EditPolicy: React.FunctionComponent = ({ - 0 - } - setPhaseData={setColdPhaseData} - phaseData={policy.phases.cold} - /> + diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts index a80382e87539..070f03f74b95 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts @@ -11,7 +11,11 @@ import { defaultSetPriority, defaultPhaseIndexPriority } from '../../constants'; import { FormInternal } from './types'; -import { ifExistsNumberGreaterThanZero, rolloverThresholdsValidator } from './form_validations'; +import { + ifExistsNumberGreaterThanZero, + ifExistsNumberNonNegative, + rolloverThresholdsValidator, +} from './form_validations'; import { i18nTexts } from './i18n_texts'; @@ -69,6 +73,30 @@ export const schema: FormSchema = { label: i18nTexts.editPolicy.allocationNodeAttributeFieldLabel, }, }, + cold: { + enabled: { + defaultValue: false, + label: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.coldPhase.activateColdPhaseSwitchLabel', + { defaultMessage: 'Activate cold phase' } + ), + }, + freezeEnabled: { + defaultValue: false, + label: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.freezeIndexLabel', { + defaultMessage: 'Freeze index', + }), + }, + minAgeUnit: { + defaultValue: 'd', + }, + dataTierAllocationType: { + label: i18nTexts.editPolicy.allocationTypeOptionsFieldLabel, + }, + allocationNodeAttribute: { + label: i18nTexts.editPolicy.allocationNodeAttributeFieldLabel, + }, + }, }, phases: { hot: { @@ -138,7 +166,7 @@ export const schema: FormSchema = { priority: { defaultValue: defaultSetPriority as any, label: i18nTexts.editPolicy.setPriorityFieldLabel, - validations: [{ validator: ifExistsNumberGreaterThanZero }], + validations: [{ validator: ifExistsNumberNonNegative }], serializer: serializers.stringToNumber, }, }, @@ -217,7 +245,48 @@ export const schema: FormSchema = { priority: { defaultValue: defaultPhaseIndexPriority as any, label: i18nTexts.editPolicy.setPriorityFieldLabel, - validations: [{ validator: ifExistsNumberGreaterThanZero }], + validations: [{ validator: ifExistsNumberNonNegative }], + serializer: serializers.stringToNumber, + }, + }, + }, + }, + cold: { + min_age: { + defaultValue: '0', + validations: [ + { + validator: (arg) => + numberGreaterThanField({ + than: 0, + allowEquality: true, + message: i18nTexts.editPolicy.errors.nonNegativeNumberRequired, + })({ + ...arg, + value: arg.value === '' ? -Infinity : parseInt(arg.value, 10), + }), + }, + ], + }, + actions: { + allocate: { + number_of_replicas: { + label: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasLabel', { + defaultMessage: 'Number of replicas (optional)', + }), + validations: [ + { + validator: ifExistsNumberGreaterThanZero, + }, + ], + serializer: serializers.stringToNumber, + }, + }, + set_priority: { + priority: { + defaultValue: '0' as any, + label: i18nTexts.editPolicy.setPriorityFieldLabel, + validations: [{ validator: ifExistsNumberNonNegative }], serializer: serializers.stringToNumber, }, }, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts index 37ca4e9def34..9c855ccb4162 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts @@ -12,18 +12,36 @@ import { i18nTexts } from './i18n_texts'; const { numberGreaterThanField } = fieldValidators; -export const ifExistsNumberGreaterThanZero: ValidationFunc = (arg) => { - if (arg.value) { - return numberGreaterThanField({ - than: 0, - message: i18nTexts.editPolicy.errors.numberGreatThan0Required, - })({ - ...arg, - value: parseInt(arg.value, 10), - }); - } +const createIfNumberExistsValidator = ({ + than, + message, +}: { + than: number; + message: string; +}): ValidationFunc => { + return (arg) => { + if (arg.value) { + return numberGreaterThanField({ + than, + message, + })({ + ...arg, + value: parseInt(arg.value, 10), + }); + } + }; }; +export const ifExistsNumberGreaterThanZero = createIfNumberExistsValidator({ + than: 0, + message: i18nTexts.editPolicy.errors.numberGreatThan0Required, +}); + +export const ifExistsNumberNonNegative = createIfNumberExistsValidator({ + than: -1, + message: i18nTexts.editPolicy.errors.nonNegativeNumberRequired, +}); + /** * A special validation type used to keep track of validation errors for * the rollover threshold values not being set (e.g., age and doc count) diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts index 90e81528f5af..564b5a2c4e39 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts @@ -31,6 +31,11 @@ const serializeAllocateAction = ( [name]: value, }, }; + } else { + // The form has been configured to use node attribute based allocation but no node attribute + // was selected. We fall back to what was originally selected in this case. This might be + // migrate.enabled: "false" + actions.migrate = originalActions.migrate; } // copy over the original include and exclude values until we can set them in the form. @@ -129,5 +134,36 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => ( } } + /** + * COLD PHASE SERIALIZATION + */ + if (policy.phases.cold) { + if (policy.phases.cold.min_age) { + policy.phases.cold.min_age = `${policy.phases.cold.min_age}${_meta.cold.minAgeUnit}`; + } + + policy.phases.cold.actions = serializeAllocateAction( + _meta.cold, + policy.phases.cold.actions, + originalPolicy?.phases.cold?.actions + ); + + if ( + policy.phases.cold.actions.allocate && + !policy.phases.cold.actions.allocate.require && + !isNumber(policy.phases.cold.actions.allocate.number_of_replicas) && + isEmpty(policy.phases.cold.actions.allocate.include) && + isEmpty(policy.phases.cold.actions.allocate.exclude) + ) { + // remove allocate action if it does not define require or number of nodes + // and both include and exclude are empty objects (ES will fail to parse if we don't) + delete policy.phases.cold.actions.allocate; + } + + if (_meta.cold.freezeEnabled) { + policy.phases.cold.actions.freeze = {}; + } + } + return policy; }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts index 6fcfbd050c69..1884f8dbc061 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts @@ -13,20 +13,29 @@ export interface DataAllocationMetaFields { allocationNodeAttribute?: string; } -interface HotPhaseMetaFields { - useRollover: boolean; +export interface MinAgeField { + minAgeUnit?: string; +} + +export interface ForcemergeFields { forceMergeEnabled: boolean; bestCompression: boolean; +} + +interface HotPhaseMetaFields extends ForcemergeFields { + useRollover: boolean; maxStorageSizeUnit?: string; maxAgeUnit?: string; } -interface WarmPhaseMetaFields extends DataAllocationMetaFields { +interface WarmPhaseMetaFields extends DataAllocationMetaFields, MinAgeField, ForcemergeFields { enabled: boolean; - forceMergeEnabled: boolean; - bestCompression: boolean; warmPhaseOnRollover: boolean; - minAgeUnit?: string; +} + +interface ColdPhaseMetaFields extends DataAllocationMetaFields, MinAgeField { + enabled: boolean; + freezeEnabled: boolean; } /** @@ -40,5 +49,6 @@ export interface FormInternal extends SerializedPolicy { _meta: { hot: HotPhaseMetaFields; warm: WarmPhaseMetaFields; + cold: ColdPhaseMetaFields; }; } diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/table_content.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/table_content.tsx index 50c67f789c3a..7b6521fd8a9e 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/table_content.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/policy_table/components/table_content.tsx @@ -193,7 +193,7 @@ export const TableContent: React.FunctionComponent = ({ icon: 'list', onClick: () => { navigateToApp('management', { - path: `/data/index_management${getIndexListUri(`ilm.policy:${policy.name}`, true)}`, + path: `/data/index_management${getIndexListUri(`ilm.policy:"${policy.name}"`, true)}`, }); }, }); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/cold_phase.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/cold_phase.ts deleted file mode 100644 index faf3954f93fd..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/cold_phase.ts +++ /dev/null @@ -1,154 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { isEmpty } from 'lodash'; -import { AllocateAction, ColdPhase, SerializedColdPhase } from '../../../../common/types'; -import { serializedPhaseInitialization } from '../../constants'; -import { isNumber, splitSizeAndUnits } from './policy_serialization'; -import { - numberRequiredMessage, - PhaseValidationErrors, - positiveNumberRequiredMessage, -} from './policy_validation'; -import { determineDataTierAllocationTypeLegacy } from '../../lib'; -import { serializePhaseWithAllocation } from './shared'; - -export const coldPhaseInitialization: ColdPhase = { - phaseEnabled: false, - selectedMinimumAge: '0', - selectedMinimumAgeUnits: 'd', - selectedNodeAttrs: '', - selectedReplicaCount: '', - freezeEnabled: false, - phaseIndexPriority: '', - dataTierAllocationType: 'default', -}; - -export const coldPhaseFromES = (phaseSerialized?: SerializedColdPhase): ColdPhase => { - const phase = { ...coldPhaseInitialization }; - if (phaseSerialized === undefined || phaseSerialized === null) { - return phase; - } - - phase.phaseEnabled = true; - - if (phaseSerialized.actions) { - phase.dataTierAllocationType = determineDataTierAllocationTypeLegacy(phaseSerialized.actions); - } - - if (phaseSerialized.min_age) { - const { size: minAge, units: minAgeUnits } = splitSizeAndUnits(phaseSerialized.min_age); - phase.selectedMinimumAge = minAge; - phase.selectedMinimumAgeUnits = minAgeUnits; - } - - if (phaseSerialized.actions) { - const actions = phaseSerialized.actions; - if (actions.allocate) { - const allocate = actions.allocate; - if (allocate.require) { - Object.entries(allocate.require).forEach((entry) => { - phase.selectedNodeAttrs = entry.join(':'); - }); - if (allocate.number_of_replicas) { - phase.selectedReplicaCount = allocate.number_of_replicas.toString(); - } - } - } - - if (actions.freeze) { - phase.freezeEnabled = true; - } - - if (actions.set_priority) { - phase.phaseIndexPriority = actions.set_priority.priority - ? actions.set_priority.priority.toString() - : ''; - } - } - - return phase; -}; - -export const coldPhaseToES = ( - phase: ColdPhase, - originalPhase: SerializedColdPhase | undefined -): SerializedColdPhase => { - if (!originalPhase) { - originalPhase = { ...serializedPhaseInitialization }; - } - - const esPhase = { ...originalPhase }; - - if (isNumber(phase.selectedMinimumAge)) { - esPhase.min_age = `${phase.selectedMinimumAge}${phase.selectedMinimumAgeUnits}`; - } - - esPhase.actions = serializePhaseWithAllocation(phase, esPhase.actions); - - if (isNumber(phase.selectedReplicaCount)) { - esPhase.actions.allocate = esPhase.actions.allocate || ({} as AllocateAction); - esPhase.actions.allocate.number_of_replicas = parseInt(phase.selectedReplicaCount, 10); - } else { - if (esPhase.actions.allocate) { - delete esPhase.actions.allocate.number_of_replicas; - } - } - - if ( - esPhase.actions.allocate && - !esPhase.actions.allocate.require && - !isNumber(esPhase.actions.allocate.number_of_replicas) && - isEmpty(esPhase.actions.allocate.include) && - isEmpty(esPhase.actions.allocate.exclude) - ) { - // remove allocate action if it does not define require or number of nodes - // and both include and exclude are empty objects (ES will fail to parse if we don't) - delete esPhase.actions.allocate; - } - - if (phase.freezeEnabled) { - esPhase.actions.freeze = {}; - } else { - delete esPhase.actions.freeze; - } - - if (isNumber(phase.phaseIndexPriority)) { - esPhase.actions.set_priority = { - priority: parseInt(phase.phaseIndexPriority, 10), - }; - } else { - delete esPhase.actions.set_priority; - } - - return esPhase; -}; - -export const validateColdPhase = (phase: ColdPhase): PhaseValidationErrors => { - if (!phase.phaseEnabled) { - return {}; - } - - const phaseErrors = {} as PhaseValidationErrors; - - // index priority is optional, but if it's set, it needs to be a positive number - if (phase.phaseIndexPriority) { - if (!isNumber(phase.phaseIndexPriority)) { - phaseErrors.phaseIndexPriority = [numberRequiredMessage]; - } else if (parseInt(phase.phaseIndexPriority, 10) < 0) { - phaseErrors.phaseIndexPriority = [positiveNumberRequiredMessage]; - } - } - - // min age needs to be a positive number - if (!isNumber(phase.selectedMinimumAge)) { - phaseErrors.selectedMinimumAge = [numberRequiredMessage]; - } else if (parseInt(phase.selectedMinimumAge, 10) < 0) { - phaseErrors.selectedMinimumAge = [positiveNumberRequiredMessage]; - } - - return { ...phaseErrors }; -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts index 0be6ab352173..19481b39a2c8 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts @@ -7,9 +7,7 @@ // eslint-disable-next-line no-restricted-imports import cloneDeep from 'lodash/cloneDeep'; import { deserializePolicy, legacySerializePolicy } from './policy_serialization'; -import { defaultNewColdPhase, defaultNewDeletePhase } from '../../constants'; -import { DataTierAllocationType } from '../../../../common/types'; -import { coldPhaseInitialization } from './cold_phase'; +import { defaultNewDeletePhase } from '../../constants'; describe('Policy serialization', () => { test('serialize a policy using "default" data allocation', () => { @@ -18,12 +16,6 @@ describe('Policy serialization', () => { { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - dataTierAllocationType: 'default', - selectedNodeAttrs: 'another:thing', - phaseEnabled: true, - }, delete: { ...defaultNewDeletePhase }, }, }, @@ -31,24 +23,12 @@ describe('Policy serialization', () => { name: 'test', phases: { hot: { actions: {} }, - cold: { - actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } }, - }, }, } ) ).toEqual({ name: 'test', - phases: { - cold: { - actions: { - set_priority: { - priority: 0, - }, - }, - min_age: '0d', - }, - }, + phases: {}, }); }); @@ -58,12 +38,6 @@ describe('Policy serialization', () => { { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - dataTierAllocationType: 'custom', - selectedNodeAttrs: 'another:thing', - phaseEnabled: true, - }, delete: { ...defaultNewDeletePhase }, }, }, @@ -71,37 +45,12 @@ describe('Policy serialization', () => { name: 'test', phases: { hot: { actions: {} }, - cold: { - actions: { - allocate: { - include: { keep: 'this' }, - exclude: { keep: 'this' }, - require: { something: 'here' }, - }, - }, - }, }, } ) ).toEqual({ name: 'test', - phases: { - cold: { - actions: { - allocate: { - include: { keep: 'this' }, - exclude: { keep: 'this' }, - require: { - another: 'thing', - }, - }, - set_priority: { - priority: 0, - }, - }, - min_age: '0d', - }, - }, + phases: {}, }); }); @@ -111,12 +60,6 @@ describe('Policy serialization', () => { { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - dataTierAllocationType: 'custom', - selectedNodeAttrs: '', - phaseEnabled: true, - }, delete: { ...defaultNewDeletePhase }, }, }, @@ -124,26 +67,13 @@ describe('Policy serialization', () => { name: 'test', phases: { hot: { actions: {} }, - cold: { - actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } }, - }, }, } ) ).toEqual({ // There should be no allocation action in any phases... name: 'test', - phases: { - cold: { - actions: { - allocate: { include: {}, exclude: {}, require: { something: 'here' } }, - set_priority: { - priority: 0, - }, - }, - min_age: '0d', - }, - }, + phases: {}, }); }); @@ -153,12 +83,6 @@ describe('Policy serialization', () => { { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - dataTierAllocationType: 'none', - selectedNodeAttrs: 'ignore:this', - phaseEnabled: true, - }, delete: { ...defaultNewDeletePhase }, }, }, @@ -166,39 +90,20 @@ describe('Policy serialization', () => { name: 'test', phases: { hot: { actions: {} }, - cold: { - actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } }, - }, }, } ) ).toEqual({ // There should be no allocation action in any phases... name: 'test', - phases: { - cold: { - actions: { - migrate: { - enabled: false, - }, - set_priority: { - priority: 0, - }, - }, - min_age: '0d', - }, - }, + phases: {}, }); }); test('serialization does not alter the original policy', () => { const originalPolicy = { name: 'test', - phases: { - cold: { - actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } }, - }, - }, + phases: {}, }; const originalClone = cloneDeep(originalPolicy); @@ -206,13 +111,6 @@ describe('Policy serialization', () => { const deserializedPolicy = { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - dataTierAllocationType: 'none' as DataTierAllocationType, - selectedNodeAttrs: 'ignore:this', - phaseEnabled: true, - }, - delete: { ...defaultNewDeletePhase }, }, }; @@ -227,9 +125,6 @@ describe('Policy serialization', () => { { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - }, delete: { ...defaultNewDeletePhase }, }, }, @@ -276,9 +171,6 @@ describe('Policy serialization', () => { ).toEqual({ name: 'test', phases: { - cold: { - ...coldPhaseInitialization, - }, delete: { ...defaultNewDeletePhase }, }, }); @@ -290,9 +182,6 @@ describe('Policy serialization', () => { { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - }, delete: { ...defaultNewDeletePhase }, }, }, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts index 32c7e698b092..55e9d88dcd38 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts @@ -6,13 +6,8 @@ import { LegacyPolicy, PolicyFromES, SerializedPolicy } from '../../../../common/types'; -import { - defaultNewColdPhase, - defaultNewDeletePhase, - serializedPhaseInitialization, -} from '../../constants'; +import { defaultNewDeletePhase, serializedPhaseInitialization } from '../../constants'; -import { coldPhaseFromES, coldPhaseToES } from './cold_phase'; import { deletePhaseFromES, deletePhaseToES } from './delete_phase'; export const splitSizeAndUnits = (field: string): { size: string; units: string } => { @@ -46,7 +41,6 @@ export const initializeNewPolicy = (newPolicyName: string = ''): LegacyPolicy => return { name: newPolicyName, phases: { - cold: { ...defaultNewColdPhase }, delete: { ...defaultNewDeletePhase }, }, }; @@ -61,7 +55,6 @@ export const deserializePolicy = (policy: PolicyFromES): LegacyPolicy => { return { name, phases: { - cold: coldPhaseFromES(phases.cold), delete: deletePhaseFromES(phases.delete), }, }; @@ -79,10 +72,6 @@ export const legacySerializePolicy = ( phases: {}, } as SerializedPolicy; - if (policy.phases.cold.phaseEnabled) { - serializedPolicy.phases.cold = coldPhaseToES(policy.phases.cold, originalEsPolicy.phases.cold); - } - if (policy.phases.delete.phaseEnabled) { serializedPolicy.phases.delete = deletePhaseToES( policy.phases.delete, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts index a113cb68a234..79c909c433f3 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts @@ -5,8 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { ColdPhase, DeletePhase, LegacyPolicy, PolicyFromES } from '../../../../common/types'; -import { validateColdPhase } from './cold_phase'; +import { DeletePhase, LegacyPolicy, PolicyFromES } from '../../../../common/types'; import { validateDeletePhase } from './delete_phase'; export const propertyof = (propertyName: keyof T & string) => propertyName; @@ -82,7 +81,6 @@ export type PhaseValidationErrors = { }; export interface ValidationErrors { - cold: PhaseValidationErrors; delete: PhaseValidationErrors; policyName: string[]; } @@ -120,17 +118,12 @@ export const validatePolicy = ( } } - const coldPhaseErrors = validateColdPhase(policy.phases.cold); const deletePhaseErrors = validateDeletePhase(policy.phases.delete); - const isValid = - policyNameErrors.length === 0 && - Object.keys(coldPhaseErrors).length === 0 && - Object.keys(deletePhaseErrors).length === 0; + const isValid = policyNameErrors.length === 0 && Object.keys(deletePhaseErrors).length === 0; return [ isValid, { policyName: [...policyNameErrors], - cold: coldPhaseErrors, delete: deletePhaseErrors, }, ]; @@ -145,9 +138,6 @@ export const findFirstError = (errors?: ValidationErrors): string | undefined => return propertyof('policyName'); } - if (Object.keys(errors.cold).length > 0) { - return `${propertyof('cold')}.${Object.keys(errors.cold)[0]}`; - } if (Object.keys(errors.delete).length > 0) { return `${propertyof('delete')}.${Object.keys(errors.delete)[0]}`; } diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/serialize_phase_with_allocation.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/serialize_phase_with_allocation.ts deleted file mode 100644 index c29ae3ab2283..000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/serialize_phase_with_allocation.ts +++ /dev/null @@ -1,42 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -// Prefer importing entire lodash library, e.g. import { get } from "lodash" -// eslint-disable-next-line no-restricted-imports -import cloneDeep from 'lodash/cloneDeep'; - -import { - AllocateAction, - PhaseWithAllocationAction, - SerializedPhase, -} from '../../../../../common/types'; - -export const serializePhaseWithAllocation = ( - phase: PhaseWithAllocationAction, - originalPhaseActions: SerializedPhase['actions'] = {} -): SerializedPhase['actions'] => { - const esPhaseActions: SerializedPhase['actions'] = cloneDeep(originalPhaseActions); - - if (phase.dataTierAllocationType === 'custom' && phase.selectedNodeAttrs) { - const [name, value] = phase.selectedNodeAttrs.split(':'); - esPhaseActions.allocate = esPhaseActions.allocate || ({} as AllocateAction); - esPhaseActions.allocate.require = { - [name]: value, - }; - } else if (phase.dataTierAllocationType === 'none') { - esPhaseActions.migrate = { enabled: false }; - if (esPhaseActions.allocate) { - delete esPhaseActions.allocate; - } - } else if (phase.dataTierAllocationType === 'default') { - if (esPhaseActions.allocate) { - delete esPhaseActions.allocate.require; - } - delete esPhaseActions.migrate; - } - - return esPhaseActions; -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts index c77e3d22f0e3..2f1c7798e7a4 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts @@ -9,7 +9,6 @@ import { UIM_CONFIG_WARM_PHASE, UIM_CONFIG_SET_PRIORITY, UIM_CONFIG_FREEZE_INDEX, - defaultNewColdPhase, defaultPhaseIndexPriority, } from '../constants/'; @@ -23,7 +22,7 @@ describe('getUiMetricsForPhases', () => { min_age: '0ms', actions: { set_priority: { - priority: parseInt(defaultNewColdPhase.phaseIndexPriority, 10), + priority: parseInt(defaultPhaseIndexPriority, 10), }, }, }, @@ -69,7 +68,7 @@ describe('getUiMetricsForPhases', () => { actions: { freeze: {}, set_priority: { - priority: parseInt(defaultNewColdPhase.phaseIndexPriority, 10), + priority: parseInt(defaultPhaseIndexPriority, 10), }, }, }, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts index 305b35b23e4d..274d3d1ca97f 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts @@ -13,7 +13,6 @@ import { UIM_CONFIG_FREEZE_INDEX, UIM_CONFIG_SET_PRIORITY, UIM_CONFIG_WARM_PHASE, - defaultNewColdPhase, defaultSetPriority, defaultPhaseIndexPriority, } from '../constants'; @@ -55,8 +54,7 @@ export function getUiMetricsForPhases(phases: Phases): string[] { const isColdPhasePriorityChanged = phases.cold && phases.cold.actions.set_priority && - phases.cold.actions.set_priority.priority !== - parseInt(defaultNewColdPhase.phaseIndexPriority, 10); + phases.cold.actions.set_priority.priority !== parseInt(defaultPhaseIndexPriority, 10); // If the priority is different than the default, we'll consider it a user interaction, // even if the user has set it to undefined. return ( diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.helpers.ts b/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.helpers.ts index 2fcf2a822cb2..82bd858240e1 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.helpers.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.helpers.ts @@ -186,3 +186,28 @@ export const createDataStreamPayload = (name: string): DataStream => ({ storageSize: '1b', maxTimeStamp: 420, }); + +export const createDataStreamBackingIndex = (indexName: string, dataStreamName: string) => ({ + health: '', + status: '', + primary: '', + replica: '', + documents: '', + documents_deleted: '', + size: '', + primary_size: '', + name: indexName, + data_stream: dataStreamName, +}); + +export const createNonDataStreamIndex = (name: string) => ({ + health: 'green', + status: 'open', + primary: 1, + replica: 1, + documents: 10000, + documents_deleted: 100, + size: '156kb', + primary_size: '156kb', + name, +}); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts b/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts index ade4a62ceb19..23539659d2af 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts @@ -9,7 +9,13 @@ import { act } from 'react-dom/test-utils'; import { API_BASE_PATH } from '../../../common/constants'; import { setupEnvironment } from '../helpers'; -import { DataStreamsTabTestBed, setup, createDataStreamPayload } from './data_streams_tab.helpers'; +import { + DataStreamsTabTestBed, + setup, + createDataStreamPayload, + createDataStreamBackingIndex, + createNonDataStreamIndex, +} from './data_streams_tab.helpers'; describe('Data Streams tab', () => { const { server, httpRequestsMockHelpers } = setupEnvironment(); @@ -85,29 +91,8 @@ describe('Data Streams tab', () => { } = httpRequestsMockHelpers; setLoadIndicesResponse([ - { - health: '', - status: '', - primary: '', - replica: '', - documents: '', - documents_deleted: '', - size: '', - primary_size: '', - name: 'data-stream-index', - data_stream: 'dataStream1', - }, - { - health: 'green', - status: 'open', - primary: 1, - replica: 1, - documents: 10000, - documents_deleted: 100, - size: '156kb', - primary_size: '156kb', - name: 'non-data-stream-index', - }, + createDataStreamBackingIndex('data-stream-index', 'dataStream1'), + createNonDataStreamIndex('non-data-stream-index'), ]); const dataStreamForDetailPanel = createDataStreamPayload('dataStream1'); @@ -260,4 +245,46 @@ describe('Data Streams tab', () => { }); }); }); + + describe('when there are special characters', () => { + beforeEach(async () => { + const { + setLoadIndicesResponse, + setLoadDataStreamsResponse, + setLoadDataStreamResponse, + } = httpRequestsMockHelpers; + + setLoadIndicesResponse([ + createDataStreamBackingIndex('data-stream-index', '%dataStream'), + createDataStreamBackingIndex('data-stream-index2', 'dataStream2'), + ]); + + const dataStreamDollarSign = createDataStreamPayload('%dataStream'); + setLoadDataStreamsResponse([dataStreamDollarSign]); + setLoadDataStreamResponse(dataStreamDollarSign); + + testBed = await setup(); + await act(async () => { + testBed.actions.goToDataStreamsList(); + }); + testBed.component.update(); + }); + + describe('detail panel', () => { + test('opens when the data stream name in the table is clicked', async () => { + const { actions, findDetailPanel, findDetailPanelTitle } = testBed; + await actions.clickNameAt(0); + expect(findDetailPanel().length).toBe(1); + expect(findDetailPanelTitle()).toBe('%dataStream'); + }); + + test('clicking the indices count navigates to the backing indices', async () => { + const { table, actions } = testBed; + await actions.clickIndicesAt(0); + expect(table.getMetaData('indexTable').tableCellsValues).toEqual([ + ['', '', '', '', '', '', '', '%dataStream'], + ]); + }); + }); + }); }); diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_details/component_template_details.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_details/component_template_details.tsx index 0f5bc64c358b..6d9aa58d6c86 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_details/component_template_details.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_details/component_template_details.tsx @@ -20,12 +20,17 @@ import { EuiBadge, } from '@elastic/eui'; -import { SectionLoading, TabSettings, TabAliases, TabMappings } from '../shared_imports'; +import { + SectionLoading, + TabSettings, + TabAliases, + TabMappings, + attemptToURIDecode, +} from '../shared_imports'; import { useComponentTemplatesContext } from '../component_templates_context'; import { TabSummary } from './tab_summary'; import { ComponentTemplateTabs, TabType } from './tabs'; import { ManageButton, ManageAction } from './manage_button'; -import { attemptToDecodeURI } from '../lib'; export interface Props { componentTemplateName: string; @@ -47,7 +52,7 @@ export const ComponentTemplateDetailsFlyoutContent: React.FunctionComponent { const { api } = useComponentTemplatesContext(); - const decodedComponentTemplateName = attemptToDecodeURI(componentTemplateName); + const decodedComponentTemplateName = attemptToURIDecode(componentTemplateName); const { data: componentTemplateDetails, isLoading, error } = api.useLoadComponentTemplate( decodedComponentTemplateName diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx index 05f7f53969de..00ea3ebf794e 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list.tsx @@ -11,9 +11,9 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { ScopedHistory } from 'kibana/public'; import { EuiLink, EuiText, EuiSpacer } from '@elastic/eui'; +import { attemptToURIDecode } from '../../../../shared_imports'; import { SectionLoading, ComponentTemplateDeserialized, GlobalFlyout } from '../shared_imports'; import { UIM_COMPONENT_TEMPLATE_LIST_LOAD } from '../constants'; -import { attemptToDecodeURI } from '../lib'; import { useComponentTemplatesContext } from '../component_templates_context'; import { ComponentTemplateDetailsFlyoutContent, @@ -84,7 +84,7 @@ export const ComponentTemplateList: React.FunctionComponent = ({ }), icon: 'pencil', handleActionClick: () => - goToEditComponentTemplate(attemptToDecodeURI(componentTemplateName)), + goToEditComponentTemplate(attemptToURIDecode(componentTemplateName)), }, { name: i18n.translate('xpack.idxMgmt.componentTemplateDetails.cloneActionLabel', { @@ -92,7 +92,7 @@ export const ComponentTemplateList: React.FunctionComponent = ({ }), icon: 'copy', handleActionClick: () => - goToCloneComponentTemplate(attemptToDecodeURI(componentTemplateName)), + goToCloneComponentTemplate(attemptToURIDecode(componentTemplateName)), }, { name: i18n.translate('xpack.idxMgmt.componentTemplateDetails.deleteButtonLabel', { @@ -103,7 +103,7 @@ export const ComponentTemplateList: React.FunctionComponent = ({ details._kbnMeta.usedBy.length > 0, closePopoverOnClick: true, handleActionClick: () => { - setComponentTemplatesToDelete([attemptToDecodeURI(componentTemplateName)]); + setComponentTemplatesToDelete([attemptToURIDecode(componentTemplateName)]); }, }, ]; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_clone/component_template_clone.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_clone/component_template_clone.tsx index 94db623f313c..6c03fcf5d997 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_clone/component_template_clone.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_clone/component_template_clone.tsx @@ -9,9 +9,8 @@ import { RouteComponentProps } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { SectionLoading } from '../../shared_imports'; +import { SectionLoading, attemptToURIDecode } from '../../shared_imports'; import { useComponentTemplatesContext } from '../../component_templates_context'; -import { attemptToDecodeURI } from '../../lib'; import { ComponentTemplateCreate } from '../component_template_create'; export interface Params { @@ -20,7 +19,7 @@ export interface Params { export const ComponentTemplateClone: FunctionComponent> = (props) => { const { sourceComponentTemplateName } = props.match.params; - const decodedSourceName = attemptToDecodeURI(sourceComponentTemplateName); + const decodedSourceName = attemptToURIDecode(sourceComponentTemplateName); const { toasts, api } = useComponentTemplatesContext(); diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx index 2bd3dfb34acb..934f86f7d759 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx +++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_edit/component_template_edit.tsx @@ -9,8 +9,11 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { EuiPageBody, EuiPageContent, EuiTitle, EuiSpacer, EuiCallOut } from '@elastic/eui'; import { useComponentTemplatesContext } from '../../component_templates_context'; -import { ComponentTemplateDeserialized, SectionLoading } from '../../shared_imports'; -import { attemptToDecodeURI } from '../../lib'; +import { + ComponentTemplateDeserialized, + SectionLoading, + attemptToURIDecode, +} from '../../shared_imports'; import { ComponentTemplateForm } from '../component_template_form'; interface MatchParams { @@ -28,7 +31,7 @@ export const ComponentTemplateEdit: React.FunctionComponent(false); const [saveError, setSaveError] = useState(null); - const decodedName = attemptToDecodeURI(name); + const decodedName = attemptToURIDecode(name); const { error, data: componentTemplate, isLoading } = api.useLoadComponentTemplate(decodedName); @@ -50,7 +53,9 @@ export const ComponentTemplateEdit: React.FunctionComponent { - let result: string; - - try { - result = decodeURI(value); - result = decodeURIComponent(result); - } catch (e) { - result = decodeURIComponent(value); - } - - return result; -}; diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/shared_imports.ts b/x-pack/plugins/index_management/public/application/components/component_templates/shared_imports.ts index ffd78925c16a..4a9771bd5ba8 100644 --- a/x-pack/plugins/index_management/public/application/components/component_templates/shared_imports.ts +++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared_imports.ts @@ -20,6 +20,7 @@ export { NotAuthorizedSection, Forms, GlobalFlyout, + attemptToURIDecode, } from '../../../../../../../src/plugins/es_ui_shared/public'; export { diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx index 4f2a5c4a27b7..19286523055f 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx @@ -20,13 +20,17 @@ import { } from '@elastic/eui'; import { ScopedHistory } from 'kibana/public'; -import { reactRouterNavigate, extractQueryParams } from '../../../../shared_imports'; +import { + reactRouterNavigate, + extractQueryParams, + attemptToURIDecode, +} from '../../../../shared_imports'; import { useAppContext } from '../../../app_context'; import { SectionError, SectionLoading, Error } from '../../../components'; import { useLoadDataStreams } from '../../../services/api'; -import { encodePathForReactRouter, decodePathFromReactRouter } from '../../../services/routing'; +import { getIndexListUri } from '../../../services/routing'; import { documentationService } from '../../../services/documentation'; -import { Section } from '../../home'; +import { Section } from '../home'; import { DataStreamTable } from './data_stream_table'; import { DataStreamDetailPanel } from './data_stream_detail_panel'; @@ -206,7 +210,7 @@ export const DataStreamList: React.FunctionComponent { history.push(`/${Section.DataStreams}`); diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx index 642123c51141..992d569bf3a4 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx @@ -12,9 +12,8 @@ import { ScopedHistory } from 'kibana/public'; import { DataStream } from '../../../../../../common/types'; import { UseRequestResponse, reactRouterNavigate } from '../../../../../shared_imports'; -import { encodePathForReactRouter } from '../../../../services/routing'; +import { getDataStreamDetailsLink, getIndexListUri } from '../../../../services/routing'; import { DataHealth } from '../../../../components'; -import { Section } from '../../../home'; import { DeleteDataStreamConfirmationModal } from '../delete_data_stream_confirmation_modal'; import { humanizeTimeStamp } from '../humanize_time_stamp'; @@ -45,13 +44,11 @@ export const DataStreamTable: React.FunctionComponent = ({ }), truncateText: true, sortable: true, - render: (name: DataStream['name'], item: DataStream) => { + render: (name: DataStream['name']) => { return ( {name} @@ -108,12 +105,7 @@ export const DataStreamTable: React.FunctionComponent = ({ render: (indices: DataStream['indices'], dataStream) => ( {indices.length} diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js index b4e003b66707..7b09f2009111 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_table/index_table.js @@ -35,9 +35,9 @@ import { } from '@elastic/eui'; import { UIM_SHOW_DETAILS_CLICK } from '../../../../../../common/constants'; -import { reactRouterNavigate } from '../../../../../shared_imports'; +import { reactRouterNavigate, attemptToURIDecode } from '../../../../../shared_imports'; import { REFRESH_RATE_INDEX_LIST } from '../../../../constants'; -import { encodePathForReactRouter } from '../../../../services/routing'; +import { getDataStreamDetailsLink } from '../../../../services/routing'; import { documentationService } from '../../../../services/documentation'; import { AppContextConsumer } from '../../../../app_context'; import { renderBadges } from '../../../../lib/render_badges'; @@ -107,7 +107,7 @@ export class IndexTable extends Component { const { location, filterChanged } = this.props; const { filter } = qs.parse((location && location.search) || ''); if (filter) { - const decodedFilter = decodeURIComponent(filter); + const decodedFilter = attemptToURIDecode(filter); try { const filter = EuiSearchBar.Query.parse(decodedFilter); @@ -279,7 +279,7 @@ export class IndexTable extends Component { diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_table/template_table.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_table/template_table.tsx index 7ec6f1f94a2a..29b841f3bdc7 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_table/template_table.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_table/template_table.tsx @@ -13,7 +13,7 @@ import { UseRequestResponse, reactRouterNavigate } from '../../../../../../share import { TemplateListItem } from '../../../../../../../common'; import { UIM_TEMPLATE_SHOW_DETAILS_CLICK } from '../../../../../../../common/constants'; import { TemplateDeleteModal } from '../../../../../components'; -import { encodePathForReactRouter } from '../../../../../services/routing'; +import { getTemplateDetailsLink } from '../../../../../services/routing'; import { useServices } from '../../../../../app_context'; import { TemplateContentIndicator } from '../../../../../components/shared'; import { TemplateTypeIndicator } from '../../components'; @@ -53,10 +53,7 @@ export const LegacyTemplateTable: React.FunctionComponent = ({ uiMetricService.trackMetric('click', UIM_TEMPLATE_SHOW_DETAILS_CLICK) )} data-test-subj="templateDetailsLink" diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/template_details_content.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/template_details_content.tsx index ada57b559154..1b1b9ad013c3 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/template_details_content.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/template_details_content.tsx @@ -34,7 +34,6 @@ import { import { UseRequestResponse } from '../../../../../shared_imports'; import { TemplateDeleteModal, SectionLoading, SectionError, Error } from '../../../../components'; import { useLoadIndexTemplate } from '../../../../services/api'; -import { decodePathFromReactRouter } from '../../../../services/routing'; import { useServices } from '../../../../app_context'; import { TabAliases, TabMappings, TabSettings } from '../../../../components/shared'; import { TemplateTypeIndicator } from '../components'; @@ -103,11 +102,7 @@ export const TemplateDetailsContent = ({ reload, }: Props) => { const { uiMetricService } = useServices(); - const decodedTemplateName = decodePathFromReactRouter(templateName); - const { error, data: templateDetails, isLoading } = useLoadIndexTemplate( - decodedTemplateName, - isLegacy - ); + const { error, data: templateDetails, isLoading } = useLoadIndexTemplate(templateName, isLegacy); const isCloudManaged = templateDetails?._kbnMeta.type === 'cloudManaged'; const [templateToDelete, setTemplateToDelete] = useState< Array<{ name: string; isLegacy?: boolean }> @@ -120,7 +115,7 @@ export const TemplateDetailsContent = ({

- {decodedTemplateName} + {templateName} {templateDetails && ( <>   @@ -302,8 +297,7 @@ export const TemplateDetailsContent = ({ defaultMessage: 'Delete', }), icon: 'trash', - onClick: () => - setTemplateToDelete([{ name: decodedTemplateName, isLegacy }]), + onClick: () => setTemplateToDelete([{ name: templateName, isLegacy }]), disabled: isCloudManaged, }, ], diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx index c711f457123f..f3e82223c30e 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx @@ -36,6 +36,7 @@ import { TemplateTable } from './template_table'; import { TemplateDetails } from './template_details'; import { LegacyTemplateTable } from './legacy_templates/template_table'; import { FilterListButton, Filters } from './components'; +import { attemptToURIDecode } from '../../../../shared_imports'; type FilterName = 'managed' | 'cloudManaged' | 'system'; interface MatchParams { @@ -100,7 +101,7 @@ export const TemplateList: React.FunctionComponent = ({ return ( <> uiMetricService.trackMetric('click', UIM_TEMPLATE_SHOW_DETAILS_CLICK) + {...reactRouterNavigate(history, getTemplateDetailsLink(name), () => + uiMetricService.trackMetric('click', UIM_TEMPLATE_SHOW_DETAILS_CLICK) )} data-test-subj="templateDetailsLink" > diff --git a/x-pack/plugins/index_management/public/application/sections/template_clone/template_clone.tsx b/x-pack/plugins/index_management/public/application/sections/template_clone/template_clone.tsx index 2aaecbd64ee2..5bb355d90478 100644 --- a/x-pack/plugins/index_management/public/application/sections/template_clone/template_clone.tsx +++ b/x-pack/plugins/index_management/public/application/sections/template_clone/template_clone.tsx @@ -11,9 +11,10 @@ import { EuiPageBody, EuiPageContent, EuiTitle } from '@elastic/eui'; import { TemplateDeserialized } from '../../../../common'; import { TemplateForm, SectionLoading, SectionError, Error } from '../../components'; import { breadcrumbService } from '../../services/breadcrumbs'; -import { decodePathFromReactRouter, getTemplateDetailsLink } from '../../services/routing'; +import { getTemplateDetailsLink } from '../../services/routing'; import { saveTemplate, useLoadIndexTemplate } from '../../services/api'; import { getIsLegacyFromQueryParams } from '../../lib/index_templates'; +import { attemptToURIDecode } from '../../../shared_imports'; interface MatchParams { name: string; @@ -26,7 +27,7 @@ export const TemplateClone: React.FunctionComponent { - const decodedTemplateName = decodePathFromReactRouter(name); + const decodedTemplateName = attemptToURIDecode(name); const isLegacy = getIsLegacyFromQueryParams(location); const [isSaving, setIsSaving] = useState(false); diff --git a/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx b/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx index 6bdcd03fa5ca..3e62f7f880f7 100644 --- a/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx +++ b/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx @@ -11,9 +11,10 @@ import { EuiPageBody, EuiPageContent, EuiTitle, EuiSpacer, EuiCallOut } from '@e import { TemplateDeserialized } from '../../../../common'; import { breadcrumbService } from '../../services/breadcrumbs'; import { useLoadIndexTemplate, updateTemplate } from '../../services/api'; -import { decodePathFromReactRouter, getTemplateDetailsLink } from '../../services/routing'; +import { getTemplateDetailsLink } from '../../services/routing'; import { SectionLoading, SectionError, TemplateForm, Error } from '../../components'; import { getIsLegacyFromQueryParams } from '../../lib/index_templates'; +import { attemptToURIDecode } from '../../../shared_imports'; interface MatchParams { name: string; @@ -26,7 +27,7 @@ export const TemplateEdit: React.FunctionComponent { - const decodedTemplateName = decodePathFromReactRouter(name); + const decodedTemplateName = attemptToURIDecode(name); const isLegacy = getIsLegacyFromQueryParams(location); const [isSaving, setIsSaving] = useState(false); @@ -51,7 +52,7 @@ export const TemplateEdit: React.FunctionComponent { diff --git a/x-pack/plugins/index_management/public/application/services/routing.ts b/x-pack/plugins/index_management/public/application/services/routing.ts index 68bf06409e6a..d12198d6b17a 100644 --- a/x-pack/plugins/index_management/public/application/services/routing.ts +++ b/x-pack/plugins/index_management/public/application/services/routing.ts @@ -6,9 +6,8 @@ export const getTemplateListLink = () => `/templates`; -export const getTemplateDetailsLink = (name: string, isLegacy?: boolean, withHash = false) => { - const baseUrl = `/templates/${encodePathForReactRouter(name)}`; - let url = withHash ? `#${baseUrl}` : baseUrl; +export const getTemplateDetailsLink = (name: string, isLegacy?: boolean) => { + let url = `/templates/${encodeURIComponent(name)}`; if (isLegacy) { url = `${url}?legacy=${isLegacy}`; } @@ -16,7 +15,7 @@ export const getTemplateDetailsLink = (name: string, isLegacy?: boolean, withHas }; export const getTemplateEditLink = (name: string, isLegacy?: boolean) => { - let url = `/edit_template/${encodePathForReactRouter(name)}`; + let url = `/edit_template/${encodeURIComponent(name)}`; if (isLegacy) { url = `${url}?legacy=true`; } @@ -24,7 +23,7 @@ export const getTemplateEditLink = (name: string, isLegacy?: boolean) => { }; export const getTemplateCloneLink = (name: string, isLegacy?: boolean) => { - let url = `/clone_template/${encodePathForReactRouter(name)}`; + let url = `/clone_template/${encodeURIComponent(name)}`; if (isLegacy) { url = `${url}?legacy=true`; } @@ -32,9 +31,7 @@ export const getTemplateCloneLink = (name: string, isLegacy?: boolean) => { }; export const getILMPolicyPath = (policyName: string) => { - return encodeURI( - `/data/index_lifecycle_management/policies/edit/${encodeURIComponent(policyName)}` - ); + return `/data/index_lifecycle_management/policies/edit/${encodeURIComponent(policyName)}`; }; export const getIndexListUri = (filter?: string, includeHiddenIndices?: boolean) => { @@ -53,18 +50,6 @@ export const getIndexListUri = (filter?: string, includeHiddenIndices?: boolean) return '/indices'; }; -export const decodePathFromReactRouter = (pathname: string): string => { - let decodedPath; - try { - decodedPath = decodeURI(pathname); - decodedPath = decodeURIComponent(decodedPath); - } catch (_error) { - decodedPath = decodeURIComponent(pathname); - } - return decodeURIComponent(decodedPath); +export const getDataStreamDetailsLink = (name: string) => { + return encodeURI(`/data_streams/${encodeURIComponent(name)}`); }; - -// Need to add some additonal encoding/decoding logic to work with React Router -// For background, see: https://github.com/ReactTraining/history/issues/505 -export const encodePathForReactRouter = (pathname: string): string => - encodeURIComponent(encodeURIComponent(pathname)); diff --git a/x-pack/plugins/index_management/public/services/extensions_service.mock.ts b/x-pack/plugins/index_management/public/services/extensions_service.mock.ts index 3075a114eedd..6cf533d67662 100644 --- a/x-pack/plugins/index_management/public/services/extensions_service.mock.ts +++ b/x-pack/plugins/index_management/public/services/extensions_service.mock.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ExtensionsService, ExtensionsSetup } from './extensions_service'; export type ExtensionsSetupMock = jest.Mocked; diff --git a/x-pack/plugins/index_management/public/shared_imports.ts b/x-pack/plugins/index_management/public/shared_imports.ts index acb3eb512e2c..360d3ba473db 100644 --- a/x-pack/plugins/index_management/public/shared_imports.ts +++ b/x-pack/plugins/index_management/public/shared_imports.ts @@ -14,6 +14,7 @@ export { Forms, extractQueryParams, GlobalFlyout, + attemptToURIDecode, } from '../../../../src/plugins/es_ui_shared/public'; export { diff --git a/x-pack/plugins/index_management/server/routes/api/data_streams/register_get_route.ts b/x-pack/plugins/index_management/server/routes/api/data_streams/register_get_route.ts index 34edcb6fb747..fa93d9bd0c56 100644 --- a/x-pack/plugins/index_management/server/routes/api/data_streams/register_get_route.ts +++ b/x-pack/plugins/index_management/server/routes/api/data_streams/register_get_route.ts @@ -83,15 +83,16 @@ export function registerGetOneRoute({ router, license, lib: { isEsError } }: Rou license.guardApiRoute(async (ctx, req, res) => { const { name } = req.params as TypeOf; const { callAsCurrentUser } = ctx.dataManagement!.client; - try { const [ { data_streams: dataStream }, { data_streams: dataStreamsStats }, ] = await Promise.all([ - callAsCurrentUser('dataManagement.getDataStream', { name }), + callAsCurrentUser('dataManagement.getDataStream', { + name, + }), ctx.core.elasticsearch.legacy.client.callAsCurrentUser('transport.request', { - path: `/_data_stream/${name}/_stats`, + path: `/_data_stream/${encodeURIComponent(name)}/_stats`, method: 'GET', query: { human: true, diff --git a/x-pack/plugins/infra/common/http_api/log_entries/entries.ts b/x-pack/plugins/infra/common/http_api/log_entries/entries.ts index 5014aeb52a3f..d38b4690fed7 100644 --- a/x-pack/plugins/infra/common/http_api/log_entries/entries.ts +++ b/x-pack/plugins/infra/common/http_api/log_entries/entries.ts @@ -5,6 +5,7 @@ */ import * as rt from 'io-ts'; +import { jsonArrayRT } from '../../typed_json'; import { logEntriesCursorRT } from './common'; export const LOG_ENTRIES_PATH = '/api/log_entries/entries'; @@ -54,7 +55,7 @@ export const logMessageConstantPartRT = rt.type({ }); export const logMessageFieldPartRT = rt.type({ field: rt.string, - value: rt.unknown, + value: jsonArrayRT, highlights: rt.array(rt.string), }); @@ -64,7 +65,7 @@ export const logTimestampColumnRT = rt.type({ columnId: rt.string, timestamp: rt export const logFieldColumnRT = rt.type({ columnId: rt.string, field: rt.string, - value: rt.unknown, + value: jsonArrayRT, highlights: rt.array(rt.string), }); export const logMessageColumnRT = rt.type({ diff --git a/x-pack/plugins/infra/common/http_api/log_entries/item.ts b/x-pack/plugins/infra/common/http_api/log_entries/item.ts index 02335d68402c..5f9457b8228a 100644 --- a/x-pack/plugins/infra/common/http_api/log_entries/item.ts +++ b/x-pack/plugins/infra/common/http_api/log_entries/item.ts @@ -16,7 +16,7 @@ export const logEntriesItemRequestRT = rt.type({ export type LogEntriesItemRequest = rt.TypeOf; -const logEntriesItemFieldRT = rt.type({ field: rt.string, value: rt.string }); +const logEntriesItemFieldRT = rt.type({ field: rt.string, value: rt.array(rt.string) }); const logEntriesItemRT = rt.type({ id: rt.string, index: rt.string, diff --git a/x-pack/plugins/infra/common/typed_json.ts b/x-pack/plugins/infra/common/typed_json.ts index 98b5456fe44b..0ff9e42942ef 100644 --- a/x-pack/plugins/infra/common/typed_json.ts +++ b/x-pack/plugins/infra/common/typed_json.ts @@ -4,11 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ -export type JsonValue = null | boolean | number | string | JsonObject | JsonArray; +import * as rt from 'io-ts'; +import { JsonArray, JsonObject, JsonValue } from '../../../../src/plugins/kibana_utils/common'; -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface JsonArray extends Array {} +export const jsonScalarRT = rt.union([rt.null, rt.boolean, rt.number, rt.string]); -export interface JsonObject { - [key: string]: JsonValue; -} +export const jsonValueRT: rt.Type = rt.recursion('JsonValue', () => + rt.union([jsonScalarRT, jsonArrayRT, jsonObjectRT]) +); + +export const jsonArrayRT: rt.Type = rt.recursion('JsonArray', () => + rt.array(jsonValueRT) +); + +export const jsonObjectRT: rt.Type = rt.recursion('JsonObject', () => + rt.record(rt.string, jsonValueRT) +); + +export { JsonValue, JsonArray, JsonObject }; diff --git a/x-pack/plugins/infra/public/components/logging/log_entry_flyout/log_entry_actions_menu.test.tsx b/x-pack/plugins/infra/public/components/logging/log_entry_flyout/log_entry_actions_menu.test.tsx index b4fa6b8800fb..77154474077c 100644 --- a/x-pack/plugins/infra/public/components/logging/log_entry_flyout/log_entry_actions_menu.test.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_entry_flyout/log_entry_actions_menu.test.tsx @@ -29,7 +29,7 @@ describe('LogEntryActionsMenu component', () => { { { { { { { .filter(({ field, value }) => value != null && UPTIME_FIELDS.includes(field)) .reduce((acc, fieldItem) => { const { field, value } = fieldItem; - try { - const parsedValue = decodeOrThrow(rt.array(rt.string))(JSON.parse(value)); - return acc.concat(parsedValue.map((val) => `${field}:${val}`)); - } catch (e) { - return acc.concat([`${field}:${value}`]); - } + return acc.concat(value.map((val) => `${field}:${val}`)); }, []); if (searchExpressions.length === 0) { @@ -119,7 +112,7 @@ const getUptimeLink = (logItem: LogEntriesItem): LinkDescriptor | undefined => { const getAPMLink = (logItem: LogEntriesItem): LinkDescriptor | undefined => { const traceIdEntry = logItem.fields.find( - ({ field, value }) => value != null && field === 'trace.id' + ({ field, value }) => value[0] != null && field === 'trace.id' ); if (!traceIdEntry) { @@ -127,7 +120,7 @@ const getAPMLink = (logItem: LogEntriesItem): LinkDescriptor | undefined => { } const timestampField = logItem.fields.find(({ field }) => field === '@timestamp'); - const timestamp = timestampField ? timestampField.value : null; + const timestamp = timestampField ? timestampField.value[0] : null; const { rangeFrom, rangeTo } = timestamp ? (() => { const from = new Date(timestamp); @@ -142,6 +135,6 @@ const getAPMLink = (logItem: LogEntriesItem): LinkDescriptor | undefined => { return { app: 'apm', - hash: getTraceUrl({ traceId: traceIdEntry.value, rangeFrom, rangeTo }), + hash: getTraceUrl({ traceId: traceIdEntry.value[0], rangeFrom, rangeTo }), }; }; diff --git a/x-pack/plugins/infra/public/components/logging/log_entry_flyout/log_entry_flyout.tsx b/x-pack/plugins/infra/public/components/logging/log_entry_flyout/log_entry_flyout.tsx index 76ffada510e5..b07d8c9dce23 100644 --- a/x-pack/plugins/infra/public/components/logging/log_entry_flyout/log_entry_flyout.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_entry_flyout/log_entry_flyout.tsx @@ -94,7 +94,7 @@ export const LogEntryFlyout = ({ onClick={createFilterHandler(item)} /> - {item.value} + {formatValue(item.value)} ), }, @@ -147,3 +147,7 @@ export const InfraFlyoutLoadingPanel = euiStyled.div` bottom: 0; left: 0; `; + +function formatValue(value: string[]) { + return value.length > 1 ? value.join(', ') : value[0]; +} diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/field_value.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/field_value.tsx new file mode 100644 index 000000000000..7caf34c0cd6b --- /dev/null +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/field_value.tsx @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import stringify from 'json-stable-stringify'; +import React from 'react'; +import { euiStyled } from '../../../../../observability/public'; +import { JsonArray, JsonValue } from '../../../../common/typed_json'; +import { ActiveHighlightMarker, highlightFieldValue, HighlightMarker } from './highlighting'; + +export const FieldValue: React.FC<{ + highlightTerms: string[]; + isActiveHighlight: boolean; + value: JsonArray; +}> = React.memo(({ highlightTerms, isActiveHighlight, value }) => { + if (value.length === 1) { + return ( + <> + {highlightFieldValue( + formatValue(value[0]), + highlightTerms, + isActiveHighlight ? ActiveHighlightMarker : HighlightMarker + )} + + ); + } else if (value.length > 1) { + return ( +
    + {value.map((entry, i) => ( + + {highlightFieldValue( + formatValue(entry), + highlightTerms, + isActiveHighlight ? ActiveHighlightMarker : HighlightMarker + )} + + ))} +
+ ); + } + + return null; +}); + +const formatValue = (value: JsonValue): string => { + if (typeof value === 'string') { + return value; + } + + return stringify(value); +}; + +const CommaSeparatedLi = euiStyled.li` + display: inline; + &:not(:last-child) { + margin-right: 1ex; + &::after { + content: ','; + } + } +`; diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_column.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_column.tsx index 51488f088e75..9b039b7f2f3b 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_column.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_column.tsx @@ -39,7 +39,9 @@ export const LogEntryColumn = euiStyled.div.attrs(() => ({ overflow: hidden; `; -export const LogEntryColumnContent = euiStyled.div` +export const LogEntryColumnContent = euiStyled.div.attrs({ + 'data-test-subj': 'LogEntryColumnContent', +})` flex: 1 0 0%; padding: 2px ${COLUMN_PADDING}px; `; diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.test.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.test.tsx index d6068b6e6099..5813f08497a7 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.test.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.test.tsx @@ -4,85 +4,113 @@ * you may not use this file except in compliance with the Elastic License. */ -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; import React from 'react'; - import { EuiThemeProvider } from '../../../../../observability/public'; +import { LogFieldColumn } from '../../../../common/http_api'; import { LogEntryFieldColumn } from './log_entry_field_column'; -import { LogColumn } from '../../../../common/http_api'; describe('LogEntryFieldColumn', () => { - it('should output a
    when displaying an Array of values', () => { - const column: LogColumn = { + it('renders a single value without a wrapping list', () => { + const column: LogFieldColumn = { + columnId: 'TEST_COLUMN', + field: 'TEST_FIELD', + value: ['a'], + highlights: [], + }; + + const renderResult = render( + , + { wrapper: EuiThemeProvider } + ); + + expect(renderResult.getByTestId('LogEntryColumnContent')).toHaveTextContent(/^a$/); + expect(renderResult.queryByTestId('LogEntryFieldValues')).toBe(null); + }); + + it('renders an array of values as a list', () => { + const column: LogFieldColumn = { columnId: 'TEST_COLUMN', field: 'TEST_FIELD', value: ['a', 'b', 'c'], highlights: [], }; - const component = mount( + const renderResult = render( , - { wrappingComponent: EuiThemeProvider } as any // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/36075 + { wrapper: EuiThemeProvider } ); - expect(component.exists('ul')).toBe(true); - expect( - component.containsAllMatchingElements([ -
  • a
  • , -
  • b
  • , -
  • c
  • , - ]) - ).toBe(true); + expect(renderResult.getByTestId('LogEntryFieldValues')).not.toBeEmptyDOMElement(); + expect(renderResult.getByTestId('LogEntryFieldValue-0')).toHaveTextContent('a'); + expect(renderResult.getByTestId('LogEntryFieldValue-1')).toHaveTextContent('b'); + expect(renderResult.getByTestId('LogEntryFieldValue-2')).toHaveTextContent('c'); }); - it('should output a text representation of a passed complex value', () => { - const column: LogColumn = { + it('renders a text representation of a single complex object', () => { + const column: LogFieldColumn = { columnId: 'TEST_COLUMN', field: 'TEST_FIELD', - value: { - lat: 1, - lon: 2, - }, + value: [ + { + lat: 1, + lon: 2, + }, + ], highlights: [], }; - const component = mount( + const renderResult = render( , - { wrappingComponent: EuiThemeProvider } as any // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/36075 + { wrapper: EuiThemeProvider } ); - expect(component.text()).toEqual('{"lat":1,"lon":2}'); + expect(renderResult.getByTestId('LogEntryColumnContent')).toHaveTextContent( + '{"lat":1,"lon":2}' + ); }); - it('should output just text when passed a non-Array', () => { - const column: LogColumn = { + it('renders text representations of a multiple complex objects', () => { + const column: LogFieldColumn = { columnId: 'TEST_COLUMN', field: 'TEST_FIELD', - value: 'foo', + value: [ + { + lat: 1, + lon: 2, + }, + [3, 4], + ], highlights: [], }; - const component = mount( + const renderResult = render( , - { wrappingComponent: EuiThemeProvider } as any // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/36075 + { wrapper: EuiThemeProvider } ); - expect(component.exists('ul')).toBe(false); - expect(component.text()).toEqual('foo'); + expect(renderResult.getByTestId('LogEntryFieldValues')).not.toBeEmptyDOMElement(); + expect(renderResult.getByTestId('LogEntryFieldValue-0')).toHaveTextContent('{"lat":1,"lon":2}'); + expect(renderResult.getByTestId('LogEntryFieldValue-1')).toHaveTextContent('[3,4]'); }); }); diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx index 4e9611f7a8d2..cdffe3742b53 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_field_column.tsx @@ -4,14 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import stringify from 'json-stable-stringify'; -import React, { useMemo } from 'react'; - +import React from 'react'; import { euiStyled } from '../../../../../observability/public'; +import { LogColumn } from '../../../../common/http_api'; import { isFieldColumn, isHighlightFieldColumn } from '../../../utils/log_entry'; -import { ActiveHighlightMarker, highlightFieldValue, HighlightMarker } from './highlighting'; +import { FieldValue } from './field_value'; import { LogEntryColumnContent } from './log_entry_column'; -import { LogColumn } from '../../../../common/http_api'; import { longWrappedContentStyle, preWrappedContentStyle, @@ -32,44 +30,20 @@ export const LogEntryFieldColumn: React.FunctionComponent { - const value = useMemo(() => { - if (isFieldColumn(columnValue)) { - return columnValue.value; - } + if (isFieldColumn(columnValue)) { + return ( + + + + ); + } else { return null; - }, [columnValue]); - const formattedValue = Array.isArray(value) ? ( -
      - {value.map((entry, i) => ( - - {highlightFieldValue( - entry, - isHighlightFieldColumn(firstHighlight) ? firstHighlight.highlights : [], - isActiveHighlight ? ActiveHighlightMarker : HighlightMarker - )} - - ))} -
    - ) : ( - highlightFieldValue( - typeof value === 'string' ? value : stringify(value), - isHighlightFieldColumn(firstHighlight) ? firstHighlight.highlights : [], - isActiveHighlight ? ActiveHighlightMarker : HighlightMarker - ) - ); - - return {formattedValue}; -}; - -const CommaSeparatedLi = euiStyled.li` - display: inline; - &:not(:last-child) { - margin-right: 1ex; - &::after { - content: ','; - } } -`; +}; interface LogEntryColumnContentProps { wrapMode: WrapMode; diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.test.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.test.tsx new file mode 100644 index 000000000000..b9871cc3b36f --- /dev/null +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.test.tsx @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { render } from '@testing-library/react'; +import React from 'react'; +import { EuiThemeProvider } from '../../../../../observability/public'; +import { LogMessageColumn } from '../../../../common/http_api'; +import { LogEntryMessageColumn } from './log_entry_message_column'; + +describe('LogEntryMessageColumn', () => { + it('renders a single scalar field value without a wrapping list', () => { + const column: LogMessageColumn = { + columnId: 'TEST_COLUMN', + message: [{ field: 'TEST_FIELD', value: ['VALUE'], highlights: [] }], + }; + + const renderResult = render( + , + { wrapper: EuiThemeProvider } + ); + + expect(renderResult.getByTestId('LogEntryColumnContent')).toHaveTextContent(/^VALUE$/); + expect(renderResult.queryByTestId('LogEntryFieldValues')).toBe(null); + }); + + it('renders a single array of scalar field values as a list', () => { + const column: LogMessageColumn = { + columnId: 'TEST_COLUMN', + message: [{ field: 'TEST_FIELD', value: ['VALUE_1', 'VALUE_2'], highlights: [] }], + }; + + const renderResult = render( + , + { wrapper: EuiThemeProvider } + ); + + expect(renderResult.getByTestId('LogEntryFieldValues')).not.toBeEmptyDOMElement(); + expect(renderResult.getByTestId('LogEntryFieldValue-0')).toHaveTextContent('VALUE_1'); + expect(renderResult.getByTestId('LogEntryFieldValue-1')).toHaveTextContent('VALUE_2'); + }); + + it('renders a complex message with an array of complex field values', () => { + const column: LogMessageColumn = { + columnId: 'TEST_COLUMN', + message: [ + { constant: 'CONSTANT_1' }, + { field: 'TEST_FIELD', value: [{ lat: 1, lon: 2 }, 'VALUE_2'], highlights: [] }, + { constant: 'CONSTANT_2' }, + ], + }; + + const renderResult = render( + , + { wrapper: EuiThemeProvider } + ); + + expect(renderResult.getByTestId('LogEntryColumnContent')).toHaveTextContent( + /^CONSTANT_1.*{"lat":1,"lon":2}.*VALUE_2.*CONSTANT_2$/ + ); + expect(renderResult.getByTestId('LogEntryFieldValues')).not.toBeEmptyDOMElement(); + expect(renderResult.getByTestId('LogEntryFieldValue-0')).toHaveTextContent('{"lat":1,"lon":2}'); + expect(renderResult.getByTestId('LogEntryFieldValue-1')).toHaveTextContent('VALUE_2'); + }); +}); diff --git a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.tsx b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.tsx index f83a0a222d3d..b7ff6b1409bd 100644 --- a/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_text_stream/log_entry_message_column.tsx @@ -5,17 +5,16 @@ */ import React, { memo, useMemo } from 'react'; -import stringify from 'json-stable-stringify'; - import { euiStyled } from '../../../../../observability/public'; +import { LogColumn, LogMessagePart } from '../../../../common/http_api'; import { isConstantSegment, isFieldSegment, + isHighlightFieldSegment, isHighlightMessageColumn, isMessageColumn, - isHighlightFieldSegment, } from '../../../utils/log_entry'; -import { ActiveHighlightMarker, highlightFieldValue, HighlightMarker } from './highlighting'; +import { FieldValue } from './field_value'; import { LogEntryColumnContent } from './log_entry_column'; import { longWrappedContentStyle, @@ -23,7 +22,6 @@ import { unwrappedContentStyle, WrapMode, } from './text_styles'; -import { LogColumn, LogMessagePart } from '../../../../common/http_api'; interface LogEntryMessageColumnProps { columnValue: LogColumn; @@ -65,10 +63,10 @@ const formatMessageSegments = ( highlights: LogColumn[], isActiveHighlight: boolean ) => - messageSegments.map((messageSegment, index) => - formatMessageSegment( - messageSegment, - highlights.map((highlight) => { + messageSegments.map((messageSegment, index) => { + if (isFieldSegment(messageSegment)) { + // we only support one highlight for now + const [firstHighlight = []] = highlights.map((highlight) => { if (isHighlightMessageColumn(highlight)) { const segment = highlight.message[index]; if (isHighlightFieldSegment(segment)) { @@ -76,30 +74,19 @@ const formatMessageSegments = ( } } return []; - }), - isActiveHighlight - ) - ); + }); -const formatMessageSegment = ( - messageSegment: LogMessagePart, - [firstHighlight = []]: string[][], // we only support one highlight for now - isActiveHighlight: boolean -): React.ReactNode => { - if (isFieldSegment(messageSegment)) { - const value = - typeof messageSegment.value === 'string' - ? messageSegment.value - : stringify(messageSegment.value); - - return highlightFieldValue( - value, - firstHighlight, - isActiveHighlight ? ActiveHighlightMarker : HighlightMarker - ); - } else if (isConstantSegment(messageSegment)) { - return messageSegment.constant; - } + return ( + + ); + } else if (isConstantSegment(messageSegment)) { + return messageSegment.constant; + } - return 'failed to format message'; -}; + return 'failed to format message'; + }); diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_example_message.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_example_message.tsx index 7bcc05280994..84d7e198636e 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_example_message.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/category_example_message.tsx @@ -86,7 +86,7 @@ export const CategoryExampleMessage: React.FunctionComponent<{ = ({ = ({ columnValue={{ columnId: datasetColumnId, field: 'event.dataset', - value: humanFriendlyDataset, + value: [humanFriendlyDataset], highlights: [], }} highlights={noHighlights} diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/map.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/map.tsx index 6621b110a6df..8023e3bf7da6 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/map.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/map.tsx @@ -45,8 +45,8 @@ export const Map: React.FC = ({ const sortedNodes = sortNodes(options.sort, nodes); const map = nodesToWaffleMap(sortedNodes); return ( - - {({ measureRef, content: { width = 0, height = 0 } }) => { + + {({ measureRef, bounds: { width = 0, height = 0 } }) => { const groupsWithLayout = applyWaffleMapLayout(map, width, height); return ( ['hits']['hits'][0]; export interface SortedSearchHit extends SearchHit { sort: any[]; _source: { - [field: string]: any; + [field: string]: JsonValue; + }; + fields: { + [field: string]: JsonArray; }; } diff --git a/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts index c5b667fb2053..9309ad85a357 100644 --- a/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts @@ -4,18 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -/* eslint-disable @typescript-eslint/no-empty-interface */ - import { timeMilliseconds } from 'd3-time'; +import { fold, map } from 'fp-ts/lib/Either'; +import { constant, identity } from 'fp-ts/lib/function'; +import { pipe } from 'fp-ts/lib/pipeable'; import * as runtimeTypes from 'io-ts'; import { compact, first } from 'lodash'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { map, fold } from 'fp-ts/lib/Either'; -import { identity, constant } from 'fp-ts/lib/function'; import { RequestHandlerContext } from 'src/core/server'; -import { JsonValue } from '../../../../common/typed_json'; +import { JsonArray } from '../../../../common/typed_json'; import { LogEntriesAdapter, + LogItemHit, LogEntriesParams, LogEntryDocument, LogEntryQuery, @@ -28,13 +27,6 @@ import { KibanaFramework } from '../framework/kibana_framework_adapter'; const TIMESTAMP_FORMAT = 'epoch_millis'; -interface LogItemHit { - _index: string; - _id: string; - fields: { [key: string]: [value: unknown] }; - sort: [number, number]; -} - export class InfraKibanaLogEntriesAdapter implements LogEntriesAdapter { constructor(private readonly framework: KibanaFramework) {} @@ -231,13 +223,14 @@ export class InfraKibanaLogEntriesAdapter implements LogEntriesAdapter { function mapHitsToLogEntryDocuments(hits: SortedSearchHit[], fields: string[]): LogEntryDocument[] { return hits.map((hit) => { - const logFields = fields.reduce<{ [fieldName: string]: JsonValue }>( - (flattenedFields, field) => { - if (field in hit.fields) { - flattenedFields[field] = hit.fields[field][0]; - } - return flattenedFields; - }, + const logFields = fields.reduce<{ [fieldName: string]: JsonArray }>( + (flattenedFields, field) => + field in hit.fields + ? { + ...flattenedFields, + [field]: hit.fields[field], + } + : flattenedFields, {} ); @@ -338,8 +331,9 @@ const LogSummaryDateRangeBucketRuntimeType = runtimeTypes.intersection([ }), ]); -export interface LogSummaryDateRangeBucket - extends runtimeTypes.TypeOf {} +export type LogSummaryDateRangeBucket = runtimeTypes.TypeOf< + typeof LogSummaryDateRangeBucketRuntimeType +>; const LogSummaryResponseRuntimeType = runtimeTypes.type({ aggregations: runtimeTypes.type({ @@ -349,5 +343,4 @@ const LogSummaryResponseRuntimeType = runtimeTypes.type({ }), }); -export interface LogSummaryResponse - extends runtimeTypes.TypeOf {} +export type LogSummaryResponse = runtimeTypes.TypeOf; diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_apache2.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_apache2.test.ts index 367ae6a0cae8..e7e381dc7f8f 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_apache2.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_apache2.test.ts @@ -13,251 +13,290 @@ describe('Filebeat Rules', () => { describe('in ECS format', () => { test('Apache2 Access', () => { const flattenedDocument = { - '@timestamp': '2016-12-26T16:22:13.000Z', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'apache.access', - 'event.module': 'apache', - 'fileset.name': 'access', - 'http.request.method': 'GET', - 'http.request.referrer': '-', - 'http.response.body.bytes': 499, - 'http.response.status_code': 404, - 'http.version': '1.1', - 'input.type': 'log', - 'log.offset': 73, - 'service.type': 'apache', - 'source.address': '192.168.33.1', - 'source.ip': '192.168.33.1', - 'url.original': '/hello', - 'user.name': '-', - 'user_agent.device': 'Other', - 'user_agent.major': '50', - 'user_agent.minor': '0', - 'user_agent.name': 'Firefox', - 'user_agent.original': + '@timestamp': ['2016-12-26T16:22:13.000Z'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['apache.access'], + 'event.module': ['apache'], + 'fileset.name': ['access'], + 'http.request.method': ['GET'], + 'http.request.referrer': ['-'], + 'http.response.body.bytes': [499], + 'http.response.status_code': [404], + 'http.version': ['1.1'], + 'input.type': ['log'], + 'log.offset': [73], + 'service.type': ['apache'], + 'source.address': ['192.168.33.1'], + 'source.ip': ['192.168.33.1'], + 'url.original': ['/hello'], + 'user.name': ['-'], + 'user_agent.device': ['Other'], + 'user_agent.major': ['50'], + 'user_agent.minor': ['0'], + 'user_agent.name': ['Firefox'], + 'user_agent.original': [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0', - 'user_agent.os.full_name': 'Mac OS X 10.12', - 'user_agent.os.major': '10', - 'user_agent.os.minor': '12', - 'user_agent.os.name': 'Mac OS X', + ], + 'user_agent.os.full_name': ['Mac OS X 10.12'], + 'user_agent.os.major': ['10'], + 'user_agent.os.minor': ['12'], + 'user_agent.os.name': ['Mac OS X'], }; const highlights = { 'http.request.method': ['GET'], }; expect(format(flattenedDocument, highlights)).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[", - }, - Object { - "field": "event.module", - "highlights": Array [], - "value": "apache", - }, - Object { - "constant": "][access] ", - }, - Object { - "field": "source.ip", - "highlights": Array [], - "value": "192.168.33.1", - }, - Object { - "constant": " ", - }, - Object { - "field": "user.name", - "highlights": Array [], - "value": "-", - }, - Object { - "constant": " \\"", - }, - Object { - "field": "http.request.method", - "highlights": Array [ - "GET", - ], - "value": "GET", - }, - Object { - "constant": " ", - }, - Object { - "field": "url.original", - "highlights": Array [], - "value": "/hello", - }, - Object { - "constant": " HTTP/", - }, - Object { - "field": "http.version", - "highlights": Array [], - "value": "1.1", - }, - Object { - "constant": "\\" ", - }, - Object { - "field": "http.response.status_code", - "highlights": Array [], - "value": "404", - }, - Object { - "constant": " ", - }, - Object { - "field": "http.response.body.bytes", - "highlights": Array [], - "value": "499", - }, -] -`); + Array [ + Object { + "constant": "[", + }, + Object { + "field": "event.module", + "highlights": Array [], + "value": Array [ + "apache", + ], + }, + Object { + "constant": "][access] ", + }, + Object { + "field": "source.ip", + "highlights": Array [], + "value": Array [ + "192.168.33.1", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "user.name", + "highlights": Array [], + "value": Array [ + "-", + ], + }, + Object { + "constant": " \\"", + }, + Object { + "field": "http.request.method", + "highlights": Array [ + "GET", + ], + "value": Array [ + "GET", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "url.original", + "highlights": Array [], + "value": Array [ + "/hello", + ], + }, + Object { + "constant": " HTTP/", + }, + Object { + "field": "http.version", + "highlights": Array [], + "value": Array [ + "1.1", + ], + }, + Object { + "constant": "\\" ", + }, + Object { + "field": "http.response.status_code", + "highlights": Array [], + "value": Array [ + 404, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "http.response.body.bytes", + "highlights": Array [], + "value": Array [ + 499, + ], + }, + ] + `); }); test('Apache2 Error', () => { const flattenedDocument = { - '@timestamp': '2016-12-26T16:22:08.000Z', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'apache.error', - 'event.module': 'apache', - 'fileset.name': 'error', - 'input.type': 'log', - 'log.level': 'error', - 'log.offset': 0, - message: 'File does not exist: /var/www/favicon.ico', - 'service.type': 'apache', - 'source.address': '192.168.33.1', - 'source.ip': '192.168.33.1', + '@timestamp': ['2016-12-26T16:22:08.000Z'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['apache.error'], + 'event.module': ['apache'], + 'fileset.name': ['error'], + 'input.type': ['log'], + 'log.level': ['error'], + 'log.offset': [0], + message: ['File does not exist: /var/www/favicon.ico'], + 'service.type': ['apache'], + 'source.address': ['192.168.33.1'], + 'source.ip': ['192.168.33.1'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[apache][", - }, - Object { - "field": "log.level", - "highlights": Array [], - "value": "error", - }, - Object { - "constant": "] ", - }, - Object { - "field": "message", - "highlights": Array [], - "value": "File does not exist: /var/www/favicon.ico", - }, -] -`); + Array [ + Object { + "constant": "[apache][", + }, + Object { + "field": "log.level", + "highlights": Array [], + "value": Array [ + "error", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "message", + "highlights": Array [], + "value": Array [ + "File does not exist: /var/www/favicon.ico", + ], + }, + ] + `); }); }); describe('in pre-ECS format', () => { test('Apache2 Access', () => { const flattenedDocument = { - 'apache2.access': true, - 'apache2.access.remote_ip': '192.168.1.42', - 'apache2.access.user_name': 'admin', - 'apache2.access.method': 'GET', - 'apache2.access.url': '/faqs', - 'apache2.access.http_version': '1.1', - 'apache2.access.response_code': '200', - 'apache2.access.body_sent.bytes': 1024, + 'apache2.access.remote_ip': ['192.168.1.42'], + 'apache2.access.user_name': ['admin'], + 'apache2.access.method': ['GET'], + 'apache2.access.url': ['/faqs'], + 'apache2.access.http_version': ['1.1'], + 'apache2.access.response_code': ['200'], + 'apache2.access.body_sent.bytes': [1024], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[apache][access] ", - }, - Object { - "field": "apache2.access.remote_ip", - "highlights": Array [], - "value": "192.168.1.42", - }, - Object { - "constant": " ", - }, - Object { - "field": "apache2.access.user_name", - "highlights": Array [], - "value": "admin", - }, - Object { - "constant": " \\"", - }, - Object { - "field": "apache2.access.method", - "highlights": Array [], - "value": "GET", - }, - Object { - "constant": " ", - }, - Object { - "field": "apache2.access.url", - "highlights": Array [], - "value": "/faqs", - }, - Object { - "constant": " HTTP/", - }, - Object { - "field": "apache2.access.http_version", - "highlights": Array [], - "value": "1.1", - }, - Object { - "constant": "\\" ", - }, - Object { - "field": "apache2.access.response_code", - "highlights": Array [], - "value": "200", - }, - Object { - "constant": " ", - }, - Object { - "field": "apache2.access.body_sent.bytes", - "highlights": Array [], - "value": "1024", - }, -] -`); + Array [ + Object { + "constant": "[apache][access] ", + }, + Object { + "field": "apache2.access.remote_ip", + "highlights": Array [], + "value": Array [ + "192.168.1.42", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "apache2.access.user_name", + "highlights": Array [], + "value": Array [ + "admin", + ], + }, + Object { + "constant": " \\"", + }, + Object { + "field": "apache2.access.method", + "highlights": Array [], + "value": Array [ + "GET", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "apache2.access.url", + "highlights": Array [], + "value": Array [ + "/faqs", + ], + }, + Object { + "constant": " HTTP/", + }, + Object { + "field": "apache2.access.http_version", + "highlights": Array [], + "value": Array [ + "1.1", + ], + }, + Object { + "constant": "\\" ", + }, + Object { + "field": "apache2.access.response_code", + "highlights": Array [], + "value": Array [ + "200", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "apache2.access.body_sent.bytes", + "highlights": Array [], + "value": Array [ + 1024, + ], + }, + ] + `); }); test('Apache2 Error', () => { const flattenedDocument = { - 'apache2.error.message': + 'apache2.error.message': [ 'AH00489: Apache/2.4.18 (Ubuntu) configured -- resuming normal operations', - 'apache2.error.level': 'notice', + ], + 'apache2.error.level': ['notice'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[apache][", - }, - Object { - "field": "apache2.error.level", - "highlights": Array [], - "value": "notice", - }, - Object { - "constant": "] ", - }, - Object { - "field": "apache2.error.message", - "highlights": Array [], - "value": "AH00489: Apache/2.4.18 (Ubuntu) configured -- resuming normal operations", - }, -] -`); + Array [ + Object { + "constant": "[apache][", + }, + Object { + "field": "apache2.error.level", + "highlights": Array [], + "value": Array [ + "notice", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "apache2.error.message", + "highlights": Array [], + "value": Array [ + "AH00489: Apache/2.4.18 (Ubuntu) configured -- resuming normal operations", + ], + }, + ] + `); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_apache2.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_apache2.ts index fe7ebffe9132..3698753ef42e 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_apache2.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_apache2.ts @@ -8,7 +8,7 @@ export const filebeatApache2Rules = [ { // pre-ECS when: { - exists: ['apache2.access'], + existsPrefix: ['apache2.access'], }, format: [ { diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_auditd.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_auditd.test.ts index aa490c595d9f..4481ff434802 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_auditd.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_auditd.test.ts @@ -13,345 +13,605 @@ describe('Filebeat Rules', () => { describe('in ECS format', () => { test('auditd log with outcome', () => { const flattenedDocument = { - '@timestamp': '2016-12-07T02:17:21.515Z', - 'auditd.log': { - addr: '96.241.146.97', - cipher: 'chacha20-poly1305@openssh.com', - direction: 'from-server', - ksize: '512', - laddr: '10.142.0.2', - lport: '22', - pfs: 'curve25519-sha256@libssh.org', - rport: '63927', - sequence: 406, - ses: '4294967295', - spid: '1299', - subj: 'system_u:system_r:sshd_t:s0-s0:c0.c1023', - }, - 'ecs.version': '1.0.0-beta2', - 'event.action': 'crypto_session', - 'event.dataset': 'auditd.log', - 'event.module': 'auditd', - 'event.outcome': 'success', - 'fileset.name': 'log', - 'input.type': 'log', - 'log.offset': 783, - message: 'op=start', - process: { executable: '/usr/sbin/sshd', pid: 1298 }, - 'service.type': 'auditd', - user: { 'audit.id': '4294967295', id: '0', 'saved.id': '74' }, + '@timestamp': ['2016-12-07T02:17:21.515Z'], + 'auditd.log.addr': ['96.241.146.97'], + 'auditd.log.cipher': ['chacha20-poly1305@openssh.com'], + 'auditd.log.direction': ['from-server'], + 'auditd.log.ksize': ['512'], + 'auditd.log.laddr': ['10.142.0.2'], + 'auditd.log.lport': ['22'], + 'auditd.log.pfs': ['curve25519-sha256@libssh.org'], + 'auditd.log.rport': ['63927'], + 'auditd.log.sequence': [406], + 'auditd.log.ses': ['4294967295'], + 'auditd.log.spid': ['1299'], + 'auditd.log.subj': ['system_u:system_r:sshd_t:s0-s0:c0.c1023'], + 'ecs.version': ['1.0.0-beta2'], + 'event.action': ['crypto_session'], + 'event.dataset': ['auditd.log'], + 'event.module': ['auditd'], + 'event.outcome': ['success'], + 'fileset.name': ['log'], + 'input.type': ['log'], + 'log.offset': [783], + message: ['op=start'], + 'process.executable': ['/usr/sbin/sshd'], + 'process.pid': [1298], + 'service.type': ['auditd'], + 'user.audit.id': ['4294967295'], + 'user.id': ['0'], + 'user.saved.id': ['74'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[AuditD][", - }, - Object { - "field": "event.action", - "highlights": Array [], - "value": "crypto_session", - }, - Object { - "constant": "]", - }, - Object { - "constant": " ", - }, - Object { - "field": "event.outcome", - "highlights": Array [], - "value": "success", - }, - Object { - "constant": " ", - }, - Object { - "constant": "user", - }, - Object { - "constant": "=", - }, - Object { - "field": "user", - "highlights": Array [], - "value": "{\\"audit.id\\":\\"4294967295\\",\\"id\\":\\"0\\",\\"saved.id\\":\\"74\\"}", - }, - Object { - "constant": " ", - }, - Object { - "constant": "process", - }, - Object { - "constant": "=", - }, - Object { - "field": "process", - "highlights": Array [], - "value": "{\\"executable\\":\\"/usr/sbin/sshd\\",\\"pid\\":1298}", - }, - Object { - "constant": " ", - }, - Object { - "field": "auditd.log", - "highlights": Array [], - "value": "{\\"addr\\":\\"96.241.146.97\\",\\"cipher\\":\\"chacha20-poly1305@openssh.com\\",\\"direction\\":\\"from-server\\",\\"ksize\\":\\"512\\",\\"laddr\\":\\"10.142.0.2\\",\\"lport\\":\\"22\\",\\"pfs\\":\\"curve25519-sha256@libssh.org\\",\\"rport\\":\\"63927\\",\\"sequence\\":406,\\"ses\\":\\"4294967295\\",\\"spid\\":\\"1299\\",\\"subj\\":\\"system_u:system_r:sshd_t:s0-s0:c0.c1023\\"}", - }, - Object { - "constant": " ", - }, - Object { - "field": "message", - "highlights": Array [], - "value": "op=start", - }, -] -`); + Array [ + Object { + "constant": "[AuditD][", + }, + Object { + "field": "event.action", + "highlights": Array [], + "value": Array [ + "crypto_session", + ], + }, + Object { + "constant": "]", + }, + Object { + "constant": " ", + }, + Object { + "field": "event.outcome", + "highlights": Array [], + "value": Array [ + "success", + ], + }, + Object { + "constant": " ", + }, + Object { + "constant": "user", + }, + Object { + "constant": "=", + }, + Object { + "field": "user.audit.id", + "highlights": Array [], + "value": Array [ + "4294967295", + ], + }, + Object { + "field": "user.id", + "highlights": Array [], + "value": Array [ + "0", + ], + }, + Object { + "field": "user.saved.id", + "highlights": Array [], + "value": Array [ + "74", + ], + }, + Object { + "constant": " ", + }, + Object { + "constant": "process", + }, + Object { + "constant": "=", + }, + Object { + "field": "process.executable", + "highlights": Array [], + "value": Array [ + "/usr/sbin/sshd", + ], + }, + Object { + "field": "process.pid", + "highlights": Array [], + "value": Array [ + 1298, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "auditd.log.addr", + "highlights": Array [], + "value": Array [ + "96.241.146.97", + ], + }, + Object { + "field": "auditd.log.cipher", + "highlights": Array [], + "value": Array [ + "chacha20-poly1305@openssh.com", + ], + }, + Object { + "field": "auditd.log.direction", + "highlights": Array [], + "value": Array [ + "from-server", + ], + }, + Object { + "field": "auditd.log.ksize", + "highlights": Array [], + "value": Array [ + "512", + ], + }, + Object { + "field": "auditd.log.laddr", + "highlights": Array [], + "value": Array [ + "10.142.0.2", + ], + }, + Object { + "field": "auditd.log.lport", + "highlights": Array [], + "value": Array [ + "22", + ], + }, + Object { + "field": "auditd.log.pfs", + "highlights": Array [], + "value": Array [ + "curve25519-sha256@libssh.org", + ], + }, + Object { + "field": "auditd.log.rport", + "highlights": Array [], + "value": Array [ + "63927", + ], + }, + Object { + "field": "auditd.log.sequence", + "highlights": Array [], + "value": Array [ + 406, + ], + }, + Object { + "field": "auditd.log.ses", + "highlights": Array [], + "value": Array [ + "4294967295", + ], + }, + Object { + "field": "auditd.log.spid", + "highlights": Array [], + "value": Array [ + "1299", + ], + }, + Object { + "field": "auditd.log.subj", + "highlights": Array [], + "value": Array [ + "system_u:system_r:sshd_t:s0-s0:c0.c1023", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "message", + "highlights": Array [], + "value": Array [ + "op=start", + ], + }, + ] + `); }); test('auditd log without outcome', () => { const flattenedDocument = { - '@timestamp': '2017-01-31T20:17:14.891Z', - 'auditd.log': { - a0: '9', - a1: '7f564b2672a0', - a2: 'b8', - a3: '0', - exit: '184', - items: '0', - sequence: 18877199, - ses: '4294967295', - success: 'yes', - syscall: '44', - tty: '(none)', - }, - 'ecs.version': '1.0.0-beta2', - 'event.action': 'syscall', - 'event.dataset': 'auditd.log', - 'event.module': 'auditd', - 'fileset.name': 'log', - 'host.architecture': 'x86_64', - 'input.type': 'log', - 'log.offset': 174, - process: { - executable: '/usr/libexec/strongswan/charon (deleted)', - name: 'charon', - pid: 1281, - ppid: 1240, - }, - 'service.type': 'auditd', - user: { - 'audit.id': '4294967295', - 'effective.group.id': '0', - 'effective.id': '0', - 'filesystem.group.id': '0', - 'filesystem.id': '0', - 'group.id': '0', - id: '0', - 'saved.group.id': '0', - 'saved.id': '0', - }, + '@timestamp': ['2017-01-31T20:17:14.891Z'], + 'auditd.log.a0': ['9'], + 'auditd.log.a1': ['7f564b2672a0'], + 'auditd.log.a2': ['b8'], + 'auditd.log.a3': ['0'], + 'auditd.log.exit': ['184'], + 'auditd.log.items': ['0'], + 'auditd.log.sequence': [18877199], + 'auditd.log.ses': ['4294967295'], + 'auditd.log.success': ['yes'], + 'auditd.log.syscall': ['44'], + 'auditd.log.tty': ['(none)'], + 'ecs.version': ['1.0.0-beta2'], + 'event.action': ['syscall'], + 'event.dataset': ['auditd.log'], + 'event.module': ['auditd'], + 'fileset.name': ['log'], + 'host.architecture': ['x86_64'], + 'input.type': ['log'], + 'log.offset': [174], + 'process.executable': ['/usr/libexec/strongswan/charon (deleted)'], + 'process.name': ['charon'], + 'process.pid': [1281], + 'process.ppid': [1240], + 'service.type': ['auditd'], + 'user.audit.id': ['4294967295'], + 'user.effective.group.id': ['0'], + 'user.effective.id': ['0'], + 'user.filesystem.group.id': ['0'], + 'user.filesystem.id': ['0'], + 'user.group.id': ['0'], + 'user.id': ['0'], + 'user.saved.group.id': ['0'], + 'user.saved.id': ['0'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[AuditD][", - }, - Object { - "field": "event.action", - "highlights": Array [], - "value": "syscall", - }, - Object { - "constant": "]", - }, - Object { - "constant": " ", - }, - Object { - "constant": "user", - }, - Object { - "constant": "=", - }, - Object { - "field": "user", - "highlights": Array [], - "value": "{\\"audit.id\\":\\"4294967295\\",\\"effective.group.id\\":\\"0\\",\\"effective.id\\":\\"0\\",\\"filesystem.group.id\\":\\"0\\",\\"filesystem.id\\":\\"0\\",\\"group.id\\":\\"0\\",\\"id\\":\\"0\\",\\"saved.group.id\\":\\"0\\",\\"saved.id\\":\\"0\\"}", - }, - Object { - "constant": " ", - }, - Object { - "constant": "process", - }, - Object { - "constant": "=", - }, - Object { - "field": "process", - "highlights": Array [], - "value": "{\\"executable\\":\\"/usr/libexec/strongswan/charon (deleted)\\",\\"name\\":\\"charon\\",\\"pid\\":1281,\\"ppid\\":1240}", - }, - Object { - "constant": " ", - }, - Object { - "field": "auditd.log", - "highlights": Array [], - "value": "{\\"a0\\":\\"9\\",\\"a1\\":\\"7f564b2672a0\\",\\"a2\\":\\"b8\\",\\"a3\\":\\"0\\",\\"exit\\":\\"184\\",\\"items\\":\\"0\\",\\"sequence\\":18877199,\\"ses\\":\\"4294967295\\",\\"success\\":\\"yes\\",\\"syscall\\":\\"44\\",\\"tty\\":\\"(none)\\"}", - }, - Object { - "constant": " ", - }, - Object { - "field": "message", - "highlights": Array [], - "value": "undefined", - }, -] -`); + Array [ + Object { + "constant": "[AuditD][", + }, + Object { + "field": "event.action", + "highlights": Array [], + "value": Array [ + "syscall", + ], + }, + Object { + "constant": "]", + }, + Object { + "constant": " ", + }, + Object { + "constant": "user", + }, + Object { + "constant": "=", + }, + Object { + "field": "user.audit.id", + "highlights": Array [], + "value": Array [ + "4294967295", + ], + }, + Object { + "field": "user.effective.group.id", + "highlights": Array [], + "value": Array [ + "0", + ], + }, + Object { + "field": "user.effective.id", + "highlights": Array [], + "value": Array [ + "0", + ], + }, + Object { + "field": "user.filesystem.group.id", + "highlights": Array [], + "value": Array [ + "0", + ], + }, + Object { + "field": "user.filesystem.id", + "highlights": Array [], + "value": Array [ + "0", + ], + }, + Object { + "field": "user.group.id", + "highlights": Array [], + "value": Array [ + "0", + ], + }, + Object { + "field": "user.id", + "highlights": Array [], + "value": Array [ + "0", + ], + }, + Object { + "field": "user.saved.group.id", + "highlights": Array [], + "value": Array [ + "0", + ], + }, + Object { + "field": "user.saved.id", + "highlights": Array [], + "value": Array [ + "0", + ], + }, + Object { + "constant": " ", + }, + Object { + "constant": "process", + }, + Object { + "constant": "=", + }, + Object { + "field": "process.executable", + "highlights": Array [], + "value": Array [ + "/usr/libexec/strongswan/charon (deleted)", + ], + }, + Object { + "field": "process.name", + "highlights": Array [], + "value": Array [ + "charon", + ], + }, + Object { + "field": "process.pid", + "highlights": Array [], + "value": Array [ + 1281, + ], + }, + Object { + "field": "process.ppid", + "highlights": Array [], + "value": Array [ + 1240, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "auditd.log.a0", + "highlights": Array [], + "value": Array [ + "9", + ], + }, + Object { + "field": "auditd.log.a1", + "highlights": Array [], + "value": Array [ + "7f564b2672a0", + ], + }, + Object { + "field": "auditd.log.a2", + "highlights": Array [], + "value": Array [ + "b8", + ], + }, + Object { + "field": "auditd.log.a3", + "highlights": Array [], + "value": Array [ + "0", + ], + }, + Object { + "field": "auditd.log.exit", + "highlights": Array [], + "value": Array [ + "184", + ], + }, + Object { + "field": "auditd.log.items", + "highlights": Array [], + "value": Array [ + "0", + ], + }, + Object { + "field": "auditd.log.sequence", + "highlights": Array [], + "value": Array [ + 18877199, + ], + }, + Object { + "field": "auditd.log.ses", + "highlights": Array [], + "value": Array [ + "4294967295", + ], + }, + Object { + "field": "auditd.log.success", + "highlights": Array [], + "value": Array [ + "yes", + ], + }, + Object { + "field": "auditd.log.syscall", + "highlights": Array [], + "value": Array [ + "44", + ], + }, + Object { + "field": "auditd.log.tty", + "highlights": Array [], + "value": Array [ + "(none)", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "message", + "highlights": Array [], + "value": Array [], + }, + ] + `); }); }); describe('in pre-ECS format', () => { test('auditd IPSEC rule', () => { const event = { - '@timestamp': '2017-01-31T20:17:14.891Z', - 'auditd.log.auid': '4294967295', - 'auditd.log.dst': '192.168.0.0', - 'auditd.log.dst_prefixlen': '16', - 'auditd.log.op': 'SPD-delete', - 'auditd.log.record_type': 'MAC_IPSEC_EVENT', - 'auditd.log.res': '1', - 'auditd.log.sequence': 18877201, - 'auditd.log.ses': '4294967295', - 'auditd.log.src': '192.168.2.0', - 'auditd.log.src_prefixlen': '24', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'auditd.log', - 'event.module': 'auditd', - 'fileset.name': 'log', - 'input.type': 'log', - 'log.offset': 0, + '@timestamp': ['2017-01-31T20:17:14.891Z'], + 'auditd.log.auid': ['4294967295'], + 'auditd.log.dst': ['192.168.0.0'], + 'auditd.log.dst_prefixlen': ['16'], + 'auditd.log.op': ['SPD-delete'], + 'auditd.log.record_type': ['MAC_IPSEC_EVENT'], + 'auditd.log.res': ['1'], + 'auditd.log.sequence': [18877201], + 'auditd.log.ses': ['4294967295'], + 'auditd.log.src': ['192.168.2.0'], + 'auditd.log.src_prefixlen': ['24'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['auditd.log'], + 'event.module': ['auditd'], + 'fileset.name': ['log'], + 'input.type': ['log'], + 'log.offset': [0], }; const message = format(event, {}); expect(message).toEqual([ { constant: '[AuditD][' }, - { field: 'auditd.log.record_type', highlights: [], value: 'MAC_IPSEC_EVENT' }, + { field: 'auditd.log.record_type', highlights: [], value: ['MAC_IPSEC_EVENT'] }, { constant: '] src:' }, - { field: 'auditd.log.src', highlights: [], value: '192.168.2.0' }, + { field: 'auditd.log.src', highlights: [], value: ['192.168.2.0'] }, { constant: ' dst:' }, - { field: 'auditd.log.dst', highlights: [], value: '192.168.0.0' }, + { field: 'auditd.log.dst', highlights: [], value: ['192.168.0.0'] }, { constant: ' op:' }, - { field: 'auditd.log.op', highlights: [], value: 'SPD-delete' }, + { field: 'auditd.log.op', highlights: [], value: ['SPD-delete'] }, ]); }); test('AuditD SYSCALL rule', () => { const event = { - '@timestamp': '2017-01-31T20:17:14.891Z', - 'auditd.log.a0': '9', - 'auditd.log.a1': '7f564b2672a0', - 'auditd.log.a2': 'b8', - 'auditd.log.a3': '0', - 'auditd.log.arch': 'x86_64', - 'auditd.log.auid': '4294967295', - 'auditd.log.comm': 'charon', - 'auditd.log.egid': '0', - 'auditd.log.euid': '0', - 'auditd.log.exe': '/usr/libexec/strongswan/charon (deleted)', - 'auditd.log.exit': '184', - 'auditd.log.fsgid': '0', - 'auditd.log.fsuid': '0', - 'auditd.log.gid': '0', - 'auditd.log.items': '0', - 'auditd.log.pid': '1281', - 'auditd.log.ppid': '1240', - 'auditd.log.record_type': 'SYSCALL', - 'auditd.log.sequence': 18877199, - 'auditd.log.ses': '4294967295', - 'auditd.log.sgid': '0', - 'auditd.log.success': 'yes', - 'auditd.log.suid': '0', - 'auditd.log.syscall': '44', - 'auditd.log.tty': '(none)', - 'auditd.log.uid': '0', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'auditd.log', - 'event.module': 'auditd', - 'fileset.name': 'log', - 'input.type': 'log', - 'log.offset': 174, + '@timestamp': ['2017-01-31T20:17:14.891Z'], + 'auditd.log.a0': ['9'], + 'auditd.log.a1': ['7f564b2672a0'], + 'auditd.log.a2': ['b8'], + 'auditd.log.a3': ['0'], + 'auditd.log.arch': ['x86_64'], + 'auditd.log.auid': ['4294967295'], + 'auditd.log.comm': ['charon'], + 'auditd.log.egid': ['0'], + 'auditd.log.euid': ['0'], + 'auditd.log.exe': ['/usr/libexec/strongswan/charon (deleted)'], + 'auditd.log.exit': ['184'], + 'auditd.log.fsgid': ['0'], + 'auditd.log.fsuid': ['0'], + 'auditd.log.gid': ['0'], + 'auditd.log.items': ['0'], + 'auditd.log.pid': ['1281'], + 'auditd.log.ppid': ['1240'], + 'auditd.log.record_type': ['SYSCALL'], + 'auditd.log.sequence': [18877199], + 'auditd.log.ses': ['4294967295'], + 'auditd.log.sgid': ['0'], + 'auditd.log.success': ['yes'], + 'auditd.log.suid': ['0'], + 'auditd.log.syscall': ['44'], + 'auditd.log.tty': ['(none)'], + 'auditd.log.uid': ['0'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['auditd.log'], + 'event.module': ['auditd'], + 'fileset.name': ['log'], + 'input.type': ['log'], + 'log.offset': [174], }; const message = format(event, {}); expect(message).toEqual([ { constant: '[AuditD][' }, - { field: 'auditd.log.record_type', highlights: [], value: 'SYSCALL' }, + { field: 'auditd.log.record_type', highlights: [], value: ['SYSCALL'] }, { constant: '] exe:' }, { field: 'auditd.log.exe', highlights: [], - value: '/usr/libexec/strongswan/charon (deleted)', + value: ['/usr/libexec/strongswan/charon (deleted)'], }, { constant: ' gid:' }, - { field: 'auditd.log.gid', highlights: [], value: '0' }, + { field: 'auditd.log.gid', highlights: [], value: ['0'] }, { constant: ' uid:' }, - { field: 'auditd.log.uid', highlights: [], value: '0' }, + { field: 'auditd.log.uid', highlights: [], value: ['0'] }, { constant: ' tty:' }, - { field: 'auditd.log.tty', highlights: [], value: '(none)' }, + { field: 'auditd.log.tty', highlights: [], value: ['(none)'] }, { constant: ' pid:' }, - { field: 'auditd.log.pid', highlights: [], value: '1281' }, + { field: 'auditd.log.pid', highlights: [], value: ['1281'] }, { constant: ' ppid:' }, - { field: 'auditd.log.ppid', highlights: [], value: '1240' }, + { field: 'auditd.log.ppid', highlights: [], value: ['1240'] }, ]); }); test('AuditD events with msg rule', () => { const event = { - '@timestamp': '2017-01-31T20:17:14.891Z', - 'auditd.log.auid': '4294967295', - 'auditd.log.record_type': 'EXAMPLE', - 'auditd.log.msg': 'some kind of message', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'auditd.log', - 'event.module': 'auditd', - 'fileset.name': 'log', - 'input.type': 'log', - 'log.offset': 174, + '@timestamp': ['2017-01-31T20:17:14.891Z'], + 'auditd.log.auid': ['4294967295'], + 'auditd.log.record_type': ['EXAMPLE'], + 'auditd.log.msg': ['some kind of message'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['auditd.log'], + 'event.module': ['auditd'], + 'fileset.name': ['log'], + 'input.type': ['log'], + 'log.offset': [174], }; const message = format(event, {}); expect(message).toEqual([ { constant: '[AuditD][' }, - { field: 'auditd.log.record_type', highlights: [], value: 'EXAMPLE' }, + { field: 'auditd.log.record_type', highlights: [], value: ['EXAMPLE'] }, { constant: '] ' }, { field: 'auditd.log.msg', highlights: [], - value: 'some kind of message', + value: ['some kind of message'], }, ]); }); test('AuditD catchall rule', () => { const event = { - '@timestamp': '2017-01-31T20:17:14.891Z', - 'auditd.log.auid': '4294967295', - 'auditd.log.record_type': 'EXAMPLE', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'auditd.log', - 'event.module': 'auditd', - 'fileset.name': 'log', - 'input.type': 'log', - 'log.offset': 174, + '@timestamp': ['2017-01-31T20:17:14.891Z'], + 'auditd.log.auid': ['4294967295'], + 'auditd.log.record_type': ['EXAMPLE'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['auditd.log'], + 'event.module': ['auditd'], + 'fileset.name': ['log'], + 'input.type': ['log'], + 'log.offset': [174], }; const message = format(event, {}); expect(message).toEqual([ { constant: '[AuditD][' }, - { field: 'auditd.log.record_type', highlights: [], value: 'EXAMPLE' }, + { field: 'auditd.log.record_type', highlights: [], value: ['EXAMPLE'] }, { constant: '] Event without message.' }, ]); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_auditd.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_auditd.ts index d2557cf1599c..cd64697db6d1 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_auditd.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_auditd.ts @@ -4,24 +4,28 @@ * you may not use this file except in compliance with the Elastic License. */ -import { labelField } from './helpers'; +import { LogMessageFormattingRule } from '../rule_types'; +import { labelFieldsPrefix } from './helpers'; const commonActionField = [{ constant: '[AuditD][' }, { field: 'event.action' }, { constant: ']' }]; const commonOutcomeField = [{ constant: ' ' }, { field: 'event.outcome' }]; -export const filebeatAuditdRules = [ +export const filebeatAuditdRules: LogMessageFormattingRule[] = [ { // ECS format with outcome when: { - exists: ['ecs.version', 'event.action', 'event.outcome', 'auditd.log'], + all: [ + { exists: ['ecs.version', 'event.action', 'event.outcome'] }, + { existsPrefix: ['auditd.log'] }, + ], }, format: [ ...commonActionField, ...commonOutcomeField, - ...labelField('user', 'user'), - ...labelField('process', 'process'), + ...labelFieldsPrefix('user', 'user'), + ...labelFieldsPrefix('process', 'process'), { constant: ' ' }, - { field: 'auditd.log' }, + { fieldsPrefix: 'auditd.log' }, { constant: ' ' }, { field: 'message' }, ], @@ -29,14 +33,14 @@ export const filebeatAuditdRules = [ { // ECS format without outcome when: { - exists: ['ecs.version', 'event.action', 'auditd.log'], + all: [{ exists: ['ecs.version', 'event.action'] }, { existsPrefix: ['auditd.log'] }], }, format: [ ...commonActionField, - ...labelField('user', 'user'), - ...labelField('process', 'process'), + ...labelFieldsPrefix('user', 'user'), + ...labelFieldsPrefix('process', 'process'), { constant: ' ' }, - { field: 'auditd.log' }, + { fieldsPrefix: 'auditd.log' }, { constant: ' ' }, { field: 'message' }, ], @@ -44,10 +48,10 @@ export const filebeatAuditdRules = [ { // pre-ECS IPSEC_EVENT Rule when: { - exists: ['auditd.log.record_type', 'auditd.log.src', 'auditd.log.dst', 'auditd.log.op'], - values: { - 'auditd.log.record_type': 'MAC_IPSEC_EVENT', - }, + all: [ + { exists: ['auditd.log.record_type', 'auditd.log.src', 'auditd.log.dst', 'auditd.log.op'] }, + { values: { 'auditd.log.record_type': 'MAC_IPSEC_EVENT' } }, + ], }, format: [ { constant: '[AuditD][' }, @@ -63,18 +67,20 @@ export const filebeatAuditdRules = [ { // pre-ECS SYSCALL Rule when: { - exists: [ - 'auditd.log.record_type', - 'auditd.log.exe', - 'auditd.log.gid', - 'auditd.log.uid', - 'auditd.log.tty', - 'auditd.log.pid', - 'auditd.log.ppid', + all: [ + { + exists: [ + 'auditd.log.record_type', + 'auditd.log.exe', + 'auditd.log.gid', + 'auditd.log.uid', + 'auditd.log.tty', + 'auditd.log.pid', + 'auditd.log.ppid', + ], + }, + { values: { 'auditd.log.record_type': 'SYSCALL' } }, ], - values: { - 'auditd.log.record_type': 'SYSCALL', - }, }, format: [ { constant: '[AuditD][' }, diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_haproxy.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_haproxy.test.ts index 752b61684887..40e8ea0fad85 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_haproxy.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_haproxy.test.ts @@ -13,779 +13,917 @@ describe('Filebeat Rules', () => { describe('in ECS format', () => { test('haproxy default log', () => { const flattenedDocument = { - 'destination.ip': '1.2.3.4', - 'destination.port': 5000, - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'haproxy.log', - 'event.module': 'haproxy', - 'fileset.name': 'log', - 'haproxy.frontend_name': 'main', - 'haproxy.mode': 'HTTP', - 'haproxy.source': '1.2.3.4', - 'input.type': 'log', - 'log.offset': 0, - 'process.name': 'haproxy', - 'process.pid': 24551, - 'service.type': 'haproxy', - 'source.address': '1.2.3.4', - 'source.geo.continent_name': 'North America', - 'source.geo.country_iso_code': 'US', - 'source.geo.location.lat': 37.751, - 'source.geo.location.lon': -97.822, - 'source.ip': '1.2.3.4', - 'source.port': 40780, + 'destination.ip': ['1.2.3.4'], + 'destination.port': [5000], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['haproxy.log'], + 'event.module': ['haproxy'], + 'fileset.name': ['log'], + 'haproxy.frontend_name': ['main'], + 'haproxy.mode': ['HTTP'], + 'haproxy.source': ['1.2.3.4'], + 'input.type': ['log'], + 'log.offset': [0], + 'process.name': ['haproxy'], + 'process.pid': [24551], + 'service.type': ['haproxy'], + 'source.address': ['1.2.3.4'], + 'source.geo.continent_name': ['North America'], + 'source.geo.country_iso_code': ['US'], + 'source.geo.location.lat': [37.751], + 'source.geo.location.lon': [-97.822], + 'source.ip': ['1.2.3.4'], + 'source.port': [40780], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[HAProxy] ", - }, - Object { - "field": "source.address", - "highlights": Array [], - "value": "1.2.3.4", - }, - Object { - "constant": ":", - }, - Object { - "field": "source.port", - "highlights": Array [], - "value": "40780", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.frontend_name", - "highlights": Array [], - "value": "main", - }, -] -`); + Array [ + Object { + "constant": "[HAProxy] ", + }, + Object { + "field": "source.address", + "highlights": Array [], + "value": Array [ + "1.2.3.4", + ], + }, + Object { + "constant": ":", + }, + Object { + "field": "source.port", + "highlights": Array [], + "value": Array [ + 40780, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.frontend_name", + "highlights": Array [], + "value": Array [ + "main", + ], + }, + ] + `); }); test('haproxy tcp log', () => { const flattenedDocument = { - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'haproxy.log', - 'event.duration': 1000000, - 'event.module': 'haproxy', - 'fileset.name': 'log', - 'haproxy.backend_name': 'app', - 'haproxy.backend_queue': 0, - 'haproxy.bytes_read': 212, - 'haproxy.connection_wait_time_ms': -1, - 'haproxy.connections.active': 1, - 'haproxy.connections.backend': 0, - 'haproxy.connections.frontend': 1, - 'haproxy.connections.retries': 0, - 'haproxy.connections.server': 0, - 'haproxy.frontend_name': 'main', - 'haproxy.server_name': '', - 'haproxy.server_queue': 0, - 'haproxy.source': '127.0.0.1', - 'haproxy.termination_state': 'SC', - 'haproxy.total_waiting_time_ms': -1, - 'input.type': 'log', - 'log.offset': 0, - 'process.name': 'haproxy', - 'process.pid': 25457, - 'service.type': 'haproxy', - 'source.address': '127.0.0.1', - 'source.ip': '127.0.0.1', - 'source.port': 40962, + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['haproxy.log'], + 'event.duration': [1000000], + 'event.module': ['haproxy'], + 'fileset.name': ['log'], + 'haproxy.backend_name': ['app'], + 'haproxy.backend_queue': [0], + 'haproxy.bytes_read': [212], + 'haproxy.connection_wait_time_ms': [-1], + 'haproxy.connections.active': [1], + 'haproxy.connections.backend': [0], + 'haproxy.connections.frontend': [1], + 'haproxy.connections.retries': [0], + 'haproxy.connections.server': [0], + 'haproxy.frontend_name': ['main'], + 'haproxy.server_name': [''], + 'haproxy.server_queue': [0], + 'haproxy.source': ['127.0.0.1'], + 'haproxy.termination_state': ['SC'], + 'haproxy.total_waiting_time_ms': [-1], + 'input.type': ['log'], + 'log.offset': [0], + 'process.name': ['haproxy'], + 'process.pid': [25457], + 'service.type': ['haproxy'], + 'source.address': ['127.0.0.1'], + 'source.ip': ['127.0.0.1'], + 'source.port': [40962], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[HAProxy][tcp] ", - }, - Object { - "field": "source.address", - "highlights": Array [], - "value": "127.0.0.1", - }, - Object { - "constant": ":", - }, - Object { - "field": "source.port", - "highlights": Array [], - "value": "40962", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.frontend_name", - "highlights": Array [], - "value": "main", - }, - Object { - "constant": " -> ", - }, - Object { - "field": "haproxy.backend_name", - "highlights": Array [], - "value": "app", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.server_name", - "highlights": Array [], - "value": "", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.connections.active", - "highlights": Array [], - "value": "1", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.frontend", - "highlights": Array [], - "value": "1", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.backend", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.server", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.retries", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.server_queue", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.backend_queue", - "highlights": Array [], - "value": "0", - }, -] -`); + Array [ + Object { + "constant": "[HAProxy][tcp] ", + }, + Object { + "field": "source.address", + "highlights": Array [], + "value": Array [ + "127.0.0.1", + ], + }, + Object { + "constant": ":", + }, + Object { + "field": "source.port", + "highlights": Array [], + "value": Array [ + 40962, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.frontend_name", + "highlights": Array [], + "value": Array [ + "main", + ], + }, + Object { + "constant": " -> ", + }, + Object { + "field": "haproxy.backend_name", + "highlights": Array [], + "value": Array [ + "app", + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.server_name", + "highlights": Array [], + "value": Array [ + "", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.connections.active", + "highlights": Array [], + "value": Array [ + 1, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.frontend", + "highlights": Array [], + "value": Array [ + 1, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.backend", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.server", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.retries", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.server_queue", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.backend_queue", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + ] + `); }); test('haproxy http log', () => { const flattenedDocument = { - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'haproxy.log', - 'event.duration': 2000000, - 'event.module': 'haproxy', - 'fileset.name': 'log', - 'haproxy.backend_name': 'docs_microservice', - 'haproxy.backend_queue': 0, - 'haproxy.bytes_read': 168, - 'haproxy.connection_wait_time_ms': 1, - 'haproxy.connections.active': 6, - 'haproxy.connections.backend': 0, - 'haproxy.connections.frontend': 6, - 'haproxy.connections.retries': 0, - 'haproxy.connections.server': 0, - 'haproxy.frontend_name': 'incoming~', - 'haproxy.http.request.captured_cookie': '-', + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['haproxy.log'], + 'event.duration': [2000000], + 'event.module': ['haproxy'], + 'fileset.name': ['log'], + 'haproxy.backend_name': ['docs_microservice'], + 'haproxy.backend_queue': [0], + 'haproxy.bytes_read': [168], + 'haproxy.connection_wait_time_ms': [1], + 'haproxy.connections.active': [6], + 'haproxy.connections.backend': [0], + 'haproxy.connections.frontend': [6], + 'haproxy.connections.retries': [0], + 'haproxy.connections.server': [0], + 'haproxy.frontend_name': ['incoming~'], + 'haproxy.http.request.captured_cookie': ['-'], 'haproxy.http.request.captured_headers': ['docs.example.internal'], - 'haproxy.http.request.raw_request_line': + 'haproxy.http.request.raw_request_line': [ 'GET /component---src-pages-index-js-4b15624544f97cf0bb8f.js HTTP/1.1', - 'haproxy.http.request.time_wait_ms': 0, - 'haproxy.http.request.time_wait_without_data_ms': 0, - 'haproxy.http.response.captured_cookie': '-', + ], + 'haproxy.http.request.time_wait_ms': [0], + 'haproxy.http.request.time_wait_without_data_ms': [0], + 'haproxy.http.response.captured_cookie': ['-'], 'haproxy.http.response.captured_headers': [], - 'haproxy.server_name': 'docs', - 'haproxy.server_queue': 0, - 'haproxy.termination_state': '----', - 'haproxy.total_waiting_time_ms': 0, - 'http.response.bytes': 168, - 'http.response.status_code': 304, - 'input.type': 'log', - 'log.offset': 0, - 'process.name': 'haproxy', - 'process.pid': 32450, - 'service.type': 'haproxy', - 'source.address': '1.2.3.4', - 'source.geo.continent_name': 'North America', - 'source.geo.country_iso_code': 'US', - 'source.geo.location.lat': 37.751, - 'source.geo.location.lon': -97.822, - 'source.ip': '1.2.3.4', - 'source.port': 38862, + 'haproxy.server_name': ['docs'], + 'haproxy.server_queue': [0], + 'haproxy.termination_state': ['----'], + 'haproxy.total_waiting_time_ms': [0], + 'http.response.bytes': [168], + 'http.response.status_code': [304], + 'input.type': ['log'], + 'log.offset': [0], + 'process.name': ['haproxy'], + 'process.pid': [32450], + 'service.type': ['haproxy'], + 'source.address': ['1.2.3.4'], + 'source.geo.continent_name': ['North America'], + 'source.geo.country_iso_code': ['US'], + 'source.geo.location.lat': [37.751], + 'source.geo.location.lon': [-97.822], + 'source.ip': ['1.2.3.4'], + 'source.port': [38862], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[HAProxy][http] ", - }, - Object { - "field": "source.address", - "highlights": Array [], - "value": "1.2.3.4", - }, - Object { - "constant": ":", - }, - Object { - "field": "source.port", - "highlights": Array [], - "value": "38862", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.frontend_name", - "highlights": Array [], - "value": "incoming~", - }, - Object { - "constant": " -> ", - }, - Object { - "field": "haproxy.backend_name", - "highlights": Array [], - "value": "docs_microservice", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.server_name", - "highlights": Array [], - "value": "docs", - }, - Object { - "constant": " \\"", - }, - Object { - "field": "haproxy.http.request.raw_request_line", - "highlights": Array [], - "value": "GET /component---src-pages-index-js-4b15624544f97cf0bb8f.js HTTP/1.1", - }, - Object { - "constant": "\\" ", - }, - Object { - "field": "http.response.status_code", - "highlights": Array [], - "value": "304", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.http.request.time_wait_ms", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "event.duration", - "highlights": Array [], - "value": "2000000", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connection_wait_time_ms", - "highlights": Array [], - "value": "1", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.http.request.time_wait_without_data_ms", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "event.duration", - "highlights": Array [], - "value": "2000000", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.connections.active", - "highlights": Array [], - "value": "6", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.frontend", - "highlights": Array [], - "value": "6", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.backend", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.server", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.retries", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.server_queue", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.backend_queue", - "highlights": Array [], - "value": "0", - }, -] -`); + Array [ + Object { + "constant": "[HAProxy][http] ", + }, + Object { + "field": "source.address", + "highlights": Array [], + "value": Array [ + "1.2.3.4", + ], + }, + Object { + "constant": ":", + }, + Object { + "field": "source.port", + "highlights": Array [], + "value": Array [ + 38862, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.frontend_name", + "highlights": Array [], + "value": Array [ + "incoming~", + ], + }, + Object { + "constant": " -> ", + }, + Object { + "field": "haproxy.backend_name", + "highlights": Array [], + "value": Array [ + "docs_microservice", + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.server_name", + "highlights": Array [], + "value": Array [ + "docs", + ], + }, + Object { + "constant": " \\"", + }, + Object { + "field": "haproxy.http.request.raw_request_line", + "highlights": Array [], + "value": Array [ + "GET /component---src-pages-index-js-4b15624544f97cf0bb8f.js HTTP/1.1", + ], + }, + Object { + "constant": "\\" ", + }, + Object { + "field": "http.response.status_code", + "highlights": Array [], + "value": Array [ + 304, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.http.request.time_wait_ms", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "event.duration", + "highlights": Array [], + "value": Array [ + 2000000, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connection_wait_time_ms", + "highlights": Array [], + "value": Array [ + 1, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.http.request.time_wait_without_data_ms", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "event.duration", + "highlights": Array [], + "value": Array [ + 2000000, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.connections.active", + "highlights": Array [], + "value": Array [ + 6, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.frontend", + "highlights": Array [], + "value": Array [ + 6, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.backend", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.server", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.retries", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.server_queue", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.backend_queue", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + ] + `); }); }); describe('in pre-ECS format', () => { test('haproxy default log', () => { const flattenedDocument = { - 'event.dataset': 'haproxy.log', - 'fileset.module': 'haproxy', - 'fileset.name': 'log', - 'haproxy.client.ip': '1.2.3.4', - 'haproxy.client.port': '40780', - 'haproxy.destination.ip': '1.2.3.4', - 'haproxy.destination.port': '5000', - 'haproxy.frontend_name': 'main', - 'haproxy.geoip.continent_name': 'North America', - 'haproxy.geoip.country_iso_code': 'US', - 'haproxy.geoip.location.lat': 37.751, - 'haproxy.geoip.location.lon': -97.822, - 'haproxy.mode': 'HTTP', - 'haproxy.pid': '24551', - 'haproxy.process_name': 'haproxy', - 'haproxy.source': '1.2.3.4', - 'input.type': 'log', - offset: 0, - 'prospector.type': 'log', + 'event.dataset': ['haproxy.log'], + 'fileset.module': ['haproxy'], + 'fileset.name': ['log'], + 'haproxy.client.ip': ['1.2.3.4'], + 'haproxy.client.port': ['40780'], + 'haproxy.destination.ip': ['1.2.3.4'], + 'haproxy.destination.port': ['5000'], + 'haproxy.frontend_name': ['main'], + 'haproxy.geoip.continent_name': ['North America'], + 'haproxy.geoip.country_iso_code': ['US'], + 'haproxy.geoip.location.lat': [37.751], + 'haproxy.geoip.location.lon': [-97.822], + 'haproxy.mode': ['HTTP'], + 'haproxy.pid': ['24551'], + 'haproxy.process_name': ['haproxy'], + 'haproxy.source': ['1.2.3.4'], + 'input.type': ['log'], + offset: [0], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[HAProxy] ", - }, - Object { - "field": "haproxy.client.ip", - "highlights": Array [], - "value": "1.2.3.4", - }, - Object { - "constant": ":", - }, - Object { - "field": "haproxy.client.port", - "highlights": Array [], - "value": "40780", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.frontend_name", - "highlights": Array [], - "value": "main", - }, -] -`); + Array [ + Object { + "constant": "[HAProxy] ", + }, + Object { + "field": "haproxy.client.ip", + "highlights": Array [], + "value": Array [ + "1.2.3.4", + ], + }, + Object { + "constant": ":", + }, + Object { + "field": "haproxy.client.port", + "highlights": Array [], + "value": Array [ + "40780", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.frontend_name", + "highlights": Array [], + "value": Array [ + "main", + ], + }, + ] + `); }); test('haproxy tcp log', () => { const flattenedDocument = { - 'event.dataset': 'haproxy.log', - 'fileset.module': 'haproxy', - 'fileset.name': 'log', - 'haproxy.backend_name': 'app', - 'haproxy.backend_queue': 0, - 'haproxy.bytes_read': 212, - 'haproxy.client.ip': '127.0.0.1', - 'haproxy.client.port': 40962, - 'haproxy.connection_wait_time_ms': -1, - 'haproxy.connections.active': 1, - 'haproxy.connections.backend': 0, - 'haproxy.connections.frontend': 1, - 'haproxy.connections.retries': 0, - 'haproxy.connections.server': 0, - 'haproxy.frontend_name': 'main', - 'haproxy.pid': 25457, - 'haproxy.process_name': 'haproxy', - 'haproxy.server_name': '', - 'haproxy.server_queue': 0, - 'haproxy.source': '127.0.0.1', - 'haproxy.tcp.processing_time_ms': 0, - 'haproxy.termination_state': 'SC', - 'haproxy.total_waiting_time_ms': -1, - 'input.type': 'log', - offset: 0, - 'prospector.type': 'log', + 'event.dataset': ['haproxy.log'], + 'fileset.module': ['haproxy'], + 'fileset.name': ['log'], + 'haproxy.backend_name': ['app'], + 'haproxy.backend_queue': [0], + 'haproxy.bytes_read': [212], + 'haproxy.client.ip': ['127.0.0.1'], + 'haproxy.client.port': [40962], + 'haproxy.connection_wait_time_ms': [-1], + 'haproxy.connections.active': [1], + 'haproxy.connections.backend': [0], + 'haproxy.connections.frontend': [1], + 'haproxy.connections.retries': [0], + 'haproxy.connections.server': [0], + 'haproxy.frontend_name': ['main'], + 'haproxy.pid': [25457], + 'haproxy.process_name': ['haproxy'], + 'haproxy.server_name': [''], + 'haproxy.server_queue': [0], + 'haproxy.source': ['127.0.0.1'], + 'haproxy.tcp.processing_time_ms': [0], + 'haproxy.termination_state': ['SC'], + 'haproxy.total_waiting_time_ms': [-1], + 'input.type': ['log'], + offset: [0], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[HAProxy][tcp] ", - }, - Object { - "field": "haproxy.client.ip", - "highlights": Array [], - "value": "127.0.0.1", - }, - Object { - "constant": ":", - }, - Object { - "field": "haproxy.client.port", - "highlights": Array [], - "value": "40962", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.frontend_name", - "highlights": Array [], - "value": "main", - }, - Object { - "constant": " -> ", - }, - Object { - "field": "haproxy.backend_name", - "highlights": Array [], - "value": "app", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.server_name", - "highlights": Array [], - "value": "", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.connections.active", - "highlights": Array [], - "value": "1", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.frontend", - "highlights": Array [], - "value": "1", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.backend", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.server", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.retries", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.server_queue", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.backend_queue", - "highlights": Array [], - "value": "0", - }, -] -`); + Array [ + Object { + "constant": "[HAProxy][tcp] ", + }, + Object { + "field": "haproxy.client.ip", + "highlights": Array [], + "value": Array [ + "127.0.0.1", + ], + }, + Object { + "constant": ":", + }, + Object { + "field": "haproxy.client.port", + "highlights": Array [], + "value": Array [ + 40962, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.frontend_name", + "highlights": Array [], + "value": Array [ + "main", + ], + }, + Object { + "constant": " -> ", + }, + Object { + "field": "haproxy.backend_name", + "highlights": Array [], + "value": Array [ + "app", + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.server_name", + "highlights": Array [], + "value": Array [ + "", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.connections.active", + "highlights": Array [], + "value": Array [ + 1, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.frontend", + "highlights": Array [], + "value": Array [ + 1, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.backend", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.server", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.retries", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.server_queue", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.backend_queue", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + ] + `); }); test('haproxy http log', () => { const flattenedDocument = { - 'event.dataset': 'haproxy.log', - 'fileset.module': 'haproxy', - 'fileset.name': 'log', - 'haproxy.backend_name': 'docs_microservice', - 'haproxy.backend_queue': 0, - 'haproxy.bytes_read': 168, - 'haproxy.client.ip': '1.2.3.4', - 'haproxy.client.port': 38862, - 'haproxy.connection_wait_time_ms': 1, - 'haproxy.connections.active': 6, - 'haproxy.connections.backend': 0, - 'haproxy.connections.frontend': 6, - 'haproxy.connections.retries': 0, - 'haproxy.connections.server': 0, - 'haproxy.frontend_name': 'incoming~', - 'haproxy.geoip.continent_name': 'North America', - 'haproxy.geoip.country_iso_code': 'US', - 'haproxy.geoip.location.lat': 37.751, - 'haproxy.geoip.location.lon': -97.822, - 'haproxy.http.request.captured_cookie': '-', - 'haproxy.http.request.raw_request_line': + 'event.dataset': ['haproxy.log'], + 'fileset.module': ['haproxy'], + 'fileset.name': ['log'], + 'haproxy.backend_name': ['docs_microservice'], + 'haproxy.backend_queue': [0], + 'haproxy.bytes_read': [168], + 'haproxy.client.ip': ['1.2.3.4'], + 'haproxy.client.port': [38862], + 'haproxy.connection_wait_time_ms': [1], + 'haproxy.connections.active': [6], + 'haproxy.connections.backend': [0], + 'haproxy.connections.frontend': [6], + 'haproxy.connections.retries': [0], + 'haproxy.connections.server': [0], + 'haproxy.frontend_name': ['incoming~'], + 'haproxy.geoip.continent_name': ['North America'], + 'haproxy.geoip.country_iso_code': ['US'], + 'haproxy.geoip.location.lat': [37.751], + 'haproxy.geoip.location.lon': [-97.822], + 'haproxy.http.request.captured_cookie': ['-'], + 'haproxy.http.request.raw_request_line': [ 'GET /component---src-pages-index-js-4b15624544f97cf0bb8f.js HTTP/1.1', - 'haproxy.http.request.time_active_ms': 2, - 'haproxy.http.request.time_wait_ms': 0, - 'haproxy.http.request.time_wait_without_data_ms': 0, - 'haproxy.http.response.captured_cookie': '-', - 'haproxy.http.response.status_code': 304, - 'haproxy.pid': 32450, - 'haproxy.process_name': 'haproxy', - 'haproxy.server_name': 'docs', - 'haproxy.server_queue': 0, - 'haproxy.termination_state': '----', - 'haproxy.total_waiting_time_ms': 0, - 'input.type': 'log', - offset: 0, - 'prospector.type': 'log', + ], + 'haproxy.http.request.time_active_ms': [2], + 'haproxy.http.request.time_wait_ms': [0], + 'haproxy.http.request.time_wait_without_data_ms': [0], + 'haproxy.http.response.captured_cookie': ['-'], + 'haproxy.http.response.status_code': [304], + 'haproxy.pid': [32450], + 'haproxy.process_name': ['haproxy'], + 'haproxy.server_name': ['docs'], + 'haproxy.server_queue': [0], + 'haproxy.termination_state': ['----'], + 'haproxy.total_waiting_time_ms': [0], + 'input.type': ['log'], + offset: [0], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[HAProxy][http] ", - }, - Object { - "field": "haproxy.client.ip", - "highlights": Array [], - "value": "1.2.3.4", - }, - Object { - "constant": ":", - }, - Object { - "field": "haproxy.client.port", - "highlights": Array [], - "value": "38862", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.frontend_name", - "highlights": Array [], - "value": "incoming~", - }, - Object { - "constant": " -> ", - }, - Object { - "field": "haproxy.backend_name", - "highlights": Array [], - "value": "docs_microservice", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.server_name", - "highlights": Array [], - "value": "docs", - }, - Object { - "constant": " \\"", - }, - Object { - "field": "haproxy.http.request.raw_request_line", - "highlights": Array [], - "value": "GET /component---src-pages-index-js-4b15624544f97cf0bb8f.js HTTP/1.1", - }, - Object { - "constant": "\\" ", - }, - Object { - "field": "haproxy.http.response.status_code", - "highlights": Array [], - "value": "304", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.http.request.time_wait_ms", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.total_waiting_time_ms", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connection_wait_time_ms", - "highlights": Array [], - "value": "1", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.http.request.time_wait_without_data_ms", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.http.request.time_active_ms", - "highlights": Array [], - "value": "2", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.connections.active", - "highlights": Array [], - "value": "6", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.frontend", - "highlights": Array [], - "value": "6", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.backend", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.server", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.connections.retries", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": " ", - }, - Object { - "field": "haproxy.server_queue", - "highlights": Array [], - "value": "0", - }, - Object { - "constant": "/", - }, - Object { - "field": "haproxy.backend_queue", - "highlights": Array [], - "value": "0", - }, -] -`); + Array [ + Object { + "constant": "[HAProxy][http] ", + }, + Object { + "field": "haproxy.client.ip", + "highlights": Array [], + "value": Array [ + "1.2.3.4", + ], + }, + Object { + "constant": ":", + }, + Object { + "field": "haproxy.client.port", + "highlights": Array [], + "value": Array [ + 38862, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.frontend_name", + "highlights": Array [], + "value": Array [ + "incoming~", + ], + }, + Object { + "constant": " -> ", + }, + Object { + "field": "haproxy.backend_name", + "highlights": Array [], + "value": Array [ + "docs_microservice", + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.server_name", + "highlights": Array [], + "value": Array [ + "docs", + ], + }, + Object { + "constant": " \\"", + }, + Object { + "field": "haproxy.http.request.raw_request_line", + "highlights": Array [], + "value": Array [ + "GET /component---src-pages-index-js-4b15624544f97cf0bb8f.js HTTP/1.1", + ], + }, + Object { + "constant": "\\" ", + }, + Object { + "field": "haproxy.http.response.status_code", + "highlights": Array [], + "value": Array [ + 304, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.http.request.time_wait_ms", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.total_waiting_time_ms", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connection_wait_time_ms", + "highlights": Array [], + "value": Array [ + 1, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.http.request.time_wait_without_data_ms", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.http.request.time_active_ms", + "highlights": Array [], + "value": Array [ + 2, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.connections.active", + "highlights": Array [], + "value": Array [ + 6, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.frontend", + "highlights": Array [], + "value": Array [ + 6, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.backend", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.server", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.connections.retries", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "haproxy.server_queue", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + Object { + "constant": "/", + }, + Object { + "field": "haproxy.backend_queue", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + ] + `); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_icinga.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_icinga.test.ts index 120137f15b88..00d282e1833d 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_icinga.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_icinga.test.ts @@ -13,135 +13,155 @@ describe('Filebeat Rules', () => { describe('in pre-ECS format', () => { test('icinga debug log', () => { const flattenedDocument = { - '@timestamp': '2017-04-04T11:43:09.000Z', - 'event.dataset': 'icinga.debug', - 'fileset.module': 'icinga', - 'fileset.name': 'debug', - 'icinga.debug.facility': 'GraphiteWriter', - 'icinga.debug.message': + '@timestamp': ['2017-04-04T11:43:09.000Z'], + 'event.dataset': ['icinga.debug'], + 'fileset.module': ['icinga'], + 'fileset.name': ['debug'], + 'icinga.debug.facility': ['GraphiteWriter'], + 'icinga.debug.message': [ "Add to metric list:'icinga2.demo.services.procs.procs.perfdata.procs.warn 250 1491306189'.", - 'icinga.debug.severity': 'debug', - 'input.type': 'log', - offset: 0, - 'prospector.type': 'log', + ], + 'icinga.debug.severity': ['debug'], + 'input.type': ['log'], + offset: [0], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[Icinga][", - }, - Object { - "field": "icinga.debug.facility", - "highlights": Array [], - "value": "GraphiteWriter", - }, - Object { - "constant": "][", - }, - Object { - "field": "icinga.debug.severity", - "highlights": Array [], - "value": "debug", - }, - Object { - "constant": "] ", - }, - Object { - "field": "icinga.debug.message", - "highlights": Array [], - "value": "Add to metric list:'icinga2.demo.services.procs.procs.perfdata.procs.warn 250 1491306189'.", - }, -] -`); + Array [ + Object { + "constant": "[Icinga][", + }, + Object { + "field": "icinga.debug.facility", + "highlights": Array [], + "value": Array [ + "GraphiteWriter", + ], + }, + Object { + "constant": "][", + }, + Object { + "field": "icinga.debug.severity", + "highlights": Array [], + "value": Array [ + "debug", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "icinga.debug.message", + "highlights": Array [], + "value": Array [ + "Add to metric list:'icinga2.demo.services.procs.procs.perfdata.procs.warn 250 1491306189'.", + ], + }, + ] + `); }); test('icinga main log', () => { const flattenedDocument = { - '@timestamp': '2017-04-04T09:16:34.000Z', - 'event.dataset': 'icinga.main', - 'fileset.module': 'icinga', - 'fileset.name': 'main', - 'icinga.main.facility': 'Notification', - 'icinga.main.message': + '@timestamp': ['2017-04-04T09:16:34.000Z'], + 'event.dataset': ['icinga.main'], + 'fileset.module': ['icinga'], + 'fileset.name': ['main'], + 'icinga.main.facility': ['Notification'], + 'icinga.main.message': [ "Sending 'Recovery' notification 'demo!load!mail-icingaadmin for user 'on-call'", - 'icinga.main.severity': 'information', - 'input.type': 'log', - offset: 0, - 'prospector.type': 'log', + ], + 'icinga.main.severity': ['information'], + 'input.type': ['log'], + offset: [0], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[Icinga][", - }, - Object { - "field": "icinga.main.facility", - "highlights": Array [], - "value": "Notification", - }, - Object { - "constant": "][", - }, - Object { - "field": "icinga.main.severity", - "highlights": Array [], - "value": "information", - }, - Object { - "constant": "] ", - }, - Object { - "field": "icinga.main.message", - "highlights": Array [], - "value": "Sending 'Recovery' notification 'demo!load!mail-icingaadmin for user 'on-call'", - }, -] -`); + Array [ + Object { + "constant": "[Icinga][", + }, + Object { + "field": "icinga.main.facility", + "highlights": Array [], + "value": Array [ + "Notification", + ], + }, + Object { + "constant": "][", + }, + Object { + "field": "icinga.main.severity", + "highlights": Array [], + "value": Array [ + "information", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "icinga.main.message", + "highlights": Array [], + "value": Array [ + "Sending 'Recovery' notification 'demo!load!mail-icingaadmin for user 'on-call'", + ], + }, + ] + `); }); test('icinga startup log', () => { const flattenedDocument = { - 'event.dataset': 'icinga.startup', - 'fileset.module': 'icinga', - 'fileset.name': 'startup', - 'icinga.startup.facility': 'cli', - 'icinga.startup.message': 'Icinga application loader (version: r2.6.3-1)', - 'icinga.startup.severity': 'information', - 'input.type': 'log', - offset: 0, - 'prospector.type': 'log', + 'event.dataset': ['icinga.startup'], + 'fileset.module': ['icinga'], + 'fileset.name': ['startup'], + 'icinga.startup.facility': ['cli'], + 'icinga.startup.message': ['Icinga application loader (version: r2.6.3-1)'], + 'icinga.startup.severity': ['information'], + 'input.type': ['log'], + offset: [0], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[Icinga][", - }, - Object { - "field": "icinga.startup.facility", - "highlights": Array [], - "value": "cli", - }, - Object { - "constant": "][", - }, - Object { - "field": "icinga.startup.severity", - "highlights": Array [], - "value": "information", - }, - Object { - "constant": "] ", - }, - Object { - "field": "icinga.startup.message", - "highlights": Array [], - "value": "Icinga application loader (version: r2.6.3-1)", - }, -] -`); + Array [ + Object { + "constant": "[Icinga][", + }, + Object { + "field": "icinga.startup.facility", + "highlights": Array [], + "value": Array [ + "cli", + ], + }, + Object { + "constant": "][", + }, + Object { + "field": "icinga.startup.severity", + "highlights": Array [], + "value": Array [ + "information", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "icinga.startup.message", + "highlights": Array [], + "value": Array [ + "Icinga application loader (version: r2.6.3-1)", + ], + }, + ] + `); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_iis.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_iis.test.ts index 72449c03b63a..5238d5fe1da9 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_iis.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_iis.test.ts @@ -13,550 +13,622 @@ describe('Filebeat Rules', () => { describe('in ECS format', () => { test('iis access log', () => { const flattenedDocument = { - '@timestamp': '2018-01-01T10:11:12.000Z', - 'destination.address': '127.0.0.1', - 'destination.domain': 'example.com', - 'destination.ip': '127.0.0.1', - 'destination.port': 80, - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'iis.access', - 'event.duration': 789000000, - 'event.module': 'iis', - 'fileset.name': 'access', - 'http.request.body.bytes': 456, - 'http.request.method': 'GET', - 'http.request.referrer': '-', - 'http.response.body.bytes': 123, - 'http.response.status_code': 200, - 'http.version': '1.1', - 'iis.access.cookie': '-', - 'iis.access.server_name': 'MACHINE-NAME', - 'iis.access.site_name': 'W3SVC1', - 'iis.access.sub_status': 0, - 'iis.access.win32_status': 0, - 'input.type': 'log', - 'log.offset': 1204, - 'service.type': 'iis', - 'source.address': '85.181.35.98', - 'source.geo.city_name': 'Berlin', - 'source.geo.continent_name': 'Europe', - 'source.geo.country_iso_code': 'DE', - 'source.geo.location.lat': 52.4908, - 'source.geo.location.lon': 13.3275, - 'source.geo.region_iso_code': 'DE-BE', - 'source.geo.region_name': 'Land Berlin', - 'source.ip': '85.181.35.98', - 'url.path': '/', - 'url.query': 'q=100', - 'user.name': '-', - 'user_agent.device.name': 'Other', - 'user_agent.name': 'Chrome', - 'user_agent.original': + '@timestamp': ['2018-01-01T10:11:12.000Z'], + 'destination.address': ['127.0.0.1'], + 'destination.domain': ['example.com'], + 'destination.ip': ['127.0.0.1'], + 'destination.port': [80], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['iis.access'], + 'event.duration': [789000000], + 'event.module': ['iis'], + 'fileset.name': ['access'], + 'http.request.body.bytes': [456], + 'http.request.method': ['GET'], + 'http.request.referrer': ['-'], + 'http.response.body.bytes': [123], + 'http.response.status_code': [200], + 'http.version': ['1.1'], + 'iis.access.cookie': ['-'], + 'iis.access.server_name': ['MACHINE-NAME'], + 'iis.access.site_name': ['W3SVC1'], + 'iis.access.sub_status': [0], + 'iis.access.win32_status': [0], + 'input.type': ['log'], + 'log.offset': [1204], + 'service.type': ['iis'], + 'source.address': ['85.181.35.98'], + 'source.geo.city_name': ['Berlin'], + 'source.geo.continent_name': ['Europe'], + 'source.geo.country_iso_code': ['DE'], + 'source.geo.location.lat': [52.4908], + 'source.geo.location.lon': [13.3275], + 'source.geo.region_iso_code': ['DE-BE'], + 'source.geo.region_name': ['Land Berlin'], + 'source.ip': ['85.181.35.98'], + 'url.path': ['/'], + 'url.query': ['q=100'], + 'user.name': ['-'], + 'user_agent.device.name': ['Other'], + 'user_agent.name': ['Chrome'], + 'user_agent.original': [ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36', - 'user_agent.os.full': 'Mac OS X 10.14.0', - 'user_agent.os.name': 'Mac OS X', - 'user_agent.os.version': '10.14.0', - 'user_agent.version': '70.0.3538', + ], + 'user_agent.os.full': ['Mac OS X 10.14.0'], + 'user_agent.os.name': ['Mac OS X'], + 'user_agent.os.version': ['10.14.0'], + 'user_agent.version': ['70.0.3538'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[", - }, - Object { - "field": "event.module", - "highlights": Array [], - "value": "iis", - }, - Object { - "constant": "][access] ", - }, - Object { - "field": "source.ip", - "highlights": Array [], - "value": "85.181.35.98", - }, - Object { - "constant": " ", - }, - Object { - "field": "user.name", - "highlights": Array [], - "value": "-", - }, - Object { - "constant": " \\"", - }, - Object { - "field": "http.request.method", - "highlights": Array [], - "value": "GET", - }, - Object { - "constant": " ", - }, - Object { - "field": "url.path", - "highlights": Array [], - "value": "/", - }, - Object { - "constant": "?", - }, - Object { - "field": "url.query", - "highlights": Array [], - "value": "q=100", - }, - Object { - "constant": " HTTP/", - }, - Object { - "field": "http.version", - "highlights": Array [], - "value": "1.1", - }, - Object { - "constant": "\\" ", - }, - Object { - "field": "http.response.status_code", - "highlights": Array [], - "value": "200", - }, - Object { - "constant": " ", - }, - Object { - "field": "http.response.body.bytes", - "highlights": Array [], - "value": "123", - }, -] -`); + Array [ + Object { + "constant": "[", + }, + Object { + "field": "event.module", + "highlights": Array [], + "value": Array [ + "iis", + ], + }, + Object { + "constant": "][access] ", + }, + Object { + "field": "source.ip", + "highlights": Array [], + "value": Array [ + "85.181.35.98", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "user.name", + "highlights": Array [], + "value": Array [ + "-", + ], + }, + Object { + "constant": " \\"", + }, + Object { + "field": "http.request.method", + "highlights": Array [], + "value": Array [ + "GET", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "url.path", + "highlights": Array [], + "value": Array [ + "/", + ], + }, + Object { + "constant": "?", + }, + Object { + "field": "url.query", + "highlights": Array [], + "value": Array [ + "q=100", + ], + }, + Object { + "constant": " HTTP/", + }, + Object { + "field": "http.version", + "highlights": Array [], + "value": Array [ + "1.1", + ], + }, + Object { + "constant": "\\" ", + }, + Object { + "field": "http.response.status_code", + "highlights": Array [], + "value": Array [ + 200, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "http.response.body.bytes", + "highlights": Array [], + "value": Array [ + 123, + ], + }, + ] + `); }); test('iis 7.5 access log', () => { const flattenedDocument = { - '@timestamp': '2018-08-28T18:24:25.000Z', - 'destination.address': '10.100.220.70', - 'destination.ip': '10.100.220.70', - 'destination.port': 80, - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'iis.access', - 'event.duration': 792000000, - 'event.module': 'iis', - 'fileset.name': 'access', - 'http.request.method': 'GET', - 'http.response.status_code': 404, - 'iis.access.sub_status': 4, - 'iis.access.win32_status': 2, - 'input.type': 'log', - 'log.offset': 244, - 'service.type': 'iis', - 'source.address': '10.100.118.31', - 'source.ip': '10.100.118.31', - 'url.path': '/', - 'url.query': 'q=100', - 'user.name': '-', - 'user_agent.device.name': 'Other', - 'user_agent.name': 'IE', - 'user_agent.original': - 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR[ 2.0.50727](tel: 2050727); .NET CLR 3.0.30729)', - 'user_agent.os.name': 'Windows 8.1', - 'user_agent.version': '7.0', + '@timestamp': ['2018-08-28T18:24:25.000Z'], + 'destination.address': ['10.100.220.70'], + 'destination.ip': ['10.100.220.70'], + 'destination.port': [80], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['iis.access'], + 'event.duration': [792000000], + 'event.module': ['iis'], + 'fileset.name': ['access'], + 'http.request.method': ['GET'], + 'http.response.status_code': [404], + 'iis.access.sub_status': [4], + 'iis.access.win32_status': [2], + 'input.type': ['log'], + 'log.offset': [244], + 'service.type': ['iis'], + 'source.address': ['10.100.118.31'], + 'source.ip': ['10.100.118.31'], + 'url.path': ['/'], + 'url.query': ['q=100'], + 'user.name': ['-'], + 'user_agent.device.name': ['Other'], + 'user_agent.name': ['IE'], + 'user_agent.original': [ + 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR[ 2.0.50727](tel: [2050727); .NET CLR 3.0.30729)', + ], + 'user_agent.os.name': ['Windows 8.1'], + 'user_agent.version': ['7.0'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[", - }, - Object { - "field": "event.module", - "highlights": Array [], - "value": "iis", - }, - Object { - "constant": "][access] ", - }, - Object { - "field": "source.ip", - "highlights": Array [], - "value": "10.100.118.31", - }, - Object { - "constant": " ", - }, - Object { - "field": "user.name", - "highlights": Array [], - "value": "-", - }, - Object { - "constant": " \\"", - }, - Object { - "field": "http.request.method", - "highlights": Array [], - "value": "GET", - }, - Object { - "constant": " ", - }, - Object { - "field": "url.path", - "highlights": Array [], - "value": "/", - }, - Object { - "constant": "?", - }, - Object { - "field": "url.query", - "highlights": Array [], - "value": "q=100", - }, - Object { - "constant": " HTTP/", - }, - Object { - "field": "http.version", - "highlights": Array [], - "value": "undefined", - }, - Object { - "constant": "\\" ", - }, - Object { - "field": "http.response.status_code", - "highlights": Array [], - "value": "404", - }, - Object { - "constant": " ", - }, - Object { - "field": "http.response.body.bytes", - "highlights": Array [], - "value": "undefined", - }, -] -`); + Array [ + Object { + "constant": "[", + }, + Object { + "field": "event.module", + "highlights": Array [], + "value": Array [ + "iis", + ], + }, + Object { + "constant": "][access] ", + }, + Object { + "field": "source.ip", + "highlights": Array [], + "value": Array [ + "10.100.118.31", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "user.name", + "highlights": Array [], + "value": Array [ + "-", + ], + }, + Object { + "constant": " \\"", + }, + Object { + "field": "http.request.method", + "highlights": Array [], + "value": Array [ + "GET", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "url.path", + "highlights": Array [], + "value": Array [ + "/", + ], + }, + Object { + "constant": "?", + }, + Object { + "field": "url.query", + "highlights": Array [], + "value": Array [ + "q=100", + ], + }, + Object { + "constant": " HTTP/", + }, + Object { + "field": "http.version", + "highlights": Array [], + "value": Array [], + }, + Object { + "constant": "\\" ", + }, + Object { + "field": "http.response.status_code", + "highlights": Array [], + "value": Array [ + 404, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "http.response.body.bytes", + "highlights": Array [], + "value": Array [], + }, + ] + `); }); test('iis error log', () => { const flattenedDocument = { - '@timestamp': '2018-01-01T08:09:10.000Z', - 'destination.address': '172.31.77.6', - 'destination.ip': '172.31.77.6', - 'destination.port': 80, - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'iis.error', - 'event.module': 'iis', - 'fileset.name': 'error', - 'http.request.method': 'GET', - 'http.response.status_code': 503, - 'http.version': '1.1', - 'iis.error.queue_name': '-', - 'iis.error.reason_phrase': 'ConnLimit', - 'input.type': 'log', - 'log.offset': 186, - 'service.type': 'iis', - 'source.address': '172.31.77.6', - 'source.ip': '172.31.77.6', - 'source.port': 2094, - 'url.original': '/qos/1kbfile.txt', + '@timestamp': ['2018-01-01T08:09:10.000Z'], + 'destination.address': ['172.31.77.6'], + 'destination.ip': ['172.31.77.6'], + 'destination.port': [80], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['iis.error'], + 'event.module': ['iis'], + 'fileset.name': ['error'], + 'http.request.method': ['GET'], + 'http.response.status_code': [503], + 'http.version': ['1.1'], + 'iis.error.queue_name': ['-'], + 'iis.error.reason_phrase': ['ConnLimit'], + 'input.type': ['log'], + 'log.offset': [186], + 'service.type': ['iis'], + 'source.address': ['172.31.77.6'], + 'source.ip': ['172.31.77.6'], + 'source.port': [2094], + 'url.original': ['/qos/1kbfile.txt'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[iis][error] ", - }, - Object { - "field": "source.ip", - "highlights": Array [], - "value": "172.31.77.6", - }, - Object { - "constant": " ", - }, - Object { - "field": "iis.error.reason_phrase", - "highlights": Array [], - "value": "ConnLimit", - }, -] -`); + Array [ + Object { + "constant": "[iis][error] ", + }, + Object { + "field": "source.ip", + "highlights": Array [], + "value": Array [ + "172.31.77.6", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "iis.error.reason_phrase", + "highlights": Array [], + "value": Array [ + "ConnLimit", + ], + }, + ] + `); }); }); describe('in pre-ECS format', () => { test('iis access log', () => { const flattenedDocument = { - '@timestamp': '2018-01-01T08:09:10.000Z', - 'event.dataset': 'iis.access', - 'fileset.module': 'iis', - 'fileset.name': 'access', - 'iis.access.geoip.city_name': 'Berlin', - 'iis.access.geoip.continent_name': 'Europe', - 'iis.access.geoip.country_iso_code': 'DE', - 'iis.access.geoip.location.lat': 52.4908, - 'iis.access.geoip.location.lon': 13.3275, - 'iis.access.geoip.region_iso_code': 'DE-BE', - 'iis.access.geoip.region_name': 'Land Berlin', - 'iis.access.method': 'GET', - 'iis.access.port': '80', - 'iis.access.query_string': 'q=100', - 'iis.access.referrer': '-', - 'iis.access.remote_ip': '85.181.35.98', - 'iis.access.request_time_ms': '123', - 'iis.access.response_code': '200', - 'iis.access.server_ip': '127.0.0.1', - 'iis.access.sub_status': '0', - 'iis.access.url': '/', - 'iis.access.user_agent.device': 'Other', - 'iis.access.user_agent.major': '57', - 'iis.access.user_agent.minor': '0', - 'iis.access.user_agent.name': 'Firefox', - 'iis.access.user_agent.original': + '@timestamp': ['2018-01-01T08:09:10.000Z'], + 'event.dataset': ['iis.access'], + 'fileset.module': ['iis'], + 'fileset.name': ['access'], + 'iis.access.geoip.city_name': ['Berlin'], + 'iis.access.geoip.continent_name': ['Europe'], + 'iis.access.geoip.country_iso_code': ['DE'], + 'iis.access.geoip.location.lat': [52.4908], + 'iis.access.geoip.location.lon': [13.3275], + 'iis.access.geoip.region_iso_code': ['DE-BE'], + 'iis.access.geoip.region_name': ['Land Berlin'], + 'iis.access.method': ['GET'], + 'iis.access.port': ['80'], + 'iis.access.query_string': ['q=100'], + 'iis.access.referrer': ['-'], + 'iis.access.remote_ip': ['85.181.35.98'], + 'iis.access.request_time_ms': ['123'], + 'iis.access.response_code': ['200'], + 'iis.access.server_ip': ['127.0.0.1'], + 'iis.access.sub_status': ['0'], + 'iis.access.url': ['/'], + 'iis.access.user_agent.device': ['Other'], + 'iis.access.user_agent.major': ['57'], + 'iis.access.user_agent.minor': ['0'], + 'iis.access.user_agent.name': ['Firefox'], + 'iis.access.user_agent.original': [ 'Mozilla/5.0+(Windows+NT+6.1;+Win64;+x64;+rv:57.0)+Gecko/20100101+Firefox/57.0', - 'iis.access.user_agent.os': 'Windows', - 'iis.access.user_agent.os_name': 'Windows', - 'iis.access.user_name': '-', - 'iis.access.win32_status': '0', - 'input.type': 'log', - offset: 257, - 'prospector.type': 'log', + ], + 'iis.access.user_agent.os': ['Windows'], + 'iis.access.user_agent.os_name': ['Windows'], + 'iis.access.user_name': ['-'], + 'iis.access.win32_status': ['0'], + 'input.type': ['log'], + offset: [257], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[iis][access] ", - }, - Object { - "field": "iis.access.remote_ip", - "highlights": Array [], - "value": "85.181.35.98", - }, - Object { - "constant": " ", - }, - Object { - "field": "iis.access.user_name", - "highlights": Array [], - "value": "-", - }, - Object { - "constant": " \\"", - }, - Object { - "field": "iis.access.method", - "highlights": Array [], - "value": "GET", - }, - Object { - "constant": " ", - }, - Object { - "field": "iis.access.url", - "highlights": Array [], - "value": "/", - }, - Object { - "constant": " HTTP/", - }, - Object { - "field": "iis.access.http_version", - "highlights": Array [], - "value": "undefined", - }, - Object { - "constant": "\\" ", - }, - Object { - "field": "iis.access.response_code", - "highlights": Array [], - "value": "200", - }, - Object { - "constant": " ", - }, - Object { - "field": "iis.access.body_sent.bytes", - "highlights": Array [], - "value": "undefined", - }, -] -`); + Array [ + Object { + "constant": "[iis][access] ", + }, + Object { + "field": "iis.access.remote_ip", + "highlights": Array [], + "value": Array [ + "85.181.35.98", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "iis.access.user_name", + "highlights": Array [], + "value": Array [ + "-", + ], + }, + Object { + "constant": " \\"", + }, + Object { + "field": "iis.access.method", + "highlights": Array [], + "value": Array [ + "GET", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "iis.access.url", + "highlights": Array [], + "value": Array [ + "/", + ], + }, + Object { + "constant": " HTTP/", + }, + Object { + "field": "iis.access.http_version", + "highlights": Array [], + "value": Array [], + }, + Object { + "constant": "\\" ", + }, + Object { + "field": "iis.access.response_code", + "highlights": Array [], + "value": Array [ + "200", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "iis.access.body_sent.bytes", + "highlights": Array [], + "value": Array [], + }, + ] + `); }); test('iis 7.5 access log', () => { const flattenedDocument = { - '@timestamp': '2018-08-28T18:24:25.000Z', - 'event.dataset': 'iis.access', - 'fileset.module': 'iis', - 'fileset.name': 'access', - 'iis.access.method': 'GET', - 'iis.access.port': '80', - 'iis.access.query_string': '-', - 'iis.access.remote_ip': '10.100.118.31', - 'iis.access.request_time_ms': '792', - 'iis.access.response_code': '404', - 'iis.access.server_ip': '10.100.220.70', - 'iis.access.sub_status': '4', - 'iis.access.url': '/', - 'iis.access.user_agent.device': 'Other', - 'iis.access.user_agent.name': 'Other', - 'iis.access.user_agent.original': + '@timestamp': ['2018-08-28T18:24:25.000Z'], + 'event.dataset': ['iis.access'], + 'fileset.module': ['iis'], + 'fileset.name': ['access'], + 'iis.access.method': ['GET'], + 'iis.access.port': ['80'], + 'iis.access.query_string': ['-'], + 'iis.access.remote_ip': ['10.100.118.31'], + 'iis.access.request_time_ms': ['792'], + 'iis.access.response_code': ['404'], + 'iis.access.server_ip': ['10.100.220.70'], + 'iis.access.sub_status': ['4'], + 'iis.access.url': ['/'], + 'iis.access.user_agent.device': ['Other'], + 'iis.access.user_agent.name': ['Other'], + 'iis.access.user_agent.original': [ 'Mozilla/4.0+(compatible;+MSIE+7.0;+Windows+NT+6.3;+WOW64;+Trident/7.0;+.NET4.0E;+.NET4.0C;+.NET+CLR+3.5.30729;+.NET+CLR[+2.0.50727](tel:+2050727);+.NET+CLR+3.0.30729)', - 'iis.access.user_agent.os': 'Windows', - 'iis.access.user_agent.os_name': 'Windows', - 'iis.access.user_name': '-', - 'iis.access.win32_status': '2', - 'input.type': 'log', - offset: 244, - 'prospector.type': 'log', + ], + 'iis.access.user_agent.os': ['Windows'], + 'iis.access.user_agent.os_name': ['Windows'], + 'iis.access.user_name': ['-'], + 'iis.access.win32_status': ['2'], + 'input.type': ['log'], + offset: [244], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[iis][access] ", - }, - Object { - "field": "iis.access.remote_ip", - "highlights": Array [], - "value": "10.100.118.31", - }, - Object { - "constant": " ", - }, - Object { - "field": "iis.access.user_name", - "highlights": Array [], - "value": "-", - }, - Object { - "constant": " \\"", - }, - Object { - "field": "iis.access.method", - "highlights": Array [], - "value": "GET", - }, - Object { - "constant": " ", - }, - Object { - "field": "iis.access.url", - "highlights": Array [], - "value": "/", - }, - Object { - "constant": " HTTP/", - }, - Object { - "field": "iis.access.http_version", - "highlights": Array [], - "value": "undefined", - }, - Object { - "constant": "\\" ", - }, - Object { - "field": "iis.access.response_code", - "highlights": Array [], - "value": "404", - }, - Object { - "constant": " ", - }, - Object { - "field": "iis.access.body_sent.bytes", - "highlights": Array [], - "value": "undefined", - }, -] -`); + Array [ + Object { + "constant": "[iis][access] ", + }, + Object { + "field": "iis.access.remote_ip", + "highlights": Array [], + "value": Array [ + "10.100.118.31", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "iis.access.user_name", + "highlights": Array [], + "value": Array [ + "-", + ], + }, + Object { + "constant": " \\"", + }, + Object { + "field": "iis.access.method", + "highlights": Array [], + "value": Array [ + "GET", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "iis.access.url", + "highlights": Array [], + "value": Array [ + "/", + ], + }, + Object { + "constant": " HTTP/", + }, + Object { + "field": "iis.access.http_version", + "highlights": Array [], + "value": Array [], + }, + Object { + "constant": "\\" ", + }, + Object { + "field": "iis.access.response_code", + "highlights": Array [], + "value": Array [ + "404", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "iis.access.body_sent.bytes", + "highlights": Array [], + "value": Array [], + }, + ] + `); }); test('iis error log', () => { const flattenedDocument = { - '@timestamp': '2018-01-01T08:09:10.000Z', - 'event.dataset': 'iis.error', - 'fileset.module': 'iis', - 'fileset.name': 'error', - 'iis.error.http_version': '1.1', - 'iis.error.method': 'GET', - 'iis.error.queue_name': '-', - 'iis.error.reason_phrase': 'ConnLimit', - 'iis.error.remote_ip': '172.31.77.6', - 'iis.error.remote_port': '2094', - 'iis.error.response_code': '503', - 'iis.error.server_ip': '172.31.77.6', - 'iis.error.server_port': '80', - 'iis.error.url': '/qos/1kbfile.txt', - 'input.type': 'log', - offset: 186, - 'prospector.type': 'log', + '@timestamp': ['2018-01-01T08:09:10.000Z'], + 'event.dataset': ['iis.error'], + 'fileset.module': ['iis'], + 'fileset.name': ['error'], + 'iis.error.http_version': ['1.1'], + 'iis.error.method': ['GET'], + 'iis.error.queue_name': ['-'], + 'iis.error.reason_phrase': ['ConnLimit'], + 'iis.error.remote_ip': ['172.31.77.6'], + 'iis.error.remote_port': ['2094'], + 'iis.error.response_code': ['503'], + 'iis.error.server_ip': ['172.31.77.6'], + 'iis.error.server_port': ['80'], + 'iis.error.url': ['/qos/1kbfile.txt'], + 'input.type': ['log'], + offset: [186], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[iis][error] ", - }, - Object { - "field": "iis.error.remote_ip", - "highlights": Array [], - "value": "172.31.77.6", - }, - Object { - "constant": " \\"", - }, - Object { - "field": "iis.error.method", - "highlights": Array [], - "value": "GET", - }, - Object { - "constant": " ", - }, - Object { - "field": "iis.error.url", - "highlights": Array [], - "value": "/qos/1kbfile.txt", - }, - Object { - "constant": " HTTP/", - }, - Object { - "field": "iis.error.http_version", - "highlights": Array [], - "value": "1.1", - }, - Object { - "constant": "\\" ", - }, - Object { - "field": "iis.error.response_code", - "highlights": Array [], - "value": "503", - }, - Object { - "constant": " ", - }, - Object { - "field": "iis.error.reason_phrase", - "highlights": Array [], - "value": "ConnLimit", - }, -] -`); + Array [ + Object { + "constant": "[iis][error] ", + }, + Object { + "field": "iis.error.remote_ip", + "highlights": Array [], + "value": Array [ + "172.31.77.6", + ], + }, + Object { + "constant": " \\"", + }, + Object { + "field": "iis.error.method", + "highlights": Array [], + "value": Array [ + "GET", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "iis.error.url", + "highlights": Array [], + "value": Array [ + "/qos/1kbfile.txt", + ], + }, + Object { + "constant": " HTTP/", + }, + Object { + "field": "iis.error.http_version", + "highlights": Array [], + "value": Array [ + "1.1", + ], + }, + Object { + "constant": "\\" ", + }, + Object { + "field": "iis.error.response_code", + "highlights": Array [], + "value": Array [ + "503", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "iis.error.reason_phrase", + "highlights": Array [], + "value": Array [ + "ConnLimit", + ], + }, + ] + `); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_kafka.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_kafka.test.ts index 19cb5f6e3111..4ea3cec8e91f 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_kafka.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_kafka.test.ts @@ -13,48 +13,54 @@ describe('Filebeat Rules', () => { describe('in ECS format', () => { test('kafka log', () => { const flattenedDocument = { - '@timestamp': '2017-08-04T10:48:21.063Z', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'kafka.log', - 'event.module': 'kafka', - 'fileset.name': 'log', - 'input.type': 'log', - 'kafka.log.class': 'kafka.controller.KafkaController', - 'kafka.log.component': 'Controller 0', - 'log.level': 'INFO', - 'log.offset': 131, - message: '0 successfully elected as the controller', - 'service.type': 'kafka', + '@timestamp': ['2017-08-04T10:48:21.063Z'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['kafka.log'], + 'event.module': ['kafka'], + 'fileset.name': ['log'], + 'input.type': ['log'], + 'kafka.log.class': ['kafka.controller.KafkaController'], + 'kafka.log.component': ['Controller 0'], + 'log.level': ['INFO'], + 'log.offset': [131], + message: ['0 successfully elected as the controller'], + 'service.type': ['kafka'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[", - }, - Object { - "field": "event.dataset", - "highlights": Array [], - "value": "kafka.log", - }, - Object { - "constant": "][", - }, - Object { - "field": "log.level", - "highlights": Array [], - "value": "INFO", - }, - Object { - "constant": "] ", - }, - Object { - "field": "message", - "highlights": Array [], - "value": "0 successfully elected as the controller", - }, -] -`); + Array [ + Object { + "constant": "[", + }, + Object { + "field": "event.dataset", + "highlights": Array [], + "value": Array [ + "kafka.log", + ], + }, + Object { + "constant": "][", + }, + Object { + "field": "log.level", + "highlights": Array [], + "value": Array [ + "INFO", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "message", + "highlights": Array [], + "value": Array [ + "0 successfully elected as the controller", + ], + }, + ] + `); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_logstash.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_logstash.test.ts index edc534d9c345..022ea4921d9a 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_logstash.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_logstash.test.ts @@ -13,194 +13,256 @@ describe('Filebeat Rules', () => { describe('in ECS format', () => { test('logstash log', () => { const flattenedDocument = { - '@timestamp': '2017-10-23T14:20:12.046Z', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'logstash.log', - 'event.module': 'logstash', - 'fileset.name': 'log', - 'input.type': 'log', - 'log.level': 'INFO', - 'log.offset': 0, - 'logstash.log.module': 'logstash.modules.scaffold', - message: + '@timestamp': ['2017-10-23T14:20:12.046Z'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['logstash.log'], + 'event.module': ['logstash'], + 'fileset.name': ['log'], + 'input.type': ['log'], + 'log.level': ['INFO'], + 'log.offset': [0], + 'logstash.log.module': ['logstash.modules.scaffold'], + message: [ 'Initializing module {:module_name=>"fb_apache", :directory=>"/usr/share/logstash/modules/fb_apache/configuration"}', - 'service.type': 'logstash', + ], + 'service.type': ['logstash'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[", - }, - Object { - "field": "event.dataset", - "highlights": Array [], - "value": "logstash.log", - }, - Object { - "constant": "][", - }, - Object { - "field": "log.level", - "highlights": Array [], - "value": "INFO", - }, - Object { - "constant": "] ", - }, - Object { - "field": "message", - "highlights": Array [], - "value": "Initializing module {:module_name=>\\"fb_apache\\", :directory=>\\"/usr/share/logstash/modules/fb_apache/configuration\\"}", - }, -] -`); + Array [ + Object { + "constant": "[", + }, + Object { + "field": "event.dataset", + "highlights": Array [], + "value": Array [ + "logstash.log", + ], + }, + Object { + "constant": "][", + }, + Object { + "field": "log.level", + "highlights": Array [], + "value": Array [ + "INFO", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "message", + "highlights": Array [], + "value": Array [ + "Initializing module {:module_name=>\\"fb_apache\\", :directory=>\\"/usr/share/logstash/modules/fb_apache/configuration\\"}", + ], + }, + ] + `); }); test('logstash slowlog', () => { const flattenedDocument = { - '@timestamp': '2017-10-30T09:57:58.243Z', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'logstash.slowlog', - 'event.duration': 3027675106, - 'event.module': 'logstash', - 'fileset.name': 'slowlog', - 'input.type': 'log', - 'log.level': 'WARN', - 'log.offset': 0, - 'logstash.slowlog': { - event: - '"{\\"@version\\":\\"1\\",\\"@timestamp\\":\\"2017-10-30T13:57:55.130Z\\",\\"host\\":\\"sashimi\\",\\"sequence\\":0,\\"message\\":\\"Hello world!\\"}"', - module: 'slowlog.logstash.filters.sleep', - plugin_name: 'sleep', - plugin_params: - '{"time"=>3, "id"=>"e4e12a4e3082615c5427079bf4250dbfa338ebac10f8ea9912d7b98a14f56b8c"}', - plugin_type: 'filters', - took_in_millis: 3027, - }, - 'service.type': 'logstash', + '@timestamp': ['2017-10-30T09:57:58.243Z'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['logstash.slowlog'], + 'event.duration': [3027675106], + 'event.module': ['logstash'], + 'fileset.name': ['slowlog'], + 'input.type': ['log'], + 'log.level': ['WARN'], + 'log.offset': [0], + 'logstash.slowlog.event': [ + '"{\\"@version\\":\\"1\\",\\"@timestamp\\":\\"2017-10-30T13:57:55.130Z\\",\\"host\\":\\"sashimi\\",\\"sequence\\":0,\\"message\\":\\"Hello world!\\"}"', + ], + 'logstash.slowlog.module': ['slowlog.logstash.filters.sleep'], + 'logstash.slowlog.plugin_name': ['sleep'], + 'logstash.slowlog.plugin_params': [ + '{"time"=>3, "id"=>"e4e12a4e3082615c5427079bf4250dbfa338ebac10f8ea9912d7b98a14f56b8c"}', + ], + 'logstash.slowlog.plugin_type': ['filters'], + 'logstash.slowlog.took_in_millis': [3027], + 'service.type': ['logstash'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[Logstash][", - }, - Object { - "field": "log.level", - "highlights": Array [], - "value": "WARN", - }, - Object { - "constant": "] ", - }, - Object { - "field": "logstash.slowlog", - "highlights": Array [], - "value": "{\\"event\\":\\"\\\\\\"{\\\\\\\\\\\\\\"@version\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"1\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"@timestamp\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"2017-10-30T13:57:55.130Z\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"host\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"sashimi\\\\\\\\\\\\\\",\\\\\\\\\\\\\\"sequence\\\\\\\\\\\\\\":0,\\\\\\\\\\\\\\"message\\\\\\\\\\\\\\":\\\\\\\\\\\\\\"Hello world!\\\\\\\\\\\\\\"}\\\\\\"\\",\\"module\\":\\"slowlog.logstash.filters.sleep\\",\\"plugin_name\\":\\"sleep\\",\\"plugin_params\\":\\"{\\\\\\"time\\\\\\"=>3, \\\\\\"id\\\\\\"=>\\\\\\"e4e12a4e3082615c5427079bf4250dbfa338ebac10f8ea9912d7b98a14f56b8c\\\\\\"}\\",\\"plugin_type\\":\\"filters\\",\\"took_in_millis\\":3027}", - }, -] -`); + Array [ + Object { + "constant": "[Logstash][", + }, + Object { + "field": "log.level", + "highlights": Array [], + "value": Array [ + "WARN", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "logstash.slowlog.event", + "highlights": Array [], + "value": Array [ + "\\"{\\\\\\"@version\\\\\\":\\\\\\"1\\\\\\",\\\\\\"@timestamp\\\\\\":\\\\\\"2017-10-30T13:57:55.130Z\\\\\\",\\\\\\"host\\\\\\":\\\\\\"sashimi\\\\\\",\\\\\\"sequence\\\\\\":0,\\\\\\"message\\\\\\":\\\\\\"Hello world!\\\\\\"}\\"", + ], + }, + Object { + "field": "logstash.slowlog.module", + "highlights": Array [], + "value": Array [ + "slowlog.logstash.filters.sleep", + ], + }, + Object { + "field": "logstash.slowlog.plugin_name", + "highlights": Array [], + "value": Array [ + "sleep", + ], + }, + Object { + "field": "logstash.slowlog.plugin_params", + "highlights": Array [], + "value": Array [ + "{\\"time\\"=>3, \\"id\\"=>\\"e4e12a4e3082615c5427079bf4250dbfa338ebac10f8ea9912d7b98a14f56b8c\\"}", + ], + }, + Object { + "field": "logstash.slowlog.plugin_type", + "highlights": Array [], + "value": Array [ + "filters", + ], + }, + Object { + "field": "logstash.slowlog.took_in_millis", + "highlights": Array [], + "value": Array [ + 3027, + ], + }, + ] + `); }); }); describe('in pre-ECS format', () => { test('logstash log', () => { const flattenedDocument = { - '@timestamp': '2017-10-23T14:20:12.046Z', - 'event.dataset': 'logstash.log', - 'fileset.module': 'logstash', - 'fileset.name': 'log', - 'input.type': 'log', - 'logstash.log.level': 'INFO', - 'logstash.log.message': + '@timestamp': ['2017-10-23T14:20:12.046Z'], + 'event.dataset': ['logstash.log'], + 'fileset.module': ['logstash'], + 'fileset.name': ['log'], + 'input.type': ['log'], + 'logstash.log.level': ['INFO'], + 'logstash.log.message': [ 'Initializing module {:module_name=>"fb_apache", :directory=>"/usr/share/logstash/modules/fb_apache/configuration"}', - 'logstash.log.module': 'logstash.modules.scaffold', - offset: 0, - 'prospector.type': 'log', + ], + 'logstash.log.module': ['logstash.modules.scaffold'], + offset: [0], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[Logstash][", - }, - Object { - "field": "logstash.log.level", - "highlights": Array [], - "value": "INFO", - }, - Object { - "constant": "] ", - }, - Object { - "field": "logstash.log.module", - "highlights": Array [], - "value": "logstash.modules.scaffold", - }, - Object { - "constant": " - ", - }, - Object { - "field": "logstash.log.message", - "highlights": Array [], - "value": "Initializing module {:module_name=>\\"fb_apache\\", :directory=>\\"/usr/share/logstash/modules/fb_apache/configuration\\"}", - }, -] -`); + Array [ + Object { + "constant": "[Logstash][", + }, + Object { + "field": "logstash.log.level", + "highlights": Array [], + "value": Array [ + "INFO", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "logstash.log.module", + "highlights": Array [], + "value": Array [ + "logstash.modules.scaffold", + ], + }, + Object { + "constant": " - ", + }, + Object { + "field": "logstash.log.message", + "highlights": Array [], + "value": Array [ + "Initializing module {:module_name=>\\"fb_apache\\", :directory=>\\"/usr/share/logstash/modules/fb_apache/configuration\\"}", + ], + }, + ] + `); }); test('logstash slowlog', () => { const flattenedDocument = { - '@timestamp': '2017-10-30T09:57:58.243Z', - 'event.dataset': 'logstash.slowlog', - 'fileset.module': 'logstash', - 'fileset.name': 'slowlog', - 'input.type': 'log', - 'logstash.slowlog.event': + '@timestamp': ['2017-10-30T09:57:58.243Z'], + 'event.dataset': ['logstash.slowlog'], + 'fileset.module': ['logstash'], + 'fileset.name': ['slowlog'], + 'input.type': ['log'], + 'logstash.slowlog.event': [ '"{\\"@version\\":\\"1\\",\\"@timestamp\\":\\"2017-10-30T13:57:55.130Z\\",\\"host\\":\\"sashimi\\",\\"sequence\\":0,\\"message\\":\\"Hello world!\\"}"', - 'logstash.slowlog.level': 'WARN', - 'logstash.slowlog.message': + ], + 'logstash.slowlog.level': ['WARN'], + 'logstash.slowlog.message': [ 'event processing time {:plugin_params=>{"time"=>3, "id"=>"e4e12a4e3082615c5427079bf4250dbfa338ebac10f8ea9912d7b98a14f56b8c"}, :took_in_nanos=>3027675106, :took_in_millis=>3027, :event=>"{\\"@version\\":\\"1\\",\\"@timestamp\\":\\"2017-10-30T13:57:55.130Z\\",\\"host\\":\\"sashimi\\",\\"sequence\\":0,\\"message\\":\\"Hello world!\\"}"}', - 'logstash.slowlog.module': 'slowlog.logstash.filters.sleep', - 'logstash.slowlog.plugin_name': 'sleep', - 'logstash.slowlog.plugin_params': + ], + 'logstash.slowlog.module': ['slowlog.logstash.filters.sleep'], + 'logstash.slowlog.plugin_name': ['sleep'], + 'logstash.slowlog.plugin_params': [ '{"time"=>3, "id"=>"e4e12a4e3082615c5427079bf4250dbfa338ebac10f8ea9912d7b98a14f56b8c"}', - 'logstash.slowlog.plugin_type': 'filters', - 'logstash.slowlog.took_in_millis': 3027, - 'logstash.slowlog.took_in_nanos': 3027675106, - offset: 0, - 'prospector.type': 'log', + ], + 'logstash.slowlog.plugin_type': ['filters'], + 'logstash.slowlog.took_in_millis': [3027], + 'logstash.slowlog.took_in_nanos': [3027675106], + offset: [0], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[Logstash][", - }, - Object { - "field": "logstash.slowlog.level", - "highlights": Array [], - "value": "WARN", - }, - Object { - "constant": "] ", - }, - Object { - "field": "logstash.slowlog.module", - "highlights": Array [], - "value": "slowlog.logstash.filters.sleep", - }, - Object { - "constant": " - ", - }, - Object { - "field": "logstash.slowlog.message", - "highlights": Array [], - "value": "event processing time {:plugin_params=>{\\"time\\"=>3, \\"id\\"=>\\"e4e12a4e3082615c5427079bf4250dbfa338ebac10f8ea9912d7b98a14f56b8c\\"}, :took_in_nanos=>3027675106, :took_in_millis=>3027, :event=>\\"{\\\\\\"@version\\\\\\":\\\\\\"1\\\\\\",\\\\\\"@timestamp\\\\\\":\\\\\\"2017-10-30T13:57:55.130Z\\\\\\",\\\\\\"host\\\\\\":\\\\\\"sashimi\\\\\\",\\\\\\"sequence\\\\\\":0,\\\\\\"message\\\\\\":\\\\\\"Hello world!\\\\\\"}\\"}", - }, -] -`); + Array [ + Object { + "constant": "[Logstash][", + }, + Object { + "field": "logstash.slowlog.level", + "highlights": Array [], + "value": Array [ + "WARN", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "logstash.slowlog.module", + "highlights": Array [], + "value": Array [ + "slowlog.logstash.filters.sleep", + ], + }, + Object { + "constant": " - ", + }, + Object { + "field": "logstash.slowlog.message", + "highlights": Array [], + "value": Array [ + "event processing time {:plugin_params=>{\\"time\\"=>3, \\"id\\"=>\\"e4e12a4e3082615c5427079bf4250dbfa338ebac10f8ea9912d7b98a14f56b8c\\"}, :took_in_nanos=>3027675106, :took_in_millis=>3027, :event=>\\"{\\\\\\"@version\\\\\\":\\\\\\"1\\\\\\",\\\\\\"@timestamp\\\\\\":\\\\\\"2017-10-30T13:57:55.130Z\\\\\\",\\\\\\"host\\\\\\":\\\\\\"sashimi\\\\\\",\\\\\\"sequence\\\\\\":0,\\\\\\"message\\\\\\":\\\\\\"Hello world!\\\\\\"}\\"}", + ], + }, + ] + `); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_logstash.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_logstash.ts index 39b2058ca7cd..947146518367 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_logstash.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_logstash.ts @@ -34,7 +34,7 @@ export const filebeatLogstashRules = [ { // ECS when: { - exists: ['ecs.version', 'logstash.slowlog'], + all: [{ exists: ['ecs.version'] }, { existsPrefix: ['logstash.slowlog'] }], }, format: [ { @@ -47,7 +47,7 @@ export const filebeatLogstashRules = [ constant: '] ', }, { - field: 'logstash.slowlog', + fieldsPrefix: 'logstash.slowlog', }, ], }, diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_mongodb.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_mongodb.test.ts index 3df7ebec241c..108ec29f550d 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_mongodb.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_mongodb.test.ts @@ -13,40 +13,45 @@ describe('Filebeat Rules', () => { describe('in pre-ECS format', () => { test('mongodb log', () => { const flattenedDocument = { - '@timestamp': '2018-02-05T12:44:56.677Z', - 'event.dataset': 'mongodb.log', - 'fileset.module': 'mongodb', - 'fileset.name': 'log', - 'input.type': 'log', - 'mongodb.log.component': 'STORAGE', - 'mongodb.log.context': 'initandlisten', - 'mongodb.log.message': + '@timestamp': ['2018-02-05T12:44:56.677Z'], + 'event.dataset': ['mongodb.log'], + 'fileset.module': ['mongodb'], + 'fileset.name': ['log'], + 'input.type': ['log'], + 'mongodb.log.component': ['STORAGE'], + 'mongodb.log.context': ['initandlisten'], + 'mongodb.log.message': [ 'wiredtiger_open config: create,cache_size=8G,session_max=20000,eviction=(threads_max=4),config_base=false,statistics=(fast),log=(enabled=true,archive=true,path=journal,compressor=snappy),file_manager=(close_idle_time=100000),checkpoint=(wait=60,log_size=2GB),statistics_log=(wait=0),', - 'mongodb.log.severity': 'I', - offset: 281, - 'prospector.type': 'log', + ], + 'mongodb.log.severity': ['I'], + offset: [281], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[MongoDB][", - }, - Object { - "field": "mongodb.log.component", - "highlights": Array [], - "value": "STORAGE", - }, - Object { - "constant": "] ", - }, - Object { - "field": "mongodb.log.message", - "highlights": Array [], - "value": "wiredtiger_open config: create,cache_size=8G,session_max=20000,eviction=(threads_max=4),config_base=false,statistics=(fast),log=(enabled=true,archive=true,path=journal,compressor=snappy),file_manager=(close_idle_time=100000),checkpoint=(wait=60,log_size=2GB),statistics_log=(wait=0),", - }, -] -`); + Array [ + Object { + "constant": "[MongoDB][", + }, + Object { + "field": "mongodb.log.component", + "highlights": Array [], + "value": Array [ + "STORAGE", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "mongodb.log.message", + "highlights": Array [], + "value": Array [ + "wiredtiger_open config: create,cache_size=8G,session_max=20000,eviction=(threads_max=4),config_base=false,statistics=(fast),log=(enabled=true,archive=true,path=journal,compressor=snappy),file_manager=(close_idle_time=100000),checkpoint=(wait=60,log_size=2GB),statistics_log=(wait=0),", + ], + }, + ] + `); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_mysql.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_mysql.test.ts index 0329d53f92d0..99e83e960248 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_mysql.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_mysql.test.ts @@ -13,139 +13,158 @@ describe('Filebeat Rules', () => { describe('in ECS format', () => { test('mysql error log', () => { const flattenedDocument = { - '@timestamp': '2016-12-09T12:08:33.335Z', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'mysql.error', - 'event.module': 'mysql', - 'fileset.name': 'error', - 'input.type': 'log', - 'log.level': 'Warning', - 'log.offset': 92, - message: + '@timestamp': ['2016-12-09T12:08:33.335Z'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['mysql.error'], + 'event.module': ['mysql'], + 'fileset.name': ['error'], + 'input.type': ['log'], + 'log.level': ['Warning'], + 'log.offset': [92], + message: [ 'TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).', - 'mysql.thread_id': 0, - 'service.type': 'mysql', + ], + 'mysql.thread_id': [0], + 'service.type': ['mysql'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[", - }, - Object { - "field": "event.dataset", - "highlights": Array [], - "value": "mysql.error", - }, - Object { - "constant": "][", - }, - Object { - "field": "log.level", - "highlights": Array [], - "value": "Warning", - }, - Object { - "constant": "] ", - }, - Object { - "field": "message", - "highlights": Array [], - "value": "TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).", - }, -] -`); + Array [ + Object { + "constant": "[", + }, + Object { + "field": "event.dataset", + "highlights": Array [], + "value": Array [ + "mysql.error", + ], + }, + Object { + "constant": "][", + }, + Object { + "field": "log.level", + "highlights": Array [], + "value": Array [ + "Warning", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "message", + "highlights": Array [], + "value": Array [ + "TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).", + ], + }, + ] + `); }); test('mysql slowlog', () => { const flattenedDocument = { - '@timestamp': '2018-08-07T08:27:47.000Z', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'mysql.slowlog', - 'event.duration': 4071491000, - 'event.module': 'mysql', - 'fileset.name': 'slowlog', - 'input.type': 'log', + '@timestamp': ['2018-08-07T08:27:47.000Z'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['mysql.slowlog'], + 'event.duration': [4071491000], + 'event.module': ['mysql'], + 'fileset.name': ['slowlog'], + 'input.type': ['log'], 'log.flags': ['multiline'], - 'log.offset': 526, - 'mysql.slowlog.current_user': 'appuser', - 'mysql.slowlog.lock_time.sec': 0.000212, - 'mysql.slowlog.query': + 'log.offset': [526], + 'mysql.slowlog.current_user': ['appuser'], + 'mysql.slowlog.lock_time.sec': [0.000212], + 'mysql.slowlog.query': [ 'SELECT mcu.mcu_guid, mcu.cus_guid, mcu.mcu_url, mcu.mcu_crawlelements, mcu.mcu_order, GROUP_CONCAT(mca.mca_guid SEPARATOR ";") as mca_guid\n FROM kat_mailcustomerurl mcu, kat_customer cus, kat_mailcampaign mca\n WHERE cus.cus_guid = mcu.cus_guid\n AND cus.pro_code = \'CYB\'\n AND cus.cus_offline = 0\n AND mca.cus_guid = cus.cus_guid\n AND (mcu.mcu_date IS NULL OR mcu.mcu_date < CURDATE())\n AND mcu.mcu_crawlelements IS NOT NULL\n GROUP BY mcu.mcu_guid\n ORDER BY mcu.mcu_order ASC\n LIMIT 1000;', - 'mysql.slowlog.rows_examined': 1489615, - 'mysql.slowlog.rows_sent': 1000, - 'mysql.thread_id': 10997316, - 'service.type': 'mysql', - 'source.domain': 'apphost', - 'source.ip': '1.1.1.1', - 'user.name': 'appuser', + ], + 'mysql.slowlog.rows_examined': [1489615], + 'mysql.slowlog.rows_sent': [1000], + 'mysql.thread_id': [10997316], + 'service.type': ['mysql'], + 'source.domain': ['apphost'], + 'source.ip': ['1.1.1.1'], + 'user.name': ['appuser'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[MySQL][slowlog] ", - }, - Object { - "field": "user.name", - "highlights": Array [], - "value": "appuser", - }, - Object { - "constant": "@", - }, - Object { - "field": "source.domain", - "highlights": Array [], - "value": "apphost", - }, - Object { - "constant": " [", - }, - Object { - "field": "source.ip", - "highlights": Array [], - "value": "1.1.1.1", - }, - Object { - "constant": "] ", - }, - Object { - "constant": " - ", - }, - Object { - "field": "event.duration", - "highlights": Array [], - "value": "4071491000", - }, - Object { - "constant": " ns - ", - }, - Object { - "field": "mysql.slowlog.query", - "highlights": Array [], - "value": "SELECT mcu.mcu_guid, mcu.cus_guid, mcu.mcu_url, mcu.mcu_crawlelements, mcu.mcu_order, GROUP_CONCAT(mca.mca_guid SEPARATOR \\";\\") as mca_guid - FROM kat_mailcustomerurl mcu, kat_customer cus, kat_mailcampaign mca - WHERE cus.cus_guid = mcu.cus_guid - AND cus.pro_code = 'CYB' - AND cus.cus_offline = 0 - AND mca.cus_guid = cus.cus_guid - AND (mcu.mcu_date IS NULL OR mcu.mcu_date < CURDATE()) - AND mcu.mcu_crawlelements IS NOT NULL - GROUP BY mcu.mcu_guid - ORDER BY mcu.mcu_order ASC - LIMIT 1000;", - }, -] -`); + Array [ + Object { + "constant": "[MySQL][slowlog] ", + }, + Object { + "field": "user.name", + "highlights": Array [], + "value": Array [ + "appuser", + ], + }, + Object { + "constant": "@", + }, + Object { + "field": "source.domain", + "highlights": Array [], + "value": Array [ + "apphost", + ], + }, + Object { + "constant": " [", + }, + Object { + "field": "source.ip", + "highlights": Array [], + "value": Array [ + "1.1.1.1", + ], + }, + Object { + "constant": "] ", + }, + Object { + "constant": " - ", + }, + Object { + "field": "event.duration", + "highlights": Array [], + "value": Array [ + 4071491000, + ], + }, + Object { + "constant": " ns - ", + }, + Object { + "field": "mysql.slowlog.query", + "highlights": Array [], + "value": Array [ + "SELECT mcu.mcu_guid, mcu.cus_guid, mcu.mcu_url, mcu.mcu_crawlelements, mcu.mcu_order, GROUP_CONCAT(mca.mca_guid SEPARATOR \\";\\") as mca_guid + FROM kat_mailcustomerurl mcu, kat_customer cus, kat_mailcampaign mca + WHERE cus.cus_guid = mcu.cus_guid + AND cus.pro_code = 'CYB' + AND cus.cus_offline = 0 + AND mca.cus_guid = cus.cus_guid + AND (mcu.mcu_date IS NULL OR mcu.mcu_date < CURDATE()) + AND mcu.mcu_crawlelements IS NOT NULL + GROUP BY mcu.mcu_guid + ORDER BY mcu.mcu_order ASC + LIMIT 1000;", + ], + }, + ] + `); }); }); describe('in pre-ECS format', () => { test('mysql error log', () => { const errorDoc = { - 'mysql.error.message': + 'mysql.error.message': [ "Access denied for user 'petclinicdd'@'47.153.152.234' (using password: YES)", + ], }; const message = format(errorDoc, {}); expect(message).toEqual([ @@ -155,18 +174,18 @@ Array [ { field: 'mysql.error.message', highlights: [], - value: "Access denied for user 'petclinicdd'@'47.153.152.234' (using password: YES)", + value: ["Access denied for user 'petclinicdd'@'47.153.152.234' (using password: YES)"], }, ]); }); test('mysql slow log', () => { const errorDoc = { - 'mysql.slowlog.query': 'select * from hosts', - 'mysql.slowlog.query_time.sec': 5, - 'mysql.slowlog.user': 'admin', - 'mysql.slowlog.ip': '192.168.1.42', - 'mysql.slowlog.host': 'webserver-01', + 'mysql.slowlog.query': ['select * from hosts'], + 'mysql.slowlog.query_time.sec': [5], + 'mysql.slowlog.user': ['admin'], + 'mysql.slowlog.ip': ['192.168.1.42'], + 'mysql.slowlog.host': ['webserver-01'], }; const message = format(errorDoc, {}); expect(message).toEqual([ @@ -176,7 +195,7 @@ Array [ { field: 'mysql.slowlog.user', highlights: [], - value: 'admin', + value: ['admin'], }, { constant: '@', @@ -184,7 +203,7 @@ Array [ { field: 'mysql.slowlog.host', highlights: [], - value: 'webserver-01', + value: ['webserver-01'], }, { constant: ' [', @@ -192,7 +211,7 @@ Array [ { field: 'mysql.slowlog.ip', highlights: [], - value: '192.168.1.42', + value: ['192.168.1.42'], }, { constant: '] ', @@ -203,7 +222,7 @@ Array [ { field: 'mysql.slowlog.query_time.sec', highlights: [], - value: '5', + value: [5], }, { constant: ' s - ', @@ -211,7 +230,7 @@ Array [ { field: 'mysql.slowlog.query', highlights: [], - value: 'select * from hosts', + value: ['select * from hosts'], }, ]); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_nginx.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_nginx.test.ts index 0bc8ae1e907b..62f48007eb0e 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_nginx.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_nginx.test.ts @@ -13,252 +13,293 @@ describe('Filebeat Rules', () => { describe('in ECS format', () => { test('Nginx Access', () => { const flattenedDocument = { - '@timestamp': '2017-05-29T19:02:48.000Z', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'nginx.access', - 'event.module': 'nginx', - 'fileset.name': 'access', - 'http.request.method': 'GET', - 'http.request.referrer': '-', - 'http.response.body.bytes': 612, - 'http.response.status_code': 404, - 'http.version': '1.1', - 'input.type': 'log', - 'log.offset': 183, - 'service.type': 'nginx', - 'source.ip': '172.17.0.1', - 'url.original': '/stringpatch', - 'user.name': '-', - 'user_agent.device': 'Other', - 'user_agent.major': '15', - 'user_agent.minor': '0', - 'user_agent.name': 'Firefox Alpha', - 'user_agent.original': + '@timestamp': ['2017-05-29T19:02:48.000Z'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['nginx.access'], + 'event.module': ['nginx'], + 'fileset.name': ['access'], + 'http.request.method': ['GET'], + 'http.request.referrer': ['-'], + 'http.response.body.bytes': [612], + 'http.response.status_code': [404], + 'http.version': ['1.1'], + 'input.type': ['log'], + 'log.offset': [183], + 'service.type': ['nginx'], + 'source.ip': ['172.17.0.1'], + 'url.original': ['/stringpatch'], + 'user.name': ['-'], + 'user_agent.device': ['Other'], + 'user_agent.major': ['15'], + 'user_agent.minor': ['0'], + 'user_agent.name': ['Firefox Alpha'], + 'user_agent.original': [ 'Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20120716 Firefox/15.0a2', - 'user_agent.os.full_name': 'Windows 7', - 'user_agent.os.name': 'Windows 7', - 'user_agent.patch': 'a2', + ], + 'user_agent.os.full_name': ['Windows 7'], + 'user_agent.os.name': ['Windows 7'], + 'user_agent.patch': ['a2'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[", - }, - Object { - "field": "event.module", - "highlights": Array [], - "value": "nginx", - }, - Object { - "constant": "][access] ", - }, - Object { - "field": "source.ip", - "highlights": Array [], - "value": "172.17.0.1", - }, - Object { - "constant": " ", - }, - Object { - "field": "user.name", - "highlights": Array [], - "value": "-", - }, - Object { - "constant": " \\"", - }, - Object { - "field": "http.request.method", - "highlights": Array [], - "value": "GET", - }, - Object { - "constant": " ", - }, - Object { - "field": "url.original", - "highlights": Array [], - "value": "/stringpatch", - }, - Object { - "constant": " HTTP/", - }, - Object { - "field": "http.version", - "highlights": Array [], - "value": "1.1", - }, - Object { - "constant": "\\" ", - }, - Object { - "field": "http.response.status_code", - "highlights": Array [], - "value": "404", - }, - Object { - "constant": " ", - }, - Object { - "field": "http.response.body.bytes", - "highlights": Array [], - "value": "612", - }, -] -`); + Array [ + Object { + "constant": "[", + }, + Object { + "field": "event.module", + "highlights": Array [], + "value": Array [ + "nginx", + ], + }, + Object { + "constant": "][access] ", + }, + Object { + "field": "source.ip", + "highlights": Array [], + "value": Array [ + "172.17.0.1", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "user.name", + "highlights": Array [], + "value": Array [ + "-", + ], + }, + Object { + "constant": " \\"", + }, + Object { + "field": "http.request.method", + "highlights": Array [], + "value": Array [ + "GET", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "url.original", + "highlights": Array [], + "value": Array [ + "/stringpatch", + ], + }, + Object { + "constant": " HTTP/", + }, + Object { + "field": "http.version", + "highlights": Array [], + "value": Array [ + "1.1", + ], + }, + Object { + "constant": "\\" ", + }, + Object { + "field": "http.response.status_code", + "highlights": Array [], + "value": Array [ + 404, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "http.response.body.bytes", + "highlights": Array [], + "value": Array [ + 612, + ], + }, + ] + `); }); test('Nginx Error', () => { const flattenedDocument = { - '@timestamp': '2016-10-25T14:49:34.000Z', - 'ecs.version': '1.0.0-beta2', - 'event.dataset': 'nginx.error', - 'event.module': 'nginx', - 'fileset.name': 'error', - 'input.type': 'log', - 'log.level': 'error', - 'log.offset': 0, - message: + '@timestamp': ['2016-10-25T14:49:34.000Z'], + 'ecs.version': ['1.0.0-beta2'], + 'event.dataset': ['nginx.error'], + 'event.module': ['nginx'], + 'fileset.name': ['error'], + 'input.type': ['log'], + 'log.level': ['error'], + 'log.offset': [0], + message: [ 'open() "/usr/local/Cellar/nginx/1.10.2_1/html/favicon.ico" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "localhost:8080", referrer: "http://localhost:8080/"', - 'nginx.error.connection_id': 1, - 'process.pid': 54053, - 'process.thread.id': 0, - 'service.type': 'nginx', + ], + 'nginx.error.connection_id': [1], + 'process.pid': [54053], + 'process.thread.id': [0], + 'service.type': ['nginx'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[nginx]", - }, - Object { - "constant": "[", - }, - Object { - "field": "log.level", - "highlights": Array [], - "value": "error", - }, - Object { - "constant": "] ", - }, - Object { - "field": "message", - "highlights": Array [], - "value": "open() \\"/usr/local/Cellar/nginx/1.10.2_1/html/favicon.ico\\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \\"GET /favicon.ico HTTP/1.1\\", host: \\"localhost:8080\\", referrer: \\"http://localhost:8080/\\"", - }, -] -`); + Array [ + Object { + "constant": "[nginx]", + }, + Object { + "constant": "[", + }, + Object { + "field": "log.level", + "highlights": Array [], + "value": Array [ + "error", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "message", + "highlights": Array [], + "value": Array [ + "open() \\"/usr/local/Cellar/nginx/1.10.2_1/html/favicon.ico\\" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: \\"GET /favicon.ico HTTP/1.1\\", host: \\"localhost:8080\\", referrer: \\"http://localhost:8080/\\"", + ], + }, + ] + `); }); }); describe('in pre-ECS format', () => { test('Nginx Access', () => { const flattenedDocument = { - 'nginx.access': true, - 'nginx.access.remote_ip': '192.168.1.42', - 'nginx.access.user_name': 'admin', - 'nginx.access.method': 'GET', - 'nginx.access.url': '/faq', - 'nginx.access.http_version': '1.1', - 'nginx.access.body_sent.bytes': 1024, - 'nginx.access.response_code': 200, + 'nginx.access': [true], + 'nginx.access.remote_ip': ['192.168.1.42'], + 'nginx.access.user_name': ['admin'], + 'nginx.access.method': ['GET'], + 'nginx.access.url': ['/faq'], + 'nginx.access.http_version': ['1.1'], + 'nginx.access.body_sent.bytes': [1024], + 'nginx.access.response_code': [200], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[nginx][access] ", - }, - Object { - "field": "nginx.access.remote_ip", - "highlights": Array [], - "value": "192.168.1.42", - }, - Object { - "constant": " ", - }, - Object { - "field": "nginx.access.user_name", - "highlights": Array [], - "value": "admin", - }, - Object { - "constant": " \\"", - }, - Object { - "field": "nginx.access.method", - "highlights": Array [], - "value": "GET", - }, - Object { - "constant": " ", - }, - Object { - "field": "nginx.access.url", - "highlights": Array [], - "value": "/faq", - }, - Object { - "constant": " HTTP/", - }, - Object { - "field": "nginx.access.http_version", - "highlights": Array [], - "value": "1.1", - }, - Object { - "constant": "\\" ", - }, - Object { - "field": "nginx.access.response_code", - "highlights": Array [], - "value": "200", - }, - Object { - "constant": " ", - }, - Object { - "field": "nginx.access.body_sent.bytes", - "highlights": Array [], - "value": "1024", - }, -] -`); + Array [ + Object { + "constant": "[nginx][access] ", + }, + Object { + "field": "nginx.access.remote_ip", + "highlights": Array [], + "value": Array [ + "192.168.1.42", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "nginx.access.user_name", + "highlights": Array [], + "value": Array [ + "admin", + ], + }, + Object { + "constant": " \\"", + }, + Object { + "field": "nginx.access.method", + "highlights": Array [], + "value": Array [ + "GET", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "nginx.access.url", + "highlights": Array [], + "value": Array [ + "/faq", + ], + }, + Object { + "constant": " HTTP/", + }, + Object { + "field": "nginx.access.http_version", + "highlights": Array [], + "value": Array [ + "1.1", + ], + }, + Object { + "constant": "\\" ", + }, + Object { + "field": "nginx.access.response_code", + "highlights": Array [], + "value": Array [ + 200, + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "nginx.access.body_sent.bytes", + "highlights": Array [], + "value": Array [ + 1024, + ], + }, + ] + `); }); test('Nginx Error', () => { const flattenedDocument = { - 'nginx.error.message': + 'nginx.error.message': [ 'connect() failed (111: Connection refused) while connecting to upstream, client: 127.0.0.1, server: localhost, request: "GET /php-status?json= HTTP/1.1", upstream: "fastcgi://[::1]:9000", host: "localhost"', - 'nginx.error.level': 'error', + ], + 'nginx.error.level': ['error'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[nginx]", - }, - Object { - "constant": "[", - }, - Object { - "field": "nginx.error.level", - "highlights": Array [], - "value": "error", - }, - Object { - "constant": "] ", - }, - Object { - "field": "nginx.error.message", - "highlights": Array [], - "value": "connect() failed (111: Connection refused) while connecting to upstream, client: 127.0.0.1, server: localhost, request: \\"GET /php-status?json= HTTP/1.1\\", upstream: \\"fastcgi://[::1]:9000\\", host: \\"localhost\\"", - }, -] -`); + Array [ + Object { + "constant": "[nginx]", + }, + Object { + "constant": "[", + }, + Object { + "field": "nginx.error.level", + "highlights": Array [], + "value": Array [ + "error", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "nginx.error.message", + "highlights": Array [], + "value": Array [ + "connect() failed (111: Connection refused) while connecting to upstream, client: 127.0.0.1, server: localhost, request: \\"GET /php-status?json= HTTP/1.1\\", upstream: \\"fastcgi://[::1]:9000\\", host: \\"localhost\\"", + ], + }, + ] + `); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_osquery.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_osquery.test.ts index 8dc70053e202..513a9a8fcd91 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_osquery.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_osquery.test.ts @@ -13,65 +13,139 @@ describe('Filebeat Rules', () => { describe('in pre-ECS format', () => { test('osquery result log', () => { const flattenedDocument = { - '@timestamp': '2017-12-28T14:40:08.000Z', - 'event.dataset': 'osquery.result', - 'fileset.module': 'osquery', - 'fileset.name': 'result', - 'input.type': 'log', - offset: 0, - 'osquery.result.action': 'removed', - 'osquery.result.calendar_time': 'Thu Dec 28 14:40:08 2017 UTC', - 'osquery.result.columns': { - blocks: '122061322', - blocks_available: '75966945', - blocks_free: '121274885', - blocks_size: '4096', - device: '/dev/disk1s4', - device_alias: '/dev/disk1s4', - flags: '345018372', - inodes: '9223372036854775807', - inodes_free: '9223372036854775804', - path: '/private/var/vm', - type: 'apfs', - }, - 'osquery.result.counter': '1', - 'osquery.result.decorations.host_uuid': '4AB2906D-5516-5794-AF54-86D1D7F533F3', - 'osquery.result.decorations.username': 'tsg', - 'osquery.result.epoch': '0', - 'osquery.result.host_identifier': '192-168-0-4.rdsnet.ro', - 'osquery.result.name': 'pack_it-compliance_mounts', - 'osquery.result.unix_time': '1514472008', - 'prospector.type': 'log', + '@timestamp': ['2017-12-28T14:40:08.000Z'], + 'event.dataset': ['osquery.result'], + 'fileset.module': ['osquery'], + 'fileset.name': ['result'], + 'input.type': ['log'], + offset: [0], + 'osquery.result.action': ['removed'], + 'osquery.result.calendar_time': ['Thu Dec 28 14:40:08 2017 UTC'], + 'osquery.result.columns.blocks': ['122061322'], + 'osquery.result.columns.blocks_available': ['75966945'], + 'osquery.result.columns.blocks_free': ['121274885'], + 'osquery.result.columns.blocks_size': ['4096'], + 'osquery.result.columns.device': ['/dev/disk1s4'], + 'osquery.result.columns.device_alias': ['/dev/disk1s4'], + 'osquery.result.columns.flags': ['345018372'], + 'osquery.result.columns.inodes': ['9223372036854775807'], + 'osquery.result.columns.inodes_free': ['9223372036854775804'], + 'osquery.result.columns.path': ['/private/var/vm'], + 'osquery.result.columns.type': ['apfs'], + 'osquery.result.counter': ['1'], + 'osquery.result.decorations.host_uuid': ['4AB2906D-5516-5794-AF54-86D1D7F533F3'], + 'osquery.result.decorations.username': ['tsg'], + 'osquery.result.epoch': ['0'], + 'osquery.result.host_identifier': ['192-168-0-4.rdsnet.ro'], + 'osquery.result.name': ['pack_it-compliance_mounts'], + 'osquery.result.unix_time': ['1514472008'], + 'prospector.type': ['log'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[Osquery][", - }, - Object { - "field": "osquery.result.action", - "highlights": Array [], - "value": "removed", - }, - Object { - "constant": "] ", - }, - Object { - "field": "osquery.result.host_identifier", - "highlights": Array [], - "value": "192-168-0-4.rdsnet.ro", - }, - Object { - "constant": " ", - }, - Object { - "field": "osquery.result.columns", - "highlights": Array [], - "value": "{\\"blocks\\":\\"122061322\\",\\"blocks_available\\":\\"75966945\\",\\"blocks_free\\":\\"121274885\\",\\"blocks_size\\":\\"4096\\",\\"device\\":\\"/dev/disk1s4\\",\\"device_alias\\":\\"/dev/disk1s4\\",\\"flags\\":\\"345018372\\",\\"inodes\\":\\"9223372036854775807\\",\\"inodes_free\\":\\"9223372036854775804\\",\\"path\\":\\"/private/var/vm\\",\\"type\\":\\"apfs\\"}", - }, -] -`); + Array [ + Object { + "constant": "[Osquery][", + }, + Object { + "field": "osquery.result.action", + "highlights": Array [], + "value": Array [ + "removed", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "osquery.result.host_identifier", + "highlights": Array [], + "value": Array [ + "192-168-0-4.rdsnet.ro", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "osquery.result.columns.blocks", + "highlights": Array [], + "value": Array [ + "122061322", + ], + }, + Object { + "field": "osquery.result.columns.blocks_available", + "highlights": Array [], + "value": Array [ + "75966945", + ], + }, + Object { + "field": "osquery.result.columns.blocks_free", + "highlights": Array [], + "value": Array [ + "121274885", + ], + }, + Object { + "field": "osquery.result.columns.blocks_size", + "highlights": Array [], + "value": Array [ + "4096", + ], + }, + Object { + "field": "osquery.result.columns.device", + "highlights": Array [], + "value": Array [ + "/dev/disk1s4", + ], + }, + Object { + "field": "osquery.result.columns.device_alias", + "highlights": Array [], + "value": Array [ + "/dev/disk1s4", + ], + }, + Object { + "field": "osquery.result.columns.flags", + "highlights": Array [], + "value": Array [ + "345018372", + ], + }, + Object { + "field": "osquery.result.columns.inodes", + "highlights": Array [], + "value": Array [ + "9223372036854775807", + ], + }, + Object { + "field": "osquery.result.columns.inodes_free", + "highlights": Array [], + "value": Array [ + "9223372036854775804", + ], + }, + Object { + "field": "osquery.result.columns.path", + "highlights": Array [], + "value": Array [ + "/private/var/vm", + ], + }, + Object { + "field": "osquery.result.columns.type", + "highlights": Array [], + "value": Array [ + "apfs", + ], + }, + ] + `); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_osquery.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_osquery.ts index b3a6ee8c5cb4..638fd01d50c9 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_osquery.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_osquery.ts @@ -27,7 +27,7 @@ export const filebeatOsqueryRules = [ constant: ' ', }, { - field: 'osquery.result.columns', + fieldsPrefix: 'osquery.result.columns', }, ], }, diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_traefik.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_traefik.test.ts index b19124558fdd..d5d16f26a282 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_traefik.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/filebeat_traefik.test.ts @@ -13,112 +13,129 @@ describe('Filebeat Rules', () => { describe('in pre-ECS format', () => { test('traefik access log', () => { const flattenedDocument = { - '@timestamp': '2017-10-02T20:22:08.000Z', - 'event.dataset': 'traefik.access', - 'fileset.module': 'traefik', - 'fileset.name': 'access', - 'input.type': 'log', - offset: 280, - 'prospector.type': 'log', - 'traefik.access.backend_url': 'http://172.19.0.3:5601', - 'traefik.access.body_sent.bytes': 0, - 'traefik.access.duration': 3, - 'traefik.access.frontend_name': 'Host-host1', - 'traefik.access.geoip.city_name': 'Berlin', - 'traefik.access.geoip.continent_name': 'Europe', - 'traefik.access.geoip.country_iso_code': 'DE', - 'traefik.access.geoip.location.lat': 52.4908, - 'traefik.access.geoip.location.lon': 13.3275, - 'traefik.access.geoip.region_iso_code': 'DE-BE', - 'traefik.access.geoip.region_name': 'Land Berlin', - 'traefik.access.http_version': '1.1', - 'traefik.access.method': 'GET', - 'traefik.access.referrer': 'http://example.com/login', - 'traefik.access.remote_ip': '85.181.35.98', - 'traefik.access.request_count': 271, - 'traefik.access.response_code': '304', - 'traefik.access.url': '/ui/favicons/favicon.ico', - 'traefik.access.user_agent.device': 'Other', - 'traefik.access.user_agent.major': '61', - 'traefik.access.user_agent.minor': '0', - 'traefik.access.user_agent.name': 'Chrome', - 'traefik.access.user_agent.original': + '@timestamp': ['2017-10-02T20:22:08.000Z'], + 'event.dataset': ['traefik.access'], + 'fileset.module': ['traefik'], + 'fileset.name': ['access'], + 'input.type': ['log'], + offset: [280], + 'prospector.type': ['log'], + 'traefik.access.backend_url': ['http://172.19.0.3:5601'], + 'traefik.access.body_sent.bytes': [0], + 'traefik.access.duration': [3], + 'traefik.access.frontend_name': ['Host-host1'], + 'traefik.access.geoip.city_name': ['Berlin'], + 'traefik.access.geoip.continent_name': ['Europe'], + 'traefik.access.geoip.country_iso_code': ['DE'], + 'traefik.access.geoip.location.lat': [52.4908], + 'traefik.access.geoip.location.lon': [13.3275], + 'traefik.access.geoip.region_iso_code': ['DE-BE'], + 'traefik.access.geoip.region_name': ['Land Berlin'], + 'traefik.access.http_version': ['1.1'], + 'traefik.access.method': ['GET'], + 'traefik.access.referrer': ['http://example.com/login'], + 'traefik.access.remote_ip': ['85.181.35.98'], + 'traefik.access.request_count': [271], + 'traefik.access.response_code': ['304'], + 'traefik.access.url': ['/ui/favicons/favicon.ico'], + 'traefik.access.user_agent.device': ['Other'], + 'traefik.access.user_agent.major': ['61'], + 'traefik.access.user_agent.minor': ['0'], + 'traefik.access.user_agent.name': ['Chrome'], + 'traefik.access.user_agent.original': [ 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36', - 'traefik.access.user_agent.os': 'Linux', - 'traefik.access.user_agent.os_name': 'Linux', - 'traefik.access.user_agent.patch': '3163', - 'traefik.access.user_identifier': '-', - 'traefik.access.user_name': '-', + ], + 'traefik.access.user_agent.os': ['Linux'], + 'traefik.access.user_agent.os_name': ['Linux'], + 'traefik.access.user_agent.patch': ['3163'], + 'traefik.access.user_identifier': ['-'], + 'traefik.access.user_name': ['-'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[traefik][access] ", - }, - Object { - "field": "traefik.access.remote_ip", - "highlights": Array [], - "value": "85.181.35.98", - }, - Object { - "constant": " ", - }, - Object { - "field": "traefik.access.frontend_name", - "highlights": Array [], - "value": "Host-host1", - }, - Object { - "constant": " -> ", - }, - Object { - "field": "traefik.access.backend_url", - "highlights": Array [], - "value": "http://172.19.0.3:5601", - }, - Object { - "constant": " \\"", - }, - Object { - "field": "traefik.access.method", - "highlights": Array [], - "value": "GET", - }, - Object { - "constant": " ", - }, - Object { - "field": "traefik.access.url", - "highlights": Array [], - "value": "/ui/favicons/favicon.ico", - }, - Object { - "constant": " HTTP/", - }, - Object { - "field": "traefik.access.http_version", - "highlights": Array [], - "value": "1.1", - }, - Object { - "constant": "\\" ", - }, - Object { - "field": "traefik.access.response_code", - "highlights": Array [], - "value": "304", - }, - Object { - "constant": " ", - }, - Object { - "field": "traefik.access.body_sent.bytes", - "highlights": Array [], - "value": "0", - }, -] -`); + Array [ + Object { + "constant": "[traefik][access] ", + }, + Object { + "field": "traefik.access.remote_ip", + "highlights": Array [], + "value": Array [ + "85.181.35.98", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "traefik.access.frontend_name", + "highlights": Array [], + "value": Array [ + "Host-host1", + ], + }, + Object { + "constant": " -> ", + }, + Object { + "field": "traefik.access.backend_url", + "highlights": Array [], + "value": Array [ + "http://172.19.0.3:5601", + ], + }, + Object { + "constant": " \\"", + }, + Object { + "field": "traefik.access.method", + "highlights": Array [], + "value": Array [ + "GET", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "traefik.access.url", + "highlights": Array [], + "value": Array [ + "/ui/favicons/favicon.ico", + ], + }, + Object { + "constant": " HTTP/", + }, + Object { + "field": "traefik.access.http_version", + "highlights": Array [], + "value": Array [ + "1.1", + ], + }, + Object { + "constant": "\\" ", + }, + Object { + "field": "traefik.access.response_code", + "highlights": Array [], + "value": Array [ + "304", + ], + }, + Object { + "constant": " ", + }, + Object { + "field": "traefik.access.body_sent.bytes", + "highlights": Array [], + "value": Array [ + 0, + ], + }, + ] + `); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/generic.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/generic.test.ts index d168273626cf..eba0563be3aa 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/generic.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/generic.test.ts @@ -15,154 +15,174 @@ describe('Generic Rules', () => { describe('configurable message rules', () => { test('includes the event.dataset and log.level if present', () => { const flattenedDocument = { - '@timestamp': '2016-12-26T16:22:13.000Z', - 'event.dataset': 'generic.test', - 'log.level': 'TEST_LEVEL', - first_generic_message: 'TEST_MESSAGE', + '@timestamp': ['2016-12-26T16:22:13.000Z'], + 'event.dataset': ['generic.test'], + 'log.level': ['TEST_LEVEL'], + first_generic_message: ['TEST_MESSAGE'], }; const highlights = { first_generic_message: ['TEST'], }; expect(format(flattenedDocument, highlights)).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[", - }, - Object { - "field": "event.dataset", - "highlights": Array [], - "value": "generic.test", - }, - Object { - "constant": "][", - }, - Object { - "field": "log.level", - "highlights": Array [], - "value": "TEST_LEVEL", - }, - Object { - "constant": "] ", - }, - Object { - "field": "first_generic_message", - "highlights": Array [ - "TEST", - ], - "value": "TEST_MESSAGE", - }, -] -`); + Array [ + Object { + "constant": "[", + }, + Object { + "field": "event.dataset", + "highlights": Array [], + "value": Array [ + "generic.test", + ], + }, + Object { + "constant": "][", + }, + Object { + "field": "log.level", + "highlights": Array [], + "value": Array [ + "TEST_LEVEL", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "first_generic_message", + "highlights": Array [ + "TEST", + ], + "value": Array [ + "TEST_MESSAGE", + ], + }, + ] + `); }); test('includes the log.level if present', () => { const flattenedDocument = { - '@timestamp': '2016-12-26T16:22:13.000Z', - 'log.level': 'TEST_LEVEL', - first_generic_message: 'TEST_MESSAGE', + '@timestamp': ['2016-12-26T16:22:13.000Z'], + 'log.level': ['TEST_LEVEL'], + first_generic_message: ['TEST_MESSAGE'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[", - }, - Object { - "field": "log.level", - "highlights": Array [], - "value": "TEST_LEVEL", - }, - Object { - "constant": "] ", - }, - Object { - "field": "first_generic_message", - "highlights": Array [], - "value": "TEST_MESSAGE", - }, -] -`); + Array [ + Object { + "constant": "[", + }, + Object { + "field": "log.level", + "highlights": Array [], + "value": Array [ + "TEST_LEVEL", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "first_generic_message", + "highlights": Array [], + "value": Array [ + "TEST_MESSAGE", + ], + }, + ] + `); }); test('includes the message', () => { const firstFlattenedDocument = { - '@timestamp': '2016-12-26T16:22:13.000Z', - first_generic_message: 'FIRST_TEST_MESSAGE', + '@timestamp': ['2016-12-26T16:22:13.000Z'], + first_generic_message: ['FIRST_TEST_MESSAGE'], }; expect(format(firstFlattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "field": "first_generic_message", - "highlights": Array [], - "value": "FIRST_TEST_MESSAGE", - }, -] -`); + Array [ + Object { + "field": "first_generic_message", + "highlights": Array [], + "value": Array [ + "FIRST_TEST_MESSAGE", + ], + }, + ] + `); const secondFlattenedDocument = { - '@timestamp': '2016-12-26T16:22:13.000Z', - second_generic_message: 'SECOND_TEST_MESSAGE', + '@timestamp': ['2016-12-26T16:22:13.000Z'], + second_generic_message: ['SECOND_TEST_MESSAGE'], }; expect(format(secondFlattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "field": "second_generic_message", - "highlights": Array [], - "value": "SECOND_TEST_MESSAGE", - }, -] -`); + Array [ + Object { + "field": "second_generic_message", + "highlights": Array [], + "value": Array [ + "SECOND_TEST_MESSAGE", + ], + }, + ] + `); }); }); describe('log.original fallback', () => { test('includes the event.dataset if present', () => { const flattenedDocument = { - '@timestamp': '2016-12-26T16:22:13.000Z', - 'event.dataset': 'generic.test', - 'log.original': 'TEST_MESSAGE', + '@timestamp': ['2016-12-26T16:22:13.000Z'], + 'event.dataset': ['generic.test'], + 'log.original': ['TEST_MESSAGE'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "constant": "[", - }, - Object { - "field": "event.dataset", - "highlights": Array [], - "value": "generic.test", - }, - Object { - "constant": "] ", - }, - Object { - "field": "log.original", - "highlights": Array [], - "value": "TEST_MESSAGE", - }, -] -`); + Array [ + Object { + "constant": "[", + }, + Object { + "field": "event.dataset", + "highlights": Array [], + "value": Array [ + "generic.test", + ], + }, + Object { + "constant": "] ", + }, + Object { + "field": "log.original", + "highlights": Array [], + "value": Array [ + "TEST_MESSAGE", + ], + }, + ] + `); }); test('includes the original message', () => { const flattenedDocument = { - '@timestamp': '2016-12-26T16:22:13.000Z', - 'log.original': 'TEST_MESSAGE', + '@timestamp': ['2016-12-26T16:22:13.000Z'], + 'log.original': ['TEST_MESSAGE'], }; expect(format(flattenedDocument, {})).toMatchInlineSnapshot(` -Array [ - Object { - "field": "log.original", - "highlights": Array [], - "value": "TEST_MESSAGE", - }, -] -`); + Array [ + Object { + "field": "log.original", + "highlights": Array [], + "value": Array [ + "TEST_MESSAGE", + ], + }, + ] + `); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/helpers.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/helpers.ts index 9a6fa30e17e8..e925fab75d98 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/helpers.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/builtin_rules/helpers.ts @@ -10,3 +10,10 @@ export const labelField = (label: string, field: string) => [ { constant: '=' }, { field }, ]; + +export const labelFieldsPrefix = (label: string, fieldsPrefix: string) => [ + { constant: ' ' }, + { constant: label }, + { constant: '=' }, + { fieldsPrefix }, +]; diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/convert_document_source_to_log_item_fields.test.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/convert_document_source_to_log_item_fields.test.ts index 98d1e2cd89b0..7b79a1bf0386 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/convert_document_source_to_log_item_fields.test.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/convert_document_source_to_log_item_fields.test.ts @@ -4,66 +4,62 @@ * you may not use this file except in compliance with the Elastic License. */ -import { convertDocumentSourceToLogItemFields } from './convert_document_source_to_log_item_fields'; +import { convertESFieldsToLogItemFields } from './convert_document_source_to_log_item_fields'; -describe('convertDocumentSourceToLogItemFields', () => { - test('should convert document', () => { - const doc = { - agent: { - hostname: 'demo-stack-client-01', - id: '7adef8b6-2ab7-45cd-a0d5-b3baad735f1b', - type: 'filebeat', - ephemeral_id: 'a0c8164b-3564-4e32-b0bf-f4db5a7ae566', - version: '7.0.0', - }, +describe('convertESFieldsToLogItemFields', () => { + test('Converts the fields collection to LogItemFields', () => { + const esFields = { + 'agent.hostname': ['demo-stack-client-01'], + 'agent.id': ['7adef8b6-2ab7-45cd-a0d5-b3baad735f1b'], + 'agent.type': ['filebeat'], + 'agent.ephemeral_id': ['a0c8164b-3564-4e32-b0bf-f4db5a7ae566'], + 'agent.version': ['7.0.0'], tags: ['prod', 'web'], metadata: [ { key: 'env', value: 'prod' }, { key: 'stack', value: 'web' }, ], - host: { - hostname: 'packer-virtualbox-iso-1546820004', - name: 'demo-stack-client-01', - }, + 'host.hostname': ['packer-virtualbox-iso-1546820004'], + 'host.name': ['demo-stack-client-01'], }; - const fields = convertDocumentSourceToLogItemFields(doc); + const fields = convertESFieldsToLogItemFields(esFields); expect(fields).toEqual([ { field: 'agent.hostname', - value: 'demo-stack-client-01', + value: ['demo-stack-client-01'], }, { field: 'agent.id', - value: '7adef8b6-2ab7-45cd-a0d5-b3baad735f1b', + value: ['7adef8b6-2ab7-45cd-a0d5-b3baad735f1b'], }, { field: 'agent.type', - value: 'filebeat', + value: ['filebeat'], }, { field: 'agent.ephemeral_id', - value: 'a0c8164b-3564-4e32-b0bf-f4db5a7ae566', + value: ['a0c8164b-3564-4e32-b0bf-f4db5a7ae566'], }, { field: 'agent.version', - value: '7.0.0', + value: ['7.0.0'], }, { field: 'tags', - value: '["prod","web"]', + value: ['prod', 'web'], }, { field: 'metadata', - value: '[{"key":"env","value":"prod"},{"key":"stack","value":"web"}]', + value: ['{"key":"env","value":"prod"}', '{"key":"stack","value":"web"}'], }, { field: 'host.hostname', - value: 'packer-virtualbox-iso-1546820004', + value: ['packer-virtualbox-iso-1546820004'], }, { field: 'host.name', - value: 'demo-stack-client-01', + value: ['demo-stack-client-01'], }, ]); }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/convert_document_source_to_log_item_fields.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/convert_document_source_to_log_item_fields.ts index 7c8560d72ff9..a1d855bfdaa4 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/convert_document_source_to_log_item_fields.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/convert_document_source_to_log_item_fields.ts @@ -5,39 +5,21 @@ */ import stringify from 'json-stable-stringify'; -import { isArray, isPlainObject } from 'lodash'; - -import { JsonObject } from '../../../../common/typed_json'; import { LogEntriesItemField } from '../../../../common/http_api'; +import { JsonArray } from '../../../../common/typed_json'; -const isJsonObject = (subject: any): subject is JsonObject => { - return isPlainObject(subject); +const serializeValue = (value: JsonArray): string[] => { + return value.map((v) => { + if (typeof v === 'object' && v != null) { + return stringify(v); + } else { + return `${v}`; + } + }); }; -const serializeValue = (value: any): string => { - if (isArray(value) || isPlainObject(value)) { - return stringify(value); - } - return `${value}`; -}; export const convertESFieldsToLogItemFields = (fields: { - [field: string]: [value: unknown]; + [field: string]: JsonArray; }): LogEntriesItemField[] => { - return Object.keys(fields).map((field) => ({ field, value: serializeValue(fields[field][0]) })); -}; - -export const convertDocumentSourceToLogItemFields = ( - source: JsonObject, - path: string[] = [], - fields: LogEntriesItemField[] = [] -): LogEntriesItemField[] => { - return Object.keys(source).reduce((acc, key) => { - const value = source[key]; - const nextPath = [...path, key]; - if (isJsonObject(value)) { - return convertDocumentSourceToLogItemFields(value, nextPath, acc); - } - const field = { field: nextPath.join('.'), value: serializeValue(value) }; - return [...acc, field]; - }, fields); + return Object.keys(fields).map((field) => ({ field, value: serializeValue(fields[field]) })); }; diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts index e211f72b4e07..cc9d4c749c77 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts @@ -7,7 +7,7 @@ import { sortBy } from 'lodash'; import { RequestHandlerContext } from 'src/core/server'; -import { JsonObject } from '../../../../common/typed_json'; +import { JsonArray, JsonObject } from '../../../../common/typed_json'; import { LogEntriesSummaryBucket, LogEntriesSummaryHighlightsBucket, @@ -163,8 +163,8 @@ export class InfraLogEntriesDomain { return { columnId: column.fieldColumn.id, field: column.fieldColumn.field, - value: doc.fields[column.fieldColumn.field], - highlights: doc.highlights[column.fieldColumn.field] || [], + value: doc.fields[column.fieldColumn.field] ?? [], + highlights: doc.highlights[column.fieldColumn.field] ?? [], }; } } @@ -252,8 +252,8 @@ export class InfraLogEntriesDomain { ): Promise { const document = await this.adapter.getLogItem(requestContext, id, sourceConfiguration); const defaultFields = [ - { field: '_index', value: document._index }, - { field: '_id', value: document._id }, + { field: '_index', value: [document._index] }, + { field: '_id', value: [document._id] }, ]; return { @@ -310,10 +310,10 @@ export class InfraLogEntriesDomain { } } -interface LogItemHit { +export interface LogItemHit { _index: string; _id: string; - fields: { [field: string]: [value: unknown] }; + fields: { [field: string]: [value: JsonArray] }; sort: [number, number]; } @@ -400,9 +400,9 @@ const createHighlightQueryDsl = (phrase: string, fields: string[]) => ({ const getContextFromDoc = (doc: LogEntryDocument): LogEntry['context'] => { // Get all context fields, then test for the presence and type of the ones that go together - const containerId = doc.fields['container.id']; - const hostName = doc.fields['host.name']; - const logFilePath = doc.fields['log.file.path']; + const containerId = doc.fields['container.id']?.[0]; + const hostName = doc.fields['host.name']?.[0]; + const logFilePath = doc.fields['log.file.path']?.[0]; if (typeof containerId === 'string') { return { 'container.id': containerId }; diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/message.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/message.ts index b8cadaa06f61..f9775e127088 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/message.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/message.ts @@ -4,11 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import stringify from 'json-stable-stringify'; - -import { InfraLogMessageSegment } from '../../../graphql/types'; +import { LogMessagePart } from '../../../../common/http_api/log_entries'; +import { JsonArray, JsonValue } from '../../../../common/typed_json'; import { LogMessageFormattingCondition, + LogMessageFormattingFieldValueConditionValue, LogMessageFormattingInstruction, LogMessageFormattingRule, } from './rule_types'; @@ -30,7 +30,7 @@ export function compileFormattingRules( ) ) ), - format(fields, highlights): InfraLogMessageSegment[] { + format(fields, highlights): LogMessagePart[] { for (const compiledRule of compiledRules) { if (compiledRule.fulfillsCondition(fields)) { return compiledRule.format(fields, highlights); @@ -59,16 +59,34 @@ const compileRule = (rule: LogMessageFormattingRule): CompiledLogMessageFormatti const compileCondition = ( condition: LogMessageFormattingCondition ): CompiledLogMessageFormattingCondition => - [compileExistsCondition, compileFieldValueCondition].reduce( - (compiledCondition, compile) => compile(condition) || compiledCondition, - catchAllCondition - ); + [ + compileAllCondition, + compileExistsCondition, + compileExistsPrefixCondition, + compileFieldValueCondition, + ].reduce((compiledCondition, compile) => compile(condition) || compiledCondition, falseCondition); -const catchAllCondition: CompiledLogMessageFormattingCondition = { +const falseCondition: CompiledLogMessageFormattingCondition = { conditionFields: [] as string[], fulfillsCondition: () => false, }; +const compileAllCondition = ( + condition: LogMessageFormattingCondition +): CompiledLogMessageFormattingCondition | null => { + if (!('all' in condition)) { + return null; + } + + const compiledConditions = condition.all.map(compileCondition); + + return { + conditionFields: compiledConditions.flatMap(({ conditionFields }) => conditionFields), + fulfillsCondition: (fields: Fields) => + compiledConditions.every(({ fulfillsCondition }) => fulfillsCondition(fields)), + }; +}; + const compileExistsCondition = (condition: LogMessageFormattingCondition) => 'exists' in condition ? { @@ -78,13 +96,24 @@ const compileExistsCondition = (condition: LogMessageFormattingCondition) => } : null; +const compileExistsPrefixCondition = (condition: LogMessageFormattingCondition) => + 'existsPrefix' in condition + ? { + conditionFields: condition.existsPrefix.map((prefix) => `${prefix}.*`), + fulfillsCondition: (fields: Fields) => + condition.existsPrefix.every((fieldNamePrefix) => + Object.keys(fields).some((field) => field.startsWith(`${fieldNamePrefix}.`)) + ), + } + : null; + const compileFieldValueCondition = (condition: LogMessageFormattingCondition) => 'values' in condition ? { conditionFields: Object.keys(condition.values), fulfillsCondition: (fields: Fields) => - Object.entries(condition.values).every( - ([fieldName, expectedValue]) => fields[fieldName] === expectedValue + Object.entries(condition.values).every(([fieldName, expectedValue]) => + equalsOrContains(fields[fieldName] ?? [], expectedValue) ), } : null; @@ -116,7 +145,11 @@ const compileFormattingInstructions = ( const compileFormattingInstruction = ( formattingInstruction: LogMessageFormattingInstruction ): CompiledLogMessageFormattingInstruction => - [compileFieldReferenceFormattingInstruction, compileConstantFormattingInstruction].reduce( + [ + compileFieldReferenceFormattingInstruction, + compileFieldsPrefixReferenceFormattingInstruction, + compileConstantFormattingInstruction, + ].reduce( (compiledFormattingInstruction, compile) => compile(formattingInstruction) || compiledFormattingInstruction, catchAllFormattingInstruction @@ -138,19 +171,44 @@ const compileFieldReferenceFormattingInstruction = ( ? { formattingFields: [formattingInstruction.field], format: (fields, highlights) => { - const value = fields[formattingInstruction.field]; - const highlightedValues = highlights[formattingInstruction.field]; + const value = fields[formattingInstruction.field] ?? []; + const highlightedValues = highlights[formattingInstruction.field] ?? []; return [ { field: formattingInstruction.field, - value: typeof value === 'object' ? stringify(value) : `${value}`, - highlights: highlightedValues || [], + value, + highlights: highlightedValues, }, ]; }, } : null; +const compileFieldsPrefixReferenceFormattingInstruction = ( + formattingInstruction: LogMessageFormattingInstruction +): CompiledLogMessageFormattingInstruction | null => + 'fieldsPrefix' in formattingInstruction + ? { + formattingFields: [`${formattingInstruction.fieldsPrefix}.*`], + format: (fields, highlights) => { + const matchingFields = Object.keys(fields).filter((field) => + field.startsWith(`${formattingInstruction.fieldsPrefix}.`) + ); + return matchingFields.flatMap((field) => { + const value = fields[field] ?? []; + const highlightedValues = highlights[field] ?? []; + return [ + { + field, + value, + highlights: highlightedValues, + }, + ]; + }); + }, + } + : null; + const compileConstantFormattingInstruction = ( formattingInstruction: LogMessageFormattingInstruction ): CompiledLogMessageFormattingInstruction | null => @@ -165,8 +223,21 @@ const compileConstantFormattingInstruction = ( } : null; +const equalsOrContains = ( + operand: JsonValue, + value: LogMessageFormattingFieldValueConditionValue +): boolean => { + if (Array.isArray(operand)) { + return operand.includes(value); + } else if (typeof operand === 'object' && operand !== null) { + return Object.values(operand).includes(value); + } else { + return operand === value; + } +}; + export interface Fields { - [fieldName: string]: string | number | object | boolean | null; + [fieldName: string]: JsonArray; } export interface Highlights { @@ -176,7 +247,7 @@ export interface Highlights { export interface CompiledLogMessageFormattingRule { requiredFields: string[]; fulfillsCondition(fields: Fields): boolean; - format(fields: Fields, highlights: Highlights): InfraLogMessageSegment[]; + format(fields: Fields, highlights: Highlights): LogMessagePart[]; } export interface CompiledLogMessageFormattingCondition { @@ -186,5 +257,5 @@ export interface CompiledLogMessageFormattingCondition { export interface CompiledLogMessageFormattingInstruction { formattingFields: string[]; - format(fields: Fields, highlights: Highlights): InfraLogMessageSegment[]; + format(fields: Fields, highlights: Highlights): LogMessagePart[]; } diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/rule_types.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/rule_types.ts index 6107fc362f8e..4569f4b8e8a9 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/rule_types.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/rule_types.ts @@ -4,33 +4,52 @@ * you may not use this file except in compliance with the Elastic License. */ +import { JsonValue } from '../../../../common/typed_json'; + export interface LogMessageFormattingRule { when: LogMessageFormattingCondition; format: LogMessageFormattingInstruction[]; } export type LogMessageFormattingCondition = + | LogMessageFormattingAllCondition | LogMessageFormattingExistsCondition + | LogMessageFormattingExistsPrefixCondition | LogMessageFormattingFieldValueCondition; +export interface LogMessageFormattingAllCondition { + all: LogMessageFormattingCondition[]; +} + export interface LogMessageFormattingExistsCondition { exists: string[]; } +export interface LogMessageFormattingExistsPrefixCondition { + existsPrefix: string[]; +} + export interface LogMessageFormattingFieldValueCondition { values: { - [fieldName: string]: string | number | boolean | null; + [fieldName: string]: LogMessageFormattingFieldValueConditionValue; }; } +export type LogMessageFormattingFieldValueConditionValue = JsonValue; + export type LogMessageFormattingInstruction = | LogMessageFormattingFieldReference + | LogMessageFormattingFieldsPrefixReference | LogMessageFormattingConstant; export interface LogMessageFormattingFieldReference { field: string; } +export interface LogMessageFormattingFieldsPrefixReference { + fieldsPrefix: string; +} + export interface LogMessageFormattingConstant { constant: string; } diff --git a/x-pack/plugins/ingest_manager/common/services/is_valid_namespace.ts b/x-pack/plugins/ingest_manager/common/services/is_valid_namespace.ts index 43aa64f67726..8bd8349580ed 100644 --- a/x-pack/plugins/ingest_manager/common/services/is_valid_namespace.ts +++ b/x-pack/plugins/ingest_manager/common/services/is_valid_namespace.ts @@ -12,26 +12,23 @@ export function isValidNamespace(namespace: string): { valid: boolean; error?: s if (!namespace.trim()) { return { valid: false, - error: i18n.translate('xpack.ingestManager.namespaceValidation.requiredErrorMessage', { + error: i18n.translate('xpack.fleet.namespaceValidation.requiredErrorMessage', { defaultMessage: 'Namespace is required', }), }; } else if (namespace !== namespace.toLowerCase()) { return { valid: false, - error: i18n.translate('xpack.ingestManager.namespaceValidation.lowercaseErrorMessage', { + error: i18n.translate('xpack.fleet.namespaceValidation.lowercaseErrorMessage', { defaultMessage: 'Namespace must be lowercase', }), }; } else if (/[\*\\/\?"<>|\s,#:]+/.test(namespace)) { return { valid: false, - error: i18n.translate( - 'xpack.ingestManager.namespaceValidation.invalidCharactersErrorMessage', - { - defaultMessage: 'Namespace contains invalid characters', - } - ), + error: i18n.translate('xpack.fleet.namespaceValidation.invalidCharactersErrorMessage', { + defaultMessage: 'Namespace contains invalid characters', + }), }; } // Node.js doesn't have Blob, and browser doesn't have Buffer :) @@ -41,7 +38,7 @@ export function isValidNamespace(namespace: string): { valid: boolean; error?: s ) { return { valid: false, - error: i18n.translate('xpack.ingestManager.namespaceValidation.tooLongErrorMessage', { + error: i18n.translate('xpack.fleet.namespaceValidation.tooLongErrorMessage', { defaultMessage: 'Namespace cannot be more than 100 bytes', }), }; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_flyout.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_flyout.tsx index e321dfb1826f..a6a162dbdeaf 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_flyout.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_flyout.tsx @@ -27,7 +27,7 @@ export const AlphaFlyout: React.FunctionComponent = ({ onClose }) => {

    @@ -37,13 +37,13 @@ export const AlphaFlyout: React.FunctionComponent = ({ onClose }) => {

    = ({ onClose }) => { target="_blank" > @@ -61,7 +61,7 @@ export const AlphaFlyout: React.FunctionComponent = ({ onClose }) => { forumLink: ( @@ -74,7 +74,7 @@ export const AlphaFlyout: React.FunctionComponent = ({ onClose }) => { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_messaging.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_messaging.tsx index 62158483518d..e39d07eec395 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_messaging.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_messaging.tsx @@ -26,20 +26,17 @@ export const AlphaMessaging: React.FC<{}> = () => {

    - + {' – '} {' '} setIsAlphaFlyoutOpen(true)}> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/context_menu_actions.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/context_menu_actions.tsx index 7d1f12447340..29e42363e986 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/context_menu_actions.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/context_menu_actions.tsx @@ -63,7 +63,7 @@ export const ContextMenuActions = React.memo(({ button, onChange, isOpen, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/enrollment_instructions/manual/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/enrollment_instructions/manual/index.tsx index a24640af7438..343ddfab23c7 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/enrollment_instructions/manual/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/enrollment_instructions/manual/index.tsx @@ -38,7 +38,7 @@ export const ManualInstructions: React.FunctionComponent = ({ <> @@ -46,7 +46,7 @@ export const ManualInstructions: React.FunctionComponent = ({

    @@ -59,7 +59,7 @@ export const ManualInstructions: React.FunctionComponent = ({

    @@ -71,7 +71,7 @@ export const ManualInstructions: React.FunctionComponent = ({ = ({ href="https://www.elastic.co/guide/en/ingest-management/current/elastic-agent-installation-configuration.html" > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_directory_header_link.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_directory_header_link.tsx index 2fd99a88c3c8..88759791a530 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_directory_header_link.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_directory_header_link.tsx @@ -33,7 +33,7 @@ const TutorialDirectoryHeaderLink: TutorialDirectoryHeaderLinkComponent = memo(( return hasIngestManager && noticeState.settingsDataLoaded && noticeState.hasSeenNotice ? ( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_directory_notice.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_directory_notice.tsx index 64dbb3f43312..87fd58861b27 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_directory_notice.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_directory_notice.tsx @@ -60,13 +60,13 @@ const TutorialDirectoryNotice: TutorialDirectoryNoticeComponent = memo(() => { iconType="cheer" title={ @@ -77,7 +77,7 @@ const TutorialDirectoryNotice: TutorialDirectoryNoticeComponent = memo(() => { >

    { blogPostLink: ( @@ -98,7 +98,7 @@ const TutorialDirectoryNotice: TutorialDirectoryNoticeComponent = memo(() => {

    @@ -113,7 +113,7 @@ const TutorialDirectoryNotice: TutorialDirectoryNoticeComponent = memo(() => { }} > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_module_notice.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_module_notice.tsx index 7fec1909ba22..3430a4eb5b25 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_module_notice.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/home_integration/tutorial_module_notice.tsx @@ -26,14 +26,14 @@ const TutorialModuleNotice: TutorialModuleNoticeComponent = memo(({ moduleName }

    @@ -45,7 +45,7 @@ const TutorialModuleNotice: TutorialModuleNoticeComponent = memo(({ moduleName } })} > @@ -57,7 +57,7 @@ const TutorialModuleNotice: TutorialModuleNoticeComponent = memo(({ moduleName } target="_blank" > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/search_bar.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/search_bar.tsx index 9069cc0f7380..24a5b7e4c2bc 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/search_bar.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/search_bar.tsx @@ -61,7 +61,7 @@ export const SearchBar: React.FunctionComponent = ({ icon={'search'} placeholder={ placeholder || - i18n.translate('xpack.ingestManager.defaultSearchPlaceholderText', { + i18n.translate('xpack.fleet.defaultSearchPlaceholderText', { defaultMessage: 'Search', }) } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/settings_flyout.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/settings_flyout.tsx index 7f80863faee4..80ecaa249327 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/settings_flyout.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/settings_flyout.tsx @@ -41,21 +41,21 @@ function useSettingsForm(outputId: string | undefined, onSuccess: () => void) { const kibanaUrlsInput = useComboInput([], (value) => { if (value.length === 0) { return [ - i18n.translate('xpack.ingestManager.settings.kibanaUrlEmptyError', { + i18n.translate('xpack.fleet.settings.kibanaUrlEmptyError', { defaultMessage: 'At least one URL is required', }), ]; } if (value.some((v) => !v.match(URL_REGEX))) { return [ - i18n.translate('xpack.ingestManager.settings.kibanaUrlError', { + i18n.translate('xpack.fleet.settings.kibanaUrlError', { defaultMessage: 'Invalid URL', }), ]; } if (isDiffPathProtocol(value)) { return [ - i18n.translate('xpack.ingestManager.settings.kibanaUrlDifferentPathOrProtocolError', { + i18n.translate('xpack.fleet.settings.kibanaUrlDifferentPathOrProtocolError', { defaultMessage: 'Protocol and path must be the same for each URL', }), ]; @@ -64,7 +64,7 @@ function useSettingsForm(outputId: string | undefined, onSuccess: () => void) { const elasticsearchUrlInput = useComboInput([], (value) => { if (value.some((v) => !v.match(URL_REGEX))) { return [ - i18n.translate('xpack.ingestManager.settings.elasticHostError', { + i18n.translate('xpack.fleet.settings.elasticHostError', { defaultMessage: 'Invalid URL', }), ]; @@ -77,7 +77,7 @@ function useSettingsForm(outputId: string | undefined, onSuccess: () => void) { return; } catch (error) { return [ - i18n.translate('xpack.ingestManager.settings.invalidYamlFormatErrorMessage', { + i18n.translate('xpack.fleet.settings.invalidYamlFormatErrorMessage', { defaultMessage: 'Invalid YAML: {reason}', values: { reason: error.message }, }), @@ -114,7 +114,7 @@ function useSettingsForm(outputId: string | undefined, onSuccess: () => void) { throw settingsResponse.error; } notifications.toasts.addSuccess( - i18n.translate('xpack.ingestManager.settings.success.message', { + i18n.translate('xpack.fleet.settings.success.message', { defaultMessage: 'Settings saved', }) ); @@ -166,7 +166,7 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { options={[ { id: 'enabled', - label: i18n.translate('xpack.ingestManager.settings.autoUpgradeEnabledLabel', { + label: i18n.translate('xpack.fleet.settings.autoUpgradeEnabledLabel', { defaultMessage: 'Automatically update agent binaries to use the latest minor version.', }), @@ -174,7 +174,7 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { { id: 'disabled', disabled: true, - label: i18n.translate('xpack.ingestManager.settings.autoUpgradeDisabledLabel', { + label: i18n.translate('xpack.fleet.settings.autoUpgradeDisabledLabel', { defaultMessage: 'Manually manage agent binary versions. Requires a Gold subscription.', }), @@ -187,7 +187,7 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => {

    @@ -200,23 +200,17 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { options={[ { id: 'enabled', - label: i18n.translate( - 'xpack.ingestManager.settings.integrationUpgradeEnabledFieldLabel', - { - defaultMessage: - 'Automatically update integrations to the latest version to get the latest assets. You might need to update agent policies to use new features.', - } - ), + label: i18n.translate('xpack.fleet.settings.integrationUpgradeEnabledFieldLabel', { + defaultMessage: + 'Automatically update integrations to the latest version to get the latest assets. You might need to update agent policies to use new features.', + }), }, { id: 'disabled', disabled: true, - label: i18n.translate( - 'xpack.ingestManager.settings.integrationUpgradeDisabledFieldLabel', - { - defaultMessage: 'Manually manage integration versions yourself.', - } - ), + label: i18n.translate('xpack.fleet.settings.integrationUpgradeDisabledFieldLabel', { + defaultMessage: 'Manually manage integration versions yourself.', + }), }, ]} idSelected={'enabled'} @@ -226,7 +220,7 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => {

    @@ -238,7 +232,7 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => {

    @@ -246,14 +240,14 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { = ({ onClose }) => { = ({ onClose }) => { = ({ onClose }) => {

    @@ -317,7 +311,7 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { @@ -325,7 +319,7 @@ export const SettingFlyout: React.FunctionComponent = ({ onClose }) => { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_breadcrumbs.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_breadcrumbs.tsx index ccd889dec5b9..ed38e1a5ce4a 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_breadcrumbs.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_breadcrumbs.tsx @@ -10,7 +10,7 @@ import { useCore } from './use_core'; const BASE_BREADCRUMB: ChromeBreadcrumb = { href: pagePathGetters.overview(), - text: i18n.translate('xpack.ingestManager.breadcrumbs.appTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.appTitle', { defaultMessage: 'Fleet', }), }; @@ -22,7 +22,7 @@ const breadcrumbGetters: { overview: () => [ BASE_BREADCRUMB, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.overviewPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.overviewPageTitle', { defaultMessage: 'Overview', }), }, @@ -30,7 +30,7 @@ const breadcrumbGetters: { integrations: () => [ BASE_BREADCRUMB, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.integrationsPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.integrationsPageTitle', { defaultMessage: 'Integrations', }), }, @@ -39,12 +39,12 @@ const breadcrumbGetters: { BASE_BREADCRUMB, { href: pagePathGetters.integrations(), - text: i18n.translate('xpack.ingestManager.breadcrumbs.integrationsPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.integrationsPageTitle', { defaultMessage: 'Integrations', }), }, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.allIntegrationsPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.allIntegrationsPageTitle', { defaultMessage: 'All', }), }, @@ -53,12 +53,12 @@ const breadcrumbGetters: { BASE_BREADCRUMB, { href: pagePathGetters.integrations(), - text: i18n.translate('xpack.ingestManager.breadcrumbs.integrationsPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.integrationsPageTitle', { defaultMessage: 'Integrations', }), }, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.installedIntegrationsPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.installedIntegrationsPageTitle', { defaultMessage: 'Installed', }), }, @@ -67,7 +67,7 @@ const breadcrumbGetters: { BASE_BREADCRUMB, { href: pagePathGetters.integrations(), - text: i18n.translate('xpack.ingestManager.breadcrumbs.integrationsPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.integrationsPageTitle', { defaultMessage: 'Integrations', }), }, @@ -76,7 +76,7 @@ const breadcrumbGetters: { policies: () => [ BASE_BREADCRUMB, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.policiesPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.policiesPageTitle', { defaultMessage: 'Policies', }), }, @@ -84,7 +84,7 @@ const breadcrumbGetters: { policies_list: () => [ BASE_BREADCRUMB, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.policiesPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.policiesPageTitle', { defaultMessage: 'Policies', }), }, @@ -93,7 +93,7 @@ const breadcrumbGetters: { BASE_BREADCRUMB, { href: pagePathGetters.policies(), - text: i18n.translate('xpack.ingestManager.breadcrumbs.policiesPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.policiesPageTitle', { defaultMessage: 'Policies', }), }, @@ -103,7 +103,7 @@ const breadcrumbGetters: { BASE_BREADCRUMB, { href: pagePathGetters.policies(), - text: i18n.translate('xpack.ingestManager.breadcrumbs.policiesPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.policiesPageTitle', { defaultMessage: 'Policies', }), }, @@ -112,7 +112,7 @@ const breadcrumbGetters: { text: policyName, }, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.addPackagePolicyPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.addPackagePolicyPageTitle', { defaultMessage: 'Add integration', }), }, @@ -121,7 +121,7 @@ const breadcrumbGetters: { BASE_BREADCRUMB, { href: pagePathGetters.integrations(), - text: i18n.translate('xpack.ingestManager.breadcrumbs.integrationsPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.integrationsPageTitle', { defaultMessage: 'Integrations', }), }, @@ -130,7 +130,7 @@ const breadcrumbGetters: { text: pkgTitle, }, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.addPackagePolicyPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.addPackagePolicyPageTitle', { defaultMessage: 'Add integration', }), }, @@ -139,7 +139,7 @@ const breadcrumbGetters: { BASE_BREADCRUMB, { href: pagePathGetters.policies(), - text: i18n.translate('xpack.ingestManager.breadcrumbs.policiesPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.policiesPageTitle', { defaultMessage: 'Policies', }), }, @@ -148,7 +148,7 @@ const breadcrumbGetters: { text: policyName, }, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.editPackagePolicyPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.editPackagePolicyPageTitle', { defaultMessage: 'Edit integration', }), }, @@ -156,7 +156,7 @@ const breadcrumbGetters: { fleet: () => [ BASE_BREADCRUMB, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.agentsPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.agentsPageTitle', { defaultMessage: 'Agents', }), }, @@ -164,7 +164,7 @@ const breadcrumbGetters: { fleet_agent_list: () => [ BASE_BREADCRUMB, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.agentsPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.agentsPageTitle', { defaultMessage: 'Agents', }), }, @@ -173,7 +173,7 @@ const breadcrumbGetters: { BASE_BREADCRUMB, { href: pagePathGetters.fleet(), - text: i18n.translate('xpack.ingestManager.breadcrumbs.agentsPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.agentsPageTitle', { defaultMessage: 'Agents', }), }, @@ -183,12 +183,12 @@ const breadcrumbGetters: { BASE_BREADCRUMB, { href: pagePathGetters.fleet(), - text: i18n.translate('xpack.ingestManager.breadcrumbs.agentsPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.agentsPageTitle', { defaultMessage: 'Agents', }), }, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.enrollmentTokensPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.enrollmentTokensPageTitle', { defaultMessage: 'Enrollment tokens', }), }, @@ -196,7 +196,7 @@ const breadcrumbGetters: { data_streams: () => [ BASE_BREADCRUMB, { - text: i18n.translate('xpack.ingestManager.breadcrumbs.datastreamsPageTitle', { + text: i18n.translate('xpack.fleet.breadcrumbs.datastreamsPageTitle', { defaultMessage: 'Data streams', }), }, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx index 6c16d25a7c45..03cc4a8b7aff 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx @@ -114,16 +114,13 @@ const IngestManagerRoutes = memo<{ history: AppMountParameters['history']; basep } - error={i18n.translate( - 'xpack.ingestManager.permissionsRequestErrorMessageDescription', - { - defaultMessage: 'There was a problem checking Fleet permissions', - } - )} + error={i18n.translate('xpack.fleet.permissionsRequestErrorMessageDescription', { + defaultMessage: 'There was a problem checking Fleet permissions', + })} /> ) : ( @@ -133,12 +130,12 @@ const IngestManagerRoutes = memo<{ history: AppMountParameters['history']; basep

    {permissionsError === 'MISSING_SUPERUSER_ROLE' ? ( ) : ( )} @@ -148,13 +145,13 @@ const IngestManagerRoutes = memo<{ history: AppMountParameters['history']; basep

    {permissionsError === 'MISSING_SUPERUSER_ROLE' ? ( superuser }} /> ) : ( )} @@ -174,7 +171,7 @@ const IngestManagerRoutes = memo<{ history: AppMountParameters['history']; basep } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx index 5d39995922b9..376de7e2e6a0 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx @@ -63,19 +63,19 @@ export const DefaultLayout: React.FunctionComponent = ({ @@ -85,13 +85,13 @@ export const DefaultLayout: React.FunctionComponent = ({ disabled={!agents?.enabled} > @@ -106,7 +106,7 @@ export const DefaultLayout: React.FunctionComponent = ({ target="_blank" > @@ -115,7 +115,7 @@ export const DefaultLayout: React.FunctionComponent = ({ setIsSettingsFlyoutOpen(true)}> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/actions_menu.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/actions_menu.tsx index 691de5f25913..55872aee5c3d 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/actions_menu.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/actions_menu.tsx @@ -69,7 +69,7 @@ export const AgentPolicyActionMenu = memo<{ }, children: ( ), @@ -84,7 +84,7 @@ export const AgentPolicyActionMenu = memo<{ key="enrollAgents" > , @@ -94,7 +94,7 @@ export const AgentPolicyActionMenu = memo<{ key="viewPolicy" > , @@ -107,7 +107,7 @@ export const AgentPolicyActionMenu = memo<{ key="copyPolicy" > , diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_copy_provider.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_copy_provider.tsx index fefbe1fa82a0..41201f9612f1 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_copy_provider.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_copy_provider.tsx @@ -37,13 +37,10 @@ export const AgentPolicyCopyProvider: React.FunctionComponent = ({ childr setIsModalOpen(true); setAgentPolicy(agentPolicyToCopy); setNewAgentPolicy({ - name: i18n.translate( - 'xpack.ingestManager.copyAgentPolicy.confirmModal.defaultNewPolicyName', - { - defaultMessage: '{name} (copy)', - values: { name: agentPolicyToCopy.name }, - } - ), + name: i18n.translate('xpack.fleet.copyAgentPolicy.confirmModal.defaultNewPolicyName', { + defaultMessage: '{name} (copy)', + values: { name: agentPolicyToCopy.name }, + }), description: agentPolicyToCopy.description, }); onSuccessCallback.current = onSuccess; @@ -63,7 +60,7 @@ export const AgentPolicyCopyProvider: React.FunctionComponent = ({ childr if (data) { notifications.toasts.addSuccess( - i18n.translate('xpack.ingestManager.copyAgentPolicy.successNotificationTitle', { + i18n.translate('xpack.fleet.copyAgentPolicy.successNotificationTitle', { defaultMessage: 'Agent policy copied', }) ); @@ -72,7 +69,7 @@ export const AgentPolicyCopyProvider: React.FunctionComponent = ({ childr } } else { notifications.toasts.addDanger( - i18n.translate('xpack.ingestManager.copyAgentPolicy.failureNotificationTitle', { + i18n.translate('xpack.fleet.copyAgentPolicy.failureNotificationTitle', { defaultMessage: "Error copying agent policy '{id}'", values: { id: agentPolicy!.id }, }) @@ -80,7 +77,7 @@ export const AgentPolicyCopyProvider: React.FunctionComponent = ({ childr } } catch (e) { notifications.toasts.addDanger( - i18n.translate('xpack.ingestManager.copyAgentPolicy.fatalErrorNotificationTitle', { + i18n.translate('xpack.fleet.copyAgentPolicy.fatalErrorNotificationTitle', { defaultMessage: 'Error copying agent policy', }) ); @@ -99,7 +96,7 @@ export const AgentPolicyCopyProvider: React.FunctionComponent = ({ childr title={ = ({ childr onConfirm={copyAgentPolicy} cancelButtonText={ } confirmButtonText={ } @@ -125,14 +122,14 @@ export const AgentPolicyCopyProvider: React.FunctionComponent = ({ childr >

    } @@ -147,7 +144,7 @@ export const AgentPolicyCopyProvider: React.FunctionComponent = ({ childr } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_delete_provider.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_delete_provider.tsx index ab8a9c99227c..41704f69958a 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_delete_provider.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_delete_provider.tsx @@ -61,7 +61,7 @@ export const AgentPolicyDeleteProvider: React.FunctionComponent = ({ chil if (data) { notifications.toasts.addSuccess( - i18n.translate('xpack.ingestManager.deleteAgentPolicy.successSingleNotificationTitle', { + i18n.translate('xpack.fleet.deleteAgentPolicy.successSingleNotificationTitle', { defaultMessage: "Deleted agent policy '{id}'", values: { id: data.name || data.id }, }) @@ -71,7 +71,7 @@ export const AgentPolicyDeleteProvider: React.FunctionComponent = ({ chil } } else { notifications.toasts.addDanger( - i18n.translate('xpack.ingestManager.deleteAgentPolicy.failureSingleNotificationTitle', { + i18n.translate('xpack.fleet.deleteAgentPolicy.failureSingleNotificationTitle', { defaultMessage: "Error deleting agent policy '{id}'", values: { id: agentPolicy }, }) @@ -79,7 +79,7 @@ export const AgentPolicyDeleteProvider: React.FunctionComponent = ({ chil } } catch (e) { notifications.toasts.addDanger( - i18n.translate('xpack.ingestManager.deleteAgentPolicy.fatalErrorNotificationTitle', { + i18n.translate('xpack.fleet.deleteAgentPolicy.fatalErrorNotificationTitle', { defaultMessage: 'Error deleting agent policy', }) ); @@ -113,7 +113,7 @@ export const AgentPolicyDeleteProvider: React.FunctionComponent = ({ chil } @@ -121,19 +121,19 @@ export const AgentPolicyDeleteProvider: React.FunctionComponent = ({ chil onConfirm={deleteAgentPolicy} cancelButtonText={ } confirmButtonText={ isLoading || isLoadingAgentsCount ? ( ) : ( ) @@ -143,21 +143,21 @@ export const AgentPolicyDeleteProvider: React.FunctionComponent = ({ chil > {isLoadingAgentsCount ? ( ) : agentsCount ? ( = ({ chil ) : ( )} diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_form.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_form.tsx index c716f7b12e78..919b6d3669a6 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_form.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_form.tsx @@ -46,7 +46,7 @@ export const agentPolicyFormValidation = ( if (!agentPolicy.name?.trim()) { errors.name = [ , ]; @@ -88,12 +88,9 @@ export const AgentPolicyForm: React.FunctionComponent = ({ { name: 'name', label: ( - + ), - placeholder: i18n.translate('xpack.ingestManager.agentPolicyForm.nameFieldPlaceholder', { + placeholder: i18n.translate('xpack.fleet.agentPolicyForm.nameFieldPlaceholder', { defaultMessage: 'Choose a name', }), }, @@ -101,16 +98,13 @@ export const AgentPolicyForm: React.FunctionComponent = ({ name: 'description', label: ( ), - placeholder: i18n.translate( - 'xpack.ingestManager.agentPolicyForm.descriptionFieldPlaceholder', - { - defaultMessage: 'How will this policy be used?', - } - ), + placeholder: i18n.translate('xpack.fleet.agentPolicyForm.descriptionFieldPlaceholder', { + defaultMessage: 'How will this policy be used?', + }), }, ]; }, []); @@ -120,14 +114,14 @@ export const AgentPolicyForm: React.FunctionComponent = ({ title={

    } description={ } @@ -163,14 +157,14 @@ export const AgentPolicyForm: React.FunctionComponent = ({ title={

    } description={ } @@ -202,14 +196,14 @@ export const AgentPolicyForm: React.FunctionComponent = ({ title={

    } description={ } @@ -221,12 +215,12 @@ export const AgentPolicyForm: React.FunctionComponent = ({ label: ( <> {' '} = ({ label: ( <> {' '} = ({ title={

    @@ -298,7 +292,7 @@ export const AgentPolicyForm: React.FunctionComponent = ({ description={ <> @@ -311,7 +305,7 @@ export const AgentPolicyForm: React.FunctionComponent = ({ onClick={() => deleteAgentPolicyPrompt(agentPolicy.id!, onDelete)} > @@ -323,7 +317,7 @@ export const AgentPolicyForm: React.FunctionComponent = ({ @@ -343,7 +337,7 @@ export const AgentPolicyForm: React.FunctionComponent = ({ } @@ -353,12 +347,12 @@ export const AgentPolicyForm: React.FunctionComponent = ({ label={ <> {' '} = ({ id="advancedOptions" buttonContent={ } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_yaml_flyout.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_yaml_flyout.tsx index fefb427df5ea..773d53484147 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_yaml_flyout.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/agent_policy_yaml_flyout.tsx @@ -41,7 +41,7 @@ export const AgentPolicyYamlFlyout = memo<{ policyId: string; onClose: () => voi } @@ -69,13 +69,13 @@ export const AgentPolicyYamlFlyout = memo<{ policyId: string; onClose: () => voi

    {agentPolicyData?.item ? ( ) : ( )} @@ -88,7 +88,7 @@ export const AgentPolicyYamlFlyout = memo<{ policyId: string; onClose: () => voi @@ -100,7 +100,7 @@ export const AgentPolicyYamlFlyout = memo<{ policyId: string; onClose: () => voi isDisabled={Boolean(isLoadingYaml && !yamlData)} > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/confirm_deploy_modal.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/confirm_deploy_modal.tsx index d1a9b4812bfe..9b88ee24651b 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/confirm_deploy_modal.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/confirm_deploy_modal.tsx @@ -21,7 +21,7 @@ export const ConfirmDeployAgentPolicyModal: React.FunctionComponent<{ } @@ -29,13 +29,13 @@ export const ConfirmDeployAgentPolicyModal: React.FunctionComponent<{ onConfirm={onConfirm} cancelButtonText={ } confirmButtonText={ } @@ -43,7 +43,7 @@ export const ConfirmDeployAgentPolicyModal: React.FunctionComponent<{ >
    diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/linked_agent_count.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/linked_agent_count.tsx index 72e60ae67873..c602f492f74c 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/linked_agent_count.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/linked_agent_count.tsx @@ -15,7 +15,7 @@ export const LinkedAgentCount = memo<{ count: number; agentPolicyId: string }>( const { getHref } = useLink(); const displayValue = ( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/package_policy_delete_provider.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/package_policy_delete_provider.tsx index ff5961b94f72..8de40edc4033 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/package_policy_delete_provider.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/package_policy_delete_provider.tsx @@ -95,40 +95,28 @@ export const PackagePolicyDeleteProvider: React.FunctionComponent = ({ if (successfulResults.length) { const hasMultipleSuccesses = successfulResults.length > 1; const successMessage = hasMultipleSuccesses - ? i18n.translate( - 'xpack.ingestManager.deletePackagePolicy.successMultipleNotificationTitle', - { - defaultMessage: 'Deleted {count} integrations', - values: { count: successfulResults.length }, - } - ) - : i18n.translate( - 'xpack.ingestManager.deletePackagePolicy.successSingleNotificationTitle', - { - defaultMessage: "Deleted integration '{id}'", - values: { id: successfulResults[0].name || successfulResults[0].id }, - } - ); + ? i18n.translate('xpack.fleet.deletePackagePolicy.successMultipleNotificationTitle', { + defaultMessage: 'Deleted {count} integrations', + values: { count: successfulResults.length }, + }) + : i18n.translate('xpack.fleet.deletePackagePolicy.successSingleNotificationTitle', { + defaultMessage: "Deleted integration '{id}'", + values: { id: successfulResults[0].name || successfulResults[0].id }, + }); notifications.toasts.addSuccess(successMessage); } if (failedResults.length) { const hasMultipleFailures = failedResults.length > 1; const failureMessage = hasMultipleFailures - ? i18n.translate( - 'xpack.ingestManager.deletePackagePolicy.failureMultipleNotificationTitle', - { - defaultMessage: 'Error deleting {count} integrations', - values: { count: failedResults.length }, - } - ) - : i18n.translate( - 'xpack.ingestManager.deletePackagePolicy.failureSingleNotificationTitle', - { - defaultMessage: "Error deleting integration '{id}'", - values: { id: failedResults[0].id }, - } - ); + ? i18n.translate('xpack.fleet.deletePackagePolicy.failureMultipleNotificationTitle', { + defaultMessage: 'Error deleting {count} integrations', + values: { count: failedResults.length }, + }) + : i18n.translate('xpack.fleet.deletePackagePolicy.failureSingleNotificationTitle', { + defaultMessage: "Error deleting integration '{id}'", + values: { id: failedResults[0].id }, + }); notifications.toasts.addDanger(failureMessage); } @@ -137,7 +125,7 @@ export const PackagePolicyDeleteProvider: React.FunctionComponent = ({ } } catch (e) { notifications.toasts.addDanger( - i18n.translate('xpack.ingestManager.deletePackagePolicy.fatalErrorNotificationTitle', { + i18n.translate('xpack.fleet.deletePackagePolicy.fatalErrorNotificationTitle', { defaultMessage: 'Error deleting integration', }) ); @@ -157,7 +145,7 @@ export const PackagePolicyDeleteProvider: React.FunctionComponent = ({ @@ -166,19 +154,19 @@ export const PackagePolicyDeleteProvider: React.FunctionComponent = ({ onConfirm={deletePackagePolicies} cancelButtonText={ } confirmButtonText={ isLoading || isLoadingAgentsCount ? ( ) : ( = ({ > {isLoadingAgentsCount ? ( ) : agentsCount ? ( @@ -200,14 +188,14 @@ export const PackagePolicyDeleteProvider: React.FunctionComponent = ({ color="danger" title={ } > {agentPolicy.name}, @@ -219,7 +207,7 @@ export const PackagePolicyDeleteProvider: React.FunctionComponent = ({ ) : null} {!isLoadingAgentsCount && ( )} diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/custom_package_policy.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/custom_package_policy.tsx index 47c14ce0a3e8..d5163e1b9abb 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/custom_package_policy.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/custom_package_policy.tsx @@ -46,7 +46,7 @@ const EmptyPackagePolicy: CustomConfigurePackagePolicyContent = () => (

    diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/layout.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/layout.tsx index 6edce74d162b..9188f0069b8b 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/layout.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/layout.tsx @@ -54,7 +54,7 @@ export const CreatePackagePolicyPageLayout: React.FunctionComponent<{

    {from === 'edit' ? ( ) : (

    @@ -89,7 +89,7 @@ export const CreatePackagePolicyPageLayout: React.FunctionComponent<{

    @@ -100,17 +100,17 @@ export const CreatePackagePolicyPageLayout: React.FunctionComponent<{ const pageDescription = useMemo(() => { return from === 'edit' ? ( ) : from === 'policy' ? ( ) : ( ); @@ -129,7 +129,7 @@ export const CreatePackagePolicyPageLayout: React.FunctionComponent<{ data-test-subj={`${dataTestSubj}_cancelBackLink`} > @@ -149,7 +149,7 @@ export const CreatePackagePolicyPageLayout: React.FunctionComponent<{ diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_config.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_config.tsx index e966ca30c4c9..175bfb146990 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_config.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_config.tsx @@ -76,7 +76,7 @@ export const PackagePolicyInputConfig: React.FunctionComponent<{

    @@ -85,7 +85,7 @@ export const PackagePolicyInputConfig: React.FunctionComponent<{

    @@ -133,7 +133,7 @@ export const PackagePolicyInputConfig: React.FunctionComponent<{ flush="left" > @@ -142,7 +142,7 @@ export const PackagePolicyInputConfig: React.FunctionComponent<{ diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_panel.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_panel.tsx index 13504a1ed355..1e43cc0d5938 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_panel.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_panel.tsx @@ -133,7 +133,7 @@ export const PackagePolicyInputPanel: React.FunctionComponent<{ @@ -148,7 +148,7 @@ export const PackagePolicyInputPanel: React.FunctionComponent<{ aria-label={ isShowingStreams ? i18n.translate( - 'xpack.ingestManager.createPackagePolicy.stepConfigure.hideStreamsAriaLabel', + 'xpack.fleet.createPackagePolicy.stepConfigure.hideStreamsAriaLabel', { defaultMessage: 'Hide {type} inputs', values: { @@ -157,7 +157,7 @@ export const PackagePolicyInputPanel: React.FunctionComponent<{ } ) : i18n.translate( - 'xpack.ingestManager.createPackagePolicy.stepConfigure.showStreamsAriaLabel', + 'xpack.fleet.createPackagePolicy.stepConfigure.showStreamsAriaLabel', { defaultMessage: 'Show {type} inputs', values: { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_stream.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_stream.tsx index cbc23f4079d9..3d33edd46815 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_stream.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_stream.tsx @@ -135,7 +135,7 @@ export const PackagePolicyInputStreamConfig: React.FunctionComponent<{ flush="left" > @@ -144,7 +144,7 @@ export const PackagePolicyInputStreamConfig: React.FunctionComponent<{ diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_var_field.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_var_field.tsx index 3620b11948b5..9d036f5154b8 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_var_field.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/components/package_policy_input_var_field.tsx @@ -78,7 +78,7 @@ export const PackagePolicyInputVarField: React.FunctionComponent<{ !required ? ( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/index.tsx index 70e11d46aa7f..b45794b9f87d 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/index.tsx @@ -241,7 +241,7 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => { } notifications.toasts.addSuccess({ - title: i18n.translate('xpack.ingestManager.createPackagePolicy.addedNotificationTitle', { + title: i18n.translate('xpack.fleet.createPackagePolicy.addedNotificationTitle', { defaultMessage: `'{packagePolicyName}' integration added.`, values: { packagePolicyName: packagePolicy.name, @@ -249,7 +249,7 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => { }), text: agentCount && agentPolicy - ? i18n.translate('xpack.ingestManager.createPackagePolicy.addedNotificationMessage', { + ? i18n.translate('xpack.fleet.createPackagePolicy.addedNotificationMessage', { defaultMessage: `Fleet will deploy updates to all agents that use the '{agentPolicyName}' policy.`, values: { agentPolicyName: agentPolicy.name, @@ -338,27 +338,21 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => { const steps: EuiStepProps[] = [ from === 'package' ? { - title: i18n.translate( - 'xpack.ingestManager.createPackagePolicy.stepSelectAgentPolicyTitle', - { - defaultMessage: 'Select an agent policy', - } - ), + title: i18n.translate('xpack.fleet.createPackagePolicy.stepSelectAgentPolicyTitle', { + defaultMessage: 'Select an agent policy', + }), children: stepSelectAgentPolicy, } : { - title: i18n.translate('xpack.ingestManager.createPackagePolicy.stepSelectPackageTitle', { + title: i18n.translate('xpack.fleet.createPackagePolicy.stepSelectPackageTitle', { defaultMessage: 'Select an integration', }), children: stepSelectPackage, }, { - title: i18n.translate( - 'xpack.ingestManager.createPackagePolicy.stepConfigurePackagePolicyTitle', - { - defaultMessage: 'Configure integration', - } - ), + title: i18n.translate('xpack.fleet.createPackagePolicy.stepConfigurePackagePolicyTitle', { + defaultMessage: 'Configure integration', + }), status: !packageInfo || !agentPolicy || isLoadingSecondStep ? 'disabled' : undefined, 'data-test-subj': 'dataCollectionSetupStep', children: stepConfigurePackagePolicy, @@ -392,7 +386,7 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => { {!isLoadingSecondStep && agentPolicy && packageInfo && formState === 'INVALID' ? ( ) : null} @@ -408,7 +402,7 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => { data-test-subj="createPackagePolicyCancelButton" > @@ -424,7 +418,7 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => { data-test-subj="createPackagePolicySaveButton" > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/validate_package_policy.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/validate_package_policy.ts index 04cd21884e8f..9ce73c0690cc 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/validate_package_policy.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/services/validate_package_policy.ts @@ -54,7 +54,7 @@ export const validatePackagePolicy = ( if (!packagePolicy.name.trim()) { validationResults.name = [ - i18n.translate('xpack.ingestManager.packagePolicyValidation.nameRequiredErrorMessage', { + i18n.translate('xpack.fleet.packagePolicyValidation.nameRequiredErrorMessage', { defaultMessage: 'Name is required', }), ]; @@ -183,7 +183,7 @@ export const validatePackagePolicyConfig = ( if (varDef.required) { if (parsedValue === undefined || (typeof parsedValue === 'string' && !parsedValue)) { errors.push( - i18n.translate('xpack.ingestManager.packagePolicyValidation.requiredErrorMessage', { + i18n.translate('xpack.fleet.packagePolicyValidation.requiredErrorMessage', { defaultMessage: '{fieldName} is required', values: { fieldName: varDef.title || varDef.name, @@ -198,12 +198,9 @@ export const validatePackagePolicyConfig = ( parsedValue = safeLoad(value); } catch (e) { errors.push( - i18n.translate( - 'xpack.ingestManager.packagePolicyValidation.invalidYamlFormatErrorMessage', - { - defaultMessage: 'Invalid YAML format', - } - ) + i18n.translate('xpack.fleet.packagePolicyValidation.invalidYamlFormatErrorMessage', { + defaultMessage: 'Invalid YAML format', + }) ); } } @@ -211,7 +208,7 @@ export const validatePackagePolicyConfig = ( if (varDef.multi) { if (parsedValue && !Array.isArray(parsedValue)) { errors.push( - i18n.translate('xpack.ingestManager.packagePolicyValidation.invalidArrayErrorMessage', { + i18n.translate('xpack.fleet.packagePolicyValidation.invalidArrayErrorMessage', { defaultMessage: 'Invalid format', }) ); @@ -221,7 +218,7 @@ export const validatePackagePolicyConfig = ( (!parsedValue || (Array.isArray(parsedValue) && parsedValue.length === 0)) ) { errors.push( - i18n.translate('xpack.ingestManager.packagePolicyValidation.requiredErrorMessage', { + i18n.translate('xpack.fleet.packagePolicyValidation.requiredErrorMessage', { defaultMessage: '{fieldName} is required', values: { fieldName: varDef.title || varDef.name, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx index 86f69208e063..1d242848c3e2 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_define_package_policy.tsx @@ -87,14 +87,14 @@ export const StepDefinePackagePolicy: React.FunctionComponent<{ title={

    } description={ } @@ -106,7 +106,7 @@ export const StepDefinePackagePolicy: React.FunctionComponent<{ error={validationResults.name} label={ } @@ -126,14 +126,14 @@ export const StepDefinePackagePolicy: React.FunctionComponent<{ } labelAppend={ @@ -162,7 +162,7 @@ export const StepDefinePackagePolicy: React.FunctionComponent<{ flush="left" > @@ -171,7 +171,7 @@ export const StepDefinePackagePolicy: React.FunctionComponent<{ @@ -190,7 +190,7 @@ export const StepDefinePackagePolicy: React.FunctionComponent<{ error={validationResults.namespace} label={ } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_select_agent_policy.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_select_agent_policy.tsx index ccf9e45ebc4f..525a22414699 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_select_agent_policy.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_select_agent_policy.tsx @@ -171,7 +171,7 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ } @@ -186,7 +186,7 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ } @@ -219,7 +219,7 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ @@ -230,7 +230,7 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ onClick={() => setIsCreateAgentPolicyFlyoutOpen(true)} > @@ -241,7 +241,7 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ helpText={ isFleetReady && selectedPolicyId ? ( } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_select_package.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_select_package.tsx index 704455b21d64..8c646323c312 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_select_package.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/step_select_package.tsx @@ -103,7 +103,7 @@ export const StepSelectPackage: React.FunctionComponent<{ } @@ -118,7 +118,7 @@ export const StepSelectPackage: React.FunctionComponent<{ } @@ -157,7 +157,7 @@ export const StepSelectPackage: React.FunctionComponent<{ }} searchProps={{ placeholder: i18n.translate( - 'xpack.ingestManager.createPackagePolicy.stepSelectPackage.filterPackagesInputPlaceholder', + 'xpack.fleet.createPackagePolicy.stepSelectPackage.filterPackagesInputPlaceholder', { defaultMessage: 'Search for integrations', } @@ -190,7 +190,7 @@ export const StepSelectPackage: React.FunctionComponent<{ } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx index b84466ee073e..40682a28515f 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/no_package_policies.tsx @@ -18,14 +18,14 @@ export const NoPackagePolicies = memo<{ policyId: string }>(({ policyId }) => { title={

    } body={ } @@ -36,7 +36,7 @@ export const NoPackagePolicies = memo<{ policyId: string }>(({ policyId }) => { href={getHref('add_integration_from_policy', { policyId })} > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx index af4c2f78f14a..c7268d581acc 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/package_policies/package_policies_table.tsx @@ -84,12 +84,9 @@ export const PackagePoliciesTable: React.FunctionComponent = ({ { field: 'name', sortable: true, - name: i18n.translate( - 'xpack.ingestManager.policyDetails.packagePoliciesTable.nameColumnTitle', - { - defaultMessage: 'Name', - } - ), + name: i18n.translate('xpack.fleet.policyDetails.packagePoliciesTable.nameColumnTitle', { + defaultMessage: 'Name', + }), render: (value: string) => ( {value} @@ -99,7 +96,7 @@ export const PackagePoliciesTable: React.FunctionComponent = ({ { field: 'description', name: i18n.translate( - 'xpack.ingestManager.policyDetails.packagePoliciesTable.descriptionColumnTitle', + 'xpack.fleet.policyDetails.packagePoliciesTable.descriptionColumnTitle', { defaultMessage: 'Description', } @@ -114,7 +111,7 @@ export const PackagePoliciesTable: React.FunctionComponent = ({ field: 'packageTitle', sortable: true, name: i18n.translate( - 'xpack.ingestManager.policyDetails.packagePoliciesTable.packageNameColumnTitle', + 'xpack.fleet.policyDetails.packagePoliciesTable.packageNameColumnTitle', { defaultMessage: 'Integration', } @@ -140,7 +137,7 @@ export const PackagePoliciesTable: React.FunctionComponent = ({ { field: 'namespace', name: i18n.translate( - 'xpack.ingestManager.policyDetails.packagePoliciesTable.namespaceColumnTitle', + 'xpack.fleet.policyDetails.packagePoliciesTable.namespaceColumnTitle', { defaultMessage: 'Namespace', } @@ -150,12 +147,9 @@ export const PackagePoliciesTable: React.FunctionComponent = ({ }, }, { - name: i18n.translate( - 'xpack.ingestManager.policyDetails.packagePoliciesTable.actionsColumnTitle', - { - defaultMessage: 'Actions', - } - ), + name: i18n.translate('xpack.fleet.policyDetails.packagePoliciesTable.actionsColumnTitle', { + defaultMessage: 'Actions', + }), actions: [ { render: (packagePolicy: InMemoryPackagePolicy) => ( @@ -169,7 +163,7 @@ export const PackagePoliciesTable: React.FunctionComponent = ({ // key="packagePolicyView" // > // // , @@ -183,14 +177,14 @@ export const PackagePoliciesTable: React.FunctionComponent = ({ key="packagePolicyEdit" > , // FIXME: implement Copy package policy action // {}} key="packagePolicyCopy"> // // , @@ -205,7 +199,7 @@ export const PackagePoliciesTable: React.FunctionComponent = ({ }} > @@ -243,7 +237,7 @@ export const PackagePoliciesTable: React.FunctionComponent = ({ href={getHref('add_integration_from_policy', { policyId: agentPolicy.id })} > , diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx index bc0457ffa0d4..fe3955c84dec 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx @@ -71,7 +71,7 @@ export const SettingsView = memo<{ agentPolicy: AgentPolicy }>( }); if (data) { notifications.toasts.addSuccess( - i18n.translate('xpack.ingestManager.editAgentPolicy.successNotificationTitle', { + i18n.translate('xpack.fleet.editAgentPolicy.successNotificationTitle', { defaultMessage: "Successfully updated '{name}' settings", values: { name: agentPolicy.name }, }) @@ -82,14 +82,14 @@ export const SettingsView = memo<{ agentPolicy: AgentPolicy }>( notifications.toasts.addDanger( error ? error.message - : i18n.translate('xpack.ingestManager.editAgentPolicy.errorNotificationTitle', { + : i18n.translate('xpack.fleet.editAgentPolicy.errorNotificationTitle', { defaultMessage: 'Unable to update agent policy', }) ); } } catch (e) { notifications.toasts.addDanger( - i18n.translate('xpack.ingestManager.editAgentPolicy.errorNotificationTitle', { + i18n.translate('xpack.fleet.editAgentPolicy.errorNotificationTitle', { defaultMessage: 'Unable to update agent policy', }) ); @@ -145,7 +145,7 @@ export const SettingsView = memo<{ agentPolicy: AgentPolicy }>( @@ -160,7 +160,7 @@ export const SettingsView = memo<{ agentPolicy: AgentPolicy }>( }} > @@ -178,12 +178,12 @@ export const SettingsView = memo<{ agentPolicy: AgentPolicy }>( > {isLoading ? ( ) : ( )} diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/index.tsx index 4be3108dd6ef..7528c923f0ab 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/index.tsx @@ -74,7 +74,7 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => { size="xs" > @@ -87,7 +87,7 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => { ) : ( (agentPolicy && agentPolicy.name) || ( { {[ { - label: i18n.translate('xpack.ingestManager.policyDetails.summary.revision', { + label: i18n.translate('xpack.fleet.policyDetails.summary.revision', { defaultMessage: 'Revision', }), content: agentPolicy?.revision ?? 0, }, { isDivider: true }, { - label: i18n.translate('xpack.ingestManager.policyDetails.summary.integrations', { + label: i18n.translate('xpack.fleet.policyDetails.summary.integrations', { defaultMessage: 'Integrations', }), content: ( @@ -141,7 +141,7 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => { }, { isDivider: true }, { - label: i18n.translate('xpack.ingestManager.policyDetails.summary.usedBy', { + label: i18n.translate('xpack.fleet.policyDetails.summary.usedBy', { defaultMessage: 'Used by', }), content: ( @@ -153,7 +153,7 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => { }, { isDivider: true }, { - label: i18n.translate('xpack.ingestManager.policyDetails.summary.lastUpdated', { + label: i18n.translate('xpack.fleet.policyDetails.summary.lastUpdated', { defaultMessage: 'Last updated on', }), content: @@ -217,7 +217,7 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => { return [ { id: 'integrations', - name: i18n.translate('xpack.ingestManager.policyDetails.subTabs.packagePoliciesTabText', { + name: i18n.translate('xpack.fleet.policyDetails.subTabs.packagePoliciesTabText', { defaultMessage: 'Integrations', }), href: getHref('policy_details', { policyId, tabId: 'integrations' }), @@ -225,7 +225,7 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => { }, { id: 'settings', - name: i18n.translate('xpack.ingestManager.policyDetails.subTabs.settingsTabText', { + name: i18n.translate('xpack.fleet.policyDetails.subTabs.settingsTabText', { defaultMessage: 'Settings', }), href: getHref('policy_details', { policyId, tabId: 'settings' }), @@ -248,7 +248,7 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => { } @@ -262,11 +262,11 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => { } - error={i18n.translate('xpack.ingestManager.policyDetails.policyNotFoundErrorTitle', { + error={i18n.translate('xpack.fleet.policyDetails.policyNotFoundErrorTitle', { defaultMessage: "Policy '{id}' not found", values: { id: policyId, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/edit_package_policy_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/edit_package_policy_page/index.tsx index af4ffab12a79..d642619515a5 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/edit_package_policy_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/edit_package_policy_page/index.tsx @@ -214,7 +214,7 @@ export const EditPackagePolicyPage: React.FunctionComponent = () => { if (!error) { history.push(getPath('policy_details', { policyId })); notifications.toasts.addSuccess({ - title: i18n.translate('xpack.ingestManager.editPackagePolicy.updatedNotificationTitle', { + title: i18n.translate('xpack.fleet.editPackagePolicy.updatedNotificationTitle', { defaultMessage: `Successfully updated '{packagePolicyName}'`, values: { packagePolicyName: packagePolicy.name, @@ -222,7 +222,7 @@ export const EditPackagePolicyPage: React.FunctionComponent = () => { }), text: agentCount && agentPolicy - ? i18n.translate('xpack.ingestManager.editPackagePolicy.updatedNotificationMessage', { + ? i18n.translate('xpack.fleet.editPackagePolicy.updatedNotificationMessage', { defaultMessage: `Fleet will deploy updates to all agents that use the '{agentPolicyName}' policy`, values: { agentPolicyName: agentPolicy.name, @@ -233,14 +233,14 @@ export const EditPackagePolicyPage: React.FunctionComponent = () => { } else { if (error.statusCode === 409) { notifications.toasts.addError(error, { - title: i18n.translate('xpack.ingestManager.editPackagePolicy.failedNotificationTitle', { + title: i18n.translate('xpack.fleet.editPackagePolicy.failedNotificationTitle', { defaultMessage: `Error updating '{packagePolicyName}'`, values: { packagePolicyName: packagePolicy.name, }, }), toastMessage: i18n.translate( - 'xpack.ingestManager.editPackagePolicy.failedConflictNotificationMessage', + 'xpack.fleet.editPackagePolicy.failedConflictNotificationMessage', { defaultMessage: `Data is out of date. Refresh the page to get the latest policy.`, } @@ -248,7 +248,7 @@ export const EditPackagePolicyPage: React.FunctionComponent = () => { }); } else { notifications.toasts.addError(error, { - title: i18n.translate('xpack.ingestManager.editPackagePolicy.failedNotificationTitle', { + title: i18n.translate('xpack.fleet.editPackagePolicy.failedNotificationTitle', { defaultMessage: `Error updating '{packagePolicyName}'`, values: { packagePolicyName: packagePolicy.name, @@ -309,13 +309,13 @@ export const EditPackagePolicyPage: React.FunctionComponent = () => { } error={ loadingError || - i18n.translate('xpack.ingestManager.editPackagePolicy.errorLoadingDataMessage', { + i18n.translate('xpack.fleet.editPackagePolicy.errorLoadingDataMessage', { defaultMessage: 'There was an error loading this intergration information', }) } @@ -338,7 +338,7 @@ export const EditPackagePolicyPage: React.FunctionComponent = () => { {agentPolicy && packageInfo && formState === 'INVALID' ? ( ) : null} @@ -348,7 +348,7 @@ export const EditPackagePolicyPage: React.FunctionComponent = () => { @@ -363,7 +363,7 @@ export const EditPackagePolicyPage: React.FunctionComponent = () => { fill > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/components/create_agent_policy.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/components/create_agent_policy.tsx index e3e2975777e1..d2c3fc64aa9e 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/components/create_agent_policy.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/components/create_agent_policy.tsx @@ -66,7 +66,7 @@ export const CreateAgentPolicyFlyout: React.FunctionComponent = ({

    @@ -75,7 +75,7 @@ export const CreateAgentPolicyFlyout: React.FunctionComponent = ({

    @@ -101,7 +101,7 @@ export const CreateAgentPolicyFlyout: React.FunctionComponent = ({ onClose()} flush="left"> @@ -118,31 +118,25 @@ export const CreateAgentPolicyFlyout: React.FunctionComponent = ({ setIsLoading(false); if (data) { notifications.toasts.addSuccess( - i18n.translate( - 'xpack.ingestManager.createAgentPolicy.successNotificationTitle', - { - defaultMessage: "Agent policy '{name}' created", - values: { name: agentPolicy.name }, - } - ) + i18n.translate('xpack.fleet.createAgentPolicy.successNotificationTitle', { + defaultMessage: "Agent policy '{name}' created", + values: { name: agentPolicy.name }, + }) ); onClose(data.item); } else { notifications.toasts.addDanger( error ? error.message - : i18n.translate( - 'xpack.ingestManager.createAgentPolicy.errorNotificationTitle', - { - defaultMessage: 'Unable to create agent policy', - } - ) + : i18n.translate('xpack.fleet.createAgentPolicy.errorNotificationTitle', { + defaultMessage: 'Unable to create agent policy', + }) ); } } catch (e) { setIsLoading(false); notifications.toasts.addDanger( - i18n.translate('xpack.ingestManager.createAgentPolicy.errorNotificationTitle', { + i18n.translate('xpack.fleet.createAgentPolicy.errorNotificationTitle', { defaultMessage: 'Unable to create agent policy', }) ); @@ -150,7 +144,7 @@ export const CreateAgentPolicyFlyout: React.FunctionComponent = ({ }} > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/index.tsx index aa4b42986a4f..8c2fe838bfa4 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/index.tsx @@ -46,7 +46,7 @@ const AgentPolicyListPageLayout: React.FunctionComponent = ({ children }) => (

    @@ -56,7 +56,7 @@ const AgentPolicyListPageLayout: React.FunctionComponent = ({ children }) => (

    @@ -124,7 +124,7 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { { field: 'name', sortable: true, - name: i18n.translate('xpack.ingestManager.agentPolicyList.nameColumnTitle', { + name: i18n.translate('xpack.fleet.agentPolicyList.nameColumnTitle', { defaultMessage: 'Name', }), width: '20%', @@ -142,7 +142,7 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { @@ -153,7 +153,7 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { }, { field: 'description', - name: i18n.translate('xpack.ingestManager.agentPolicyList.descriptionColumnTitle', { + name: i18n.translate('xpack.fleet.agentPolicyList.descriptionColumnTitle', { defaultMessage: 'Description', }), width: '35%', @@ -166,7 +166,7 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { { field: 'updated_at', sortable: true, - name: i18n.translate('xpack.ingestManager.agentPolicyList.updatedOnColumnTitle', { + name: i18n.translate('xpack.fleet.agentPolicyList.updatedOnColumnTitle', { defaultMessage: 'Last updated on', }), render: (date: AgentPolicy['updated_at']) => ( @@ -175,7 +175,7 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { }, { field: 'agents', - name: i18n.translate('xpack.ingestManager.agentPolicyList.agentsColumnTitle', { + name: i18n.translate('xpack.fleet.agentPolicyList.agentsColumnTitle', { defaultMessage: 'Agents', }), dataType: 'number', @@ -185,18 +185,15 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { }, { field: 'package_policies', - name: i18n.translate( - 'xpack.ingestManager.agentPolicyList.packagePoliciesCountColumnTitle', - { - defaultMessage: 'Integrations', - } - ), + name: i18n.translate('xpack.fleet.agentPolicyList.packagePoliciesCountColumnTitle', { + defaultMessage: 'Integrations', + }), dataType: 'number', render: (packagePolicies: AgentPolicy['package_policies']) => packagePolicies ? packagePolicies.length : 0, }, { - name: i18n.translate('xpack.ingestManager.agentPolicyList.actionsColumnTitle', { + name: i18n.translate('xpack.fleet.agentPolicyList.actionsColumnTitle', { defaultMessage: 'Actions', }), actions: [ @@ -229,7 +226,7 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { onClick={() => setIsCreateAgentPolicyFlyoutOpen(true)} > @@ -243,7 +240,7 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { title={

    @@ -291,7 +288,7 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { resendRequest()}> @@ -306,20 +303,20 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { noItemsMessage={ isLoading ? ( ) : !search.trim() && (agentPolicyData?.total ?? 0) === 0 ? ( emptyPrompt ) : ( setSearch('')}> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/components/data_stream_row_actions.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/components/data_stream_row_actions.tsx index 057970aa1ee9..90c0d848a507 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/components/data_stream_row_actions.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/components/data_stream_row_actions.tsx @@ -16,18 +16,18 @@ export const DataStreamRowActions = memo<{ datastream: DataStream }>(({ datastre const panels = []; const actionNameSingular = ( ); const actionNamePlural = ( ); - const panelTitle = i18n.translate('xpack.ingestManager.dataStreamList.viewDashboardsPanelTitle', { + const panelTitle = i18n.translate('xpack.fleet.dataStreamList.viewDashboardsPanelTitle', { defaultMessage: 'View dashboards', }); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx index 4e32fa0bbc1b..533c27368112 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/data_stream/list_page/index.tsx @@ -31,7 +31,7 @@ const DataStreamListPageLayout: React.FunctionComponent = ({ children }) => (

    @@ -41,7 +41,7 @@ const DataStreamListPageLayout: React.FunctionComponent = ({ children }) => (

    @@ -75,21 +75,21 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { field: 'dataset', sortable: true, width: '25%', - name: i18n.translate('xpack.ingestManager.dataStreamList.datasetColumnTitle', { + name: i18n.translate('xpack.fleet.dataStreamList.datasetColumnTitle', { defaultMessage: 'Dataset', }), }, { field: 'type', sortable: true, - name: i18n.translate('xpack.ingestManager.dataStreamList.typeColumnTitle', { + name: i18n.translate('xpack.fleet.dataStreamList.typeColumnTitle', { defaultMessage: 'Type', }), }, { field: 'namespace', sortable: true, - name: i18n.translate('xpack.ingestManager.dataStreamList.namespaceColumnTitle', { + name: i18n.translate('xpack.fleet.dataStreamList.namespaceColumnTitle', { defaultMessage: 'Namespace', }), render: (namespace: string) => { @@ -99,7 +99,7 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { { field: 'package', sortable: true, - name: i18n.translate('xpack.ingestManager.dataStreamList.integrationColumnTitle', { + name: i18n.translate('xpack.fleet.dataStreamList.integrationColumnTitle', { defaultMessage: 'Integration', }), render(pkg: DataStream['package'], datastream: DataStream) { @@ -125,7 +125,7 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { sortable: true, width: '25%', dataType: 'date', - name: i18n.translate('xpack.ingestManager.dataStreamList.lastActivityColumnTitle', { + name: i18n.translate('xpack.fleet.dataStreamList.lastActivityColumnTitle', { defaultMessage: 'Last activity', }), render: (date: DataStream['last_activity']) => { @@ -140,7 +140,7 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { { field: 'size_in_bytes', sortable: true, - name: i18n.translate('xpack.ingestManager.dataStreamList.sizeColumnTitle', { + name: i18n.translate('xpack.fleet.dataStreamList.sizeColumnTitle', { defaultMessage: 'Size', }), render: (size: DataStream['size_in_bytes']) => { @@ -153,7 +153,7 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { }, }, { - name: i18n.translate('xpack.ingestManager.dataStreamList.actionsColumnTitle', { + name: i18n.translate('xpack.fleet.dataStreamList.actionsColumnTitle', { defaultMessage: 'Actions', }), actions: [ @@ -172,7 +172,7 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { title={

    @@ -236,14 +236,14 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { message={ isLoading ? ( ) : dataStreamsData && !dataStreamsData.data_streams.length ? ( emptyPrompt ) : ( ) @@ -265,25 +265,22 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { onClick={() => resendRequest()} > , ], box: { - placeholder: i18n.translate( - 'xpack.ingestManager.dataStreamList.searchPlaceholderTitle', - { - defaultMessage: 'Filter data streams', - } - ), + placeholder: i18n.translate('xpack.fleet.dataStreamList.searchPlaceholderTitle', { + defaultMessage: 'Filter data streams', + }), incremental: true, }, filters: [ { type: 'field_value_selection', field: 'dataset', - name: i18n.translate('xpack.ingestManager.dataStreamList.datasetColumnTitle', { + name: i18n.translate('xpack.fleet.dataStreamList.datasetColumnTitle', { defaultMessage: 'Dataset', }), multiSelect: 'or', @@ -293,7 +290,7 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { { type: 'field_value_selection', field: 'type', - name: i18n.translate('xpack.ingestManager.dataStreamList.typeColumnTitle', { + name: i18n.translate('xpack.fleet.dataStreamList.typeColumnTitle', { defaultMessage: 'Type', }), multiSelect: 'or', @@ -303,7 +300,7 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { { type: 'field_value_selection', field: 'namespace', - name: i18n.translate('xpack.ingestManager.dataStreamList.namespaceColumnTitle', { + name: i18n.translate('xpack.fleet.dataStreamList.namespaceColumnTitle', { defaultMessage: 'Namespace', }), multiSelect: 'or', @@ -313,7 +310,7 @@ export const DataStreamListPage: React.FunctionComponent<{}> = () => { { type: 'field_value_selection', field: 'package', - name: i18n.translate('xpack.ingestManager.dataStreamList.integrationColumnTitle', { + name: i18n.translate('xpack.fleet.dataStreamList.integrationColumnTitle', { defaultMessage: 'Integration', }), multiSelect: 'or', diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/assets_facet_group.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/assets_facet_group.tsx index b8fab92e40da..87f83d39ad36 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/assets_facet_group.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/assets_facet_group.tsx @@ -79,7 +79,7 @@ export function AssetsFacetGroup({ assets }: { assets: AssetsGroupedByServiceByT

    ( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_list_grid.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_list_grid.tsx index 0c1199f7c886..ef3b94081b1d 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_list_grid.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/package_list_grid.tsx @@ -75,7 +75,7 @@ export function PackageListGrid({ isLoading, controls, title, list }: ListProps)

    diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/release_badge.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/release_badge.ts index f3520b4e7a9b..735a5285bacc 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/release_badge.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/components/release_badge.ts @@ -7,19 +7,19 @@ import { i18n } from '@kbn/i18n'; import { RegistryRelease } from '../../../types'; export const RELEASE_BADGE_LABEL: { [key in Exclude]: string } = { - beta: i18n.translate('xpack.ingestManager.epm.releaseBadge.betaLabel', { + beta: i18n.translate('xpack.fleet.epm.releaseBadge.betaLabel', { defaultMessage: 'Beta', }), - experimental: i18n.translate('xpack.ingestManager.epm.releaseBadge.experimentalLabel', { + experimental: i18n.translate('xpack.fleet.epm.releaseBadge.experimentalLabel', { defaultMessage: 'Experimental', }), }; export const RELEASE_BADGE_DESCRIPTION: { [key in Exclude]: string } = { - beta: i18n.translate('xpack.ingestManager.epm.releaseBadge.betaDescription', { + beta: i18n.translate('xpack.fleet.epm.releaseBadge.betaDescription', { defaultMessage: 'This integration is not recommended for use in production environments.', }), - experimental: i18n.translate('xpack.ingestManager.epm.releaseBadge.experimentalDescription', { + experimental: i18n.translate('xpack.fleet.epm.releaseBadge.experimentalDescription', { defaultMessage: 'This integration may have breaking changes or be removed in a future release.', }), }; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx index 2342a79932c8..8ab738fd8ff5 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/hooks/use_package_install.tsx @@ -73,14 +73,14 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar notifications.toasts.addWarning({ title: toMountPoint( ), text: toMountPoint( ), @@ -98,14 +98,14 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar notifications.toasts.addSuccess({ title: toMountPoint( ), text: toMountPoint( @@ -127,14 +127,14 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar notifications.toasts.addWarning({ title: toMountPoint( ), text: toMountPoint( ), @@ -146,14 +146,14 @@ function usePackageInstall({ notifications }: { notifications: NotificationsStar notifications.toasts.addSuccess({ title: toMountPoint( ), text: toMountPoint( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx index ac30815a941e..d34d947de33a 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_install.tsx @@ -20,7 +20,7 @@ export const ConfirmPackageInstall = (props: ConfirmPackageInstallProps) => { @@ -29,13 +29,13 @@ export const ConfirmPackageInstall = (props: ConfirmPackageInstallProps) => { onConfirm={onConfirm} cancelButtonText={ } confirmButtonText={ @@ -46,7 +46,7 @@ export const ConfirmPackageInstall = (props: ConfirmPackageInstallProps) => { iconType="iInCircle" title={ @@ -55,7 +55,7 @@ export const ConfirmPackageInstall = (props: ConfirmPackageInstallProps) => {

    diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx index f4d5226ebe95..24ef18e1f979 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/confirm_package_uninstall.tsx @@ -20,7 +20,7 @@ export const ConfirmPackageUninstall = (props: ConfirmPackageUninstallProps) => @@ -29,13 +29,13 @@ export const ConfirmPackageUninstall = (props: ConfirmPackageUninstallProps) => onConfirm={onConfirm} cancelButtonText={ } confirmButtonText={ @@ -47,7 +47,7 @@ export const ConfirmPackageUninstall = (props: ConfirmPackageUninstallProps) => color="danger" title={ @@ -55,7 +55,7 @@ export const ConfirmPackageUninstall = (props: ConfirmPackageUninstallProps) => >

    @@ -63,7 +63,7 @@ export const ConfirmPackageUninstall = (props: ConfirmPackageUninstallProps) =>

    diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/index.tsx index 84d3f97f3ee0..7e7958ce91af 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/index.tsx @@ -109,7 +109,7 @@ export function Detail() { href={getHref('integrations_all')} > @@ -161,7 +161,7 @@ export function Detail() { {[ { - label: i18n.translate('xpack.ingestManager.epm.versionLabel', { + label: i18n.translate('xpack.fleet.epm.versionLabel', { defaultMessage: 'Version', }), content: ( @@ -187,7 +187,7 @@ export function Detail() { })} > } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx index cdad67fd8754..306865075c63 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/installation_button.tsx @@ -66,7 +66,7 @@ export function InstallationButton(props: InstallationButtonProps) { {isInstalling ? ( ) : ( @@ -103,7 +103,7 @@ export function InstallationButton(props: InstallationButtonProps) { > {isRemoving ? ( ) : (

    - +

    diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx index 4ac6fe6872e1..814b05163d20 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/detail/settings_panel.tsx @@ -27,7 +27,7 @@ const UpdatesAvailableMsgContainer = styled.span` const NoteLabel = () => ( ); @@ -35,7 +35,7 @@ const UpdatesAvailableMsg = () => ( @@ -67,7 +67,7 @@ export const SettingsPanel = (

    @@ -78,7 +78,7 @@ export const SettingsPanel = (

    @@ -106,7 +106,7 @@ export const SettingsPanel = ( @@ -139,7 +139,7 @@ export const SettingsPanel = (

    @@ -193,7 +193,7 @@ export const SettingsPanel = ( {packageHasUsages && removable === true && (

    & { }; const PanelDisplayNames: Record = { - overview: i18n.translate('xpack.ingestManager.epm.packageDetailsNav.overviewLinkText', { + overview: i18n.translate('xpack.fleet.epm.packageDetailsNav.overviewLinkText', { defaultMessage: 'Overview', }), - usages: i18n.translate('xpack.ingestManager.epm.packageDetailsNav.packagePoliciesLinkText', { + usages: i18n.translate('xpack.fleet.epm.packageDetailsNav.packagePoliciesLinkText', { defaultMessage: 'Usages', }), - settings: i18n.translate('xpack.ingestManager.epm.packageDetailsNav.settingsLinkText', { + settings: i18n.translate('xpack.fleet.epm.packageDetailsNav.settingsLinkText', { defaultMessage: 'Settings', }), }; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/header.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/header.tsx index 363b1ede89e9..e9704cd16b21 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/header.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/epm/screens/home/header.tsx @@ -18,10 +18,7 @@ export const HeroCopy = memo(() => {

    - +

    @@ -29,7 +26,7 @@ export const HeroCopy = memo(() => {

    @@ -51,7 +48,7 @@ export const HeroImage = memo(() => { return ( ), @@ -91,7 +91,7 @@ export const AgentDetailsActionMenu: React.FunctionComponent<{ key="reassignPolicy" > , @@ -104,12 +104,12 @@ export const AgentDetailsActionMenu: React.FunctionComponent<{ > {isUnenrolling ? ( ) : ( )} @@ -122,7 +122,7 @@ export const AgentDetailsActionMenu: React.FunctionComponent<{ }} > , diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_details.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_details.tsx index 2493fda3317d..5ce757734e63 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_details.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_details.tsx @@ -31,7 +31,7 @@ export const AgentDetailsContent: React.FunctionComponent<{ {[ { - title: i18n.translate('xpack.ingestManager.agentDetails.hostNameLabel', { + title: i18n.translate('xpack.fleet.agentDetails.hostNameLabel', { defaultMessage: 'Host name', }), description: @@ -41,19 +41,19 @@ export const AgentDetailsContent: React.FunctionComponent<{ : '-', }, { - title: i18n.translate('xpack.ingestManager.agentDetails.hostIdLabel', { + title: i18n.translate('xpack.fleet.agentDetails.hostIdLabel', { defaultMessage: 'Agent ID', }), description: agent.id, }, { - title: i18n.translate('xpack.ingestManager.agentDetails.statusLabel', { + title: i18n.translate('xpack.fleet.agentDetails.statusLabel', { defaultMessage: 'Status', }), description: , }, { - title: i18n.translate('xpack.ingestManager.agentDetails.agentPolicyLabel', { + title: i18n.translate('xpack.fleet.agentDetails.agentPolicyLabel', { defaultMessage: 'Agent policy', }), description: agentPolicy ? ( @@ -68,7 +68,7 @@ export const AgentDetailsContent: React.FunctionComponent<{ ), }, { - title: i18n.translate('xpack.ingestManager.agentDetails.versionLabel', { + title: i18n.translate('xpack.fleet.agentDetails.versionLabel', { defaultMessage: 'Agent version', }), description: @@ -85,7 +85,7 @@ export const AgentDetailsContent: React.FunctionComponent<{  
    @@ -97,7 +97,7 @@ export const AgentDetailsContent: React.FunctionComponent<{ ), }, { - title: i18n.translate('xpack.ingestManager.agentDetails.releaseLabel', { + title: i18n.translate('xpack.fleet.agentDetails.releaseLabel', { defaultMessage: 'Agent release', }), description: @@ -110,7 +110,7 @@ export const AgentDetailsContent: React.FunctionComponent<{ : '-', }, { - title: i18n.translate('xpack.ingestManager.agentDetails.platformLabel', { + title: i18n.translate('xpack.fleet.agentDetails.platformLabel', { defaultMessage: 'Platform', }), description: diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_events_table.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_events_table.tsx index e11863a2db85..c1a1b3862728 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_events_table.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_events_table.tsx @@ -78,7 +78,7 @@ export const AgentEventsTable: React.FunctionComponent<{ agent: Agent }> = ({ ag @@ -92,7 +92,7 @@ export const AgentEventsTable: React.FunctionComponent<{ agent: Agent }> = ({ ag @@ -113,7 +113,7 @@ export const AgentEventsTable: React.FunctionComponent<{ agent: Agent }> = ({ ag const columns = [ { field: 'timestamp', - name: i18n.translate('xpack.ingestManager.agentEventsList.timestampColumnTitle', { + name: i18n.translate('xpack.fleet.agentEventsList.timestampColumnTitle', { defaultMessage: 'Timestamp', }), render: (timestamp: string) => ( @@ -132,7 +132,7 @@ export const AgentEventsTable: React.FunctionComponent<{ agent: Agent }> = ({ ag }, { field: 'type', - name: i18n.translate('xpack.ingestManager.agentEventsList.typeColumnTitle', { + name: i18n.translate('xpack.fleet.agentEventsList.typeColumnTitle', { defaultMessage: 'Type', }), width: '10%', @@ -141,7 +141,7 @@ export const AgentEventsTable: React.FunctionComponent<{ agent: Agent }> = ({ ag }, { field: 'subtype', - name: i18n.translate('xpack.ingestManager.agentEventsList.subtypeColumnTitle', { + name: i18n.translate('xpack.fleet.agentEventsList.subtypeColumnTitle', { defaultMessage: 'Subtype', }), width: '13%', @@ -150,7 +150,7 @@ export const AgentEventsTable: React.FunctionComponent<{ agent: Agent }> = ({ ag }, { field: 'message', - name: i18n.translate('xpack.ingestManager.agentEventsList.messageColumnTitle', { + name: i18n.translate('xpack.fleet.agentEventsList.messageColumnTitle', { defaultMessage: 'Message', }), render: (value: string) => ( @@ -168,10 +168,10 @@ export const AgentEventsTable: React.FunctionComponent<{ agent: Agent }> = ({ ag onClick={() => toggleDetails(agentEvent)} aria-label={ itemIdToExpandedRowMap[agentEvent.id] - ? i18n.translate('xpack.ingestManager.agentEventsList.collapseDetailsAriaLabel', { + ? i18n.translate('xpack.fleet.agentEventsList.collapseDetailsAriaLabel', { defaultMessage: 'Hide details', }) - : i18n.translate('xpack.ingestManager.agentEventsList.expandDetailsAriaLabel', { + : i18n.translate('xpack.fleet.agentEventsList.expandDetailsAriaLabel', { defaultMessage: 'Show details', }) } @@ -203,16 +203,15 @@ export const AgentEventsTable: React.FunctionComponent<{ agent: Agent }> = ({ ag value={search} onChange={setSearch} fieldPrefix={AGENT_EVENT_SAVED_OBJECT_TYPE} - placeholder={i18n.translate( - 'xpack.ingestManager.agentEventsList.searchPlaceholderText', - { defaultMessage: 'Search for activity logs' } - )} + placeholder={i18n.translate('xpack.fleet.agentEventsList.searchPlaceholderText', { + defaultMessage: 'Search for activity logs', + })} /> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/metadata_flyout.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/metadata_flyout.tsx index 96c09677a677..f808f4ade107 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/metadata_flyout.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/metadata_flyout.tsx @@ -41,7 +41,7 @@ export const AgentMetadataFlyout: React.FunctionComponent = ({ agent, fly

    @@ -51,7 +51,7 @@ export const AgentMetadataFlyout: React.FunctionComponent = ({ agent, fly

    @@ -62,7 +62,7 @@ export const AgentMetadataFlyout: React.FunctionComponent = ({ agent, fly

    diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/metadata_form.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/metadata_form.tsx index af7e8c674db4..fd8de709c172 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/metadata_form.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/metadata_form.tsx @@ -106,10 +106,7 @@ export const MetadataForm: React.FunctionComponent<{ agent: Agent }> = ({ agent const button = ( setOpen(true)} color={'text'}> - + ); return ( @@ -128,7 +125,7 @@ export const MetadataForm: React.FunctionComponent<{ agent: Agent }> = ({ agent @@ -137,7 +134,7 @@ export const MetadataForm: React.FunctionComponent<{ agent: Agent }> = ({ agent @@ -148,7 +145,7 @@ export const MetadataForm: React.FunctionComponent<{ agent: Agent }> = ({ agent diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/type_labels.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/type_labels.tsx index f597b9c72ab0..dbe18ab33373 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/type_labels.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/type_labels.tsx @@ -12,28 +12,25 @@ import { AgentEvent } from '../../../../types'; export const TYPE_LABEL: { [key in AgentEvent['type']]: JSX.Element } = { STATE: ( - + ), ERROR: ( - + ), ACTION_RESULT: ( ), ACTION: ( - + ), }; @@ -41,16 +38,13 @@ export const TYPE_LABEL: { [key in AgentEvent['type']]: JSX.Element } = { export const SUBTYPE_LABEL: { [key in AgentEvent['subtype']]: JSX.Element } = { RUNNING: ( - + ), STARTING: ( @@ -58,47 +52,38 @@ export const SUBTYPE_LABEL: { [key in AgentEvent['subtype']]: JSX.Element } = { IN_PROGRESS: ( ), CONFIG: ( - + ), FAILED: ( - + ), STOPPING: ( ), STOPPED: ( - + ), DEGRADED: ( @@ -106,7 +91,7 @@ export const SUBTYPE_LABEL: { [key in AgentEvent['subtype']]: JSX.Element } = { DATA_DUMP: ( @@ -114,7 +99,7 @@ export const SUBTYPE_LABEL: { [key in AgentEvent['subtype']]: JSX.Element } = { ACKNOWLEDGED: ( @@ -122,17 +107,14 @@ export const SUBTYPE_LABEL: { [key in AgentEvent['subtype']]: JSX.Element } = { UPDATING: ( ), UNKNOWN: ( - + ), }; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/index.tsx index ddd234aaa1da..7d60ae23deac 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/index.tsx @@ -89,7 +89,7 @@ export const AgentDetailsPage: React.FunctionComponent = () => { size="xs" > @@ -104,7 +104,7 @@ export const AgentDetailsPage: React.FunctionComponent = () => { agentData.item.local_metadata.host.hostname ) : ( { {[ { - label: i18n.translate('xpack.ingestManager.agentDetails.statusLabel', { + label: i18n.translate('xpack.fleet.agentDetails.statusLabel', { defaultMessage: 'Status', }), content: , }, { isDivider: true }, { - label: i18n.translate('xpack.ingestManager.agentDetails.policyLabel', { + label: i18n.translate('xpack.fleet.agentDetails.policyLabel', { defaultMessage: 'Policy', }), content: isAgentPolicyLoading ? ( @@ -150,7 +150,7 @@ export const AgentDetailsPage: React.FunctionComponent = () => { }, { isDivider: true }, { - label: i18n.translate('xpack.ingestManager.agentDetails.agentVersionLabel', { + label: i18n.translate('xpack.fleet.agentDetails.agentVersionLabel', { defaultMessage: 'Agent version', }), content: @@ -165,7 +165,7 @@ export const AgentDetailsPage: React.FunctionComponent = () => { { type="alert" color="warning" content={i18n.translate( - 'xpack.ingestManager.agentDetails.upgradeAvailableTooltip', + 'xpack.fleet.agentDetails.upgradeAvailableTooltip', { defaultMessage: 'Upgrade available', } @@ -225,7 +225,7 @@ export const AgentDetailsPage: React.FunctionComponent = () => { return [ { id: 'activity_log', - name: i18n.translate('xpack.ingestManager.agentDetails.subTabs.activityLogTab', { + name: i18n.translate('xpack.fleet.agentDetails.subTabs.activityLogTab', { defaultMessage: 'Activity log', }), href: getHref('fleet_agent_details', { agentId, tabId: 'activity' }), @@ -233,7 +233,7 @@ export const AgentDetailsPage: React.FunctionComponent = () => { }, { id: 'details', - name: i18n.translate('xpack.ingestManager.agentDetails.subTabs.detailsTab', { + name: i18n.translate('xpack.fleet.agentDetails.subTabs.detailsTab', { defaultMessage: 'Agent details', }), href: getHref('fleet_agent_details', { agentId, tabId: 'details' }), @@ -262,7 +262,7 @@ export const AgentDetailsPage: React.FunctionComponent = () => { } @@ -274,19 +274,16 @@ export const AgentDetailsPage: React.FunctionComponent = () => { } - error={i18n.translate( - 'xpack.ingestManager.agentDetails.agentNotFoundErrorDescription', - { - defaultMessage: 'Cannot find agent ID {agentId}', - values: { - agentId, - }, - } - )} + error={i18n.translate('xpack.fleet.agentDetails.agentNotFoundErrorDescription', { + defaultMessage: 'Cannot find agent ID {agentId}', + values: { + agentId, + }, + })} /> )} diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/components/bulk_actions.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/components/bulk_actions.tsx index b628cc662f82..15b4a7518806 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/components/bulk_actions.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/components/bulk_actions.tsx @@ -88,7 +88,7 @@ export const AgentBulkActions: React.FunctionComponent<{ { name: ( ), @@ -102,7 +102,7 @@ export const AgentBulkActions: React.FunctionComponent<{ { name: ( ), @@ -116,7 +116,7 @@ export const AgentBulkActions: React.FunctionComponent<{ { name: ( ), @@ -130,7 +130,7 @@ export const AgentBulkActions: React.FunctionComponent<{ { name: ( ), @@ -192,7 +192,7 @@ export const AgentBulkActions: React.FunctionComponent<{ {totalAgents > SO_SEARCH_LIMIT ? ( , @@ -201,7 +201,7 @@ export const AgentBulkActions: React.FunctionComponent<{ /> ) : ( @@ -226,7 +226,7 @@ export const AgentBulkActions: React.FunctionComponent<{ onClick={openMenu} > setSelectionMode('query')} > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/index.tsx index bc37338f0439..d46d2aa44274 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_list_page/index.tsx @@ -53,26 +53,26 @@ const REFRESH_INTERVAL_MS = 5000; const statusFilters = [ { status: 'online', - label: i18n.translate('xpack.ingestManager.agentList.statusOnlineFilterText', { + label: i18n.translate('xpack.fleet.agentList.statusOnlineFilterText', { defaultMessage: 'Online', }), }, { status: 'offline', - label: i18n.translate('xpack.ingestManager.agentList.statusOfflineFilterText', { + label: i18n.translate('xpack.fleet.agentList.statusOfflineFilterText', { defaultMessage: 'Offline', }), }, , { status: 'error', - label: i18n.translate('xpack.ingestManager.agentList.statusErrorFilterText', { + label: i18n.translate('xpack.fleet.agentList.statusErrorFilterText', { defaultMessage: 'Error', }), }, { status: 'updating', - label: i18n.translate('xpack.ingestManager.agentList.statusUpdatingFilterText', { + label: i18n.translate('xpack.fleet.agentList.statusUpdatingFilterText', { defaultMessage: 'Updating', }), }, @@ -101,10 +101,7 @@ const RowActions = React.memo<{ href={getHref('fleet_agent_details', { agentId: agent.id })} key="viewAgent" > - + , , @@ -128,12 +125,12 @@ const RowActions = React.memo<{ > {isUnenrolling ? ( ) : ( )} @@ -146,7 +143,7 @@ const RowActions = React.memo<{ }} > , @@ -294,7 +291,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { const columns = [ { field: 'local_metadata.host.hostname', - name: i18n.translate('xpack.ingestManager.agentList.hostColumnTitle', { + name: i18n.translate('xpack.fleet.agentList.hostColumnTitle', { defaultMessage: 'Host', }), render: (host: string, agent: Agent) => ( @@ -306,14 +303,14 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { { field: 'active', width: '120px', - name: i18n.translate('xpack.ingestManager.agentList.statusColumnTitle', { + name: i18n.translate('xpack.fleet.agentList.statusColumnTitle', { defaultMessage: 'Status', }), render: (active: boolean, agent: any) => , }, { field: 'policy_id', - name: i18n.translate('xpack.ingestManager.agentList.policyColumnTitle', { + name: i18n.translate('xpack.fleet.agentList.policyColumnTitle', { defaultMessage: 'Agent policy', }), render: (policyId: string, agent: Agent) => { @@ -333,7 +330,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { @@ -351,7 +348,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { {true && ( <> @@ -366,7 +363,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { { field: 'local_metadata.elastic.agent.version', width: '200px', - name: i18n.translate('xpack.ingestManager.agentList.versionTitle', { + name: i18n.translate('xpack.fleet.agentList.versionTitle', { defaultMessage: 'Version', }), render: (version: string, agent: Agent) => ( @@ -380,7 +377,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => {   @@ -391,14 +388,14 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { }, { field: 'last_checkin', - name: i18n.translate('xpack.ingestManager.agentList.lastCheckinTitle', { + name: i18n.translate('xpack.fleet.agentList.lastCheckinTitle', { defaultMessage: 'Last activity', }), render: (lastCheckin: string, agent: any) => lastCheckin ? : null, }, { - name: i18n.translate('xpack.ingestManager.agentList.actionsColumnTitle', { + name: i18n.translate('xpack.fleet.agentList.actionsColumnTitle', { defaultMessage: 'Actions', }), actions: [ @@ -425,7 +422,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { title={

    @@ -433,10 +430,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { actions={ hasWriteCapabilites ? ( setIsEnrollmentFlyoutOpen(true)}> - + ) : null } @@ -521,7 +515,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { disabled={isAgentPoliciesLoading} > @@ -561,7 +555,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { disabled={isAgentPoliciesLoading} > @@ -595,7 +589,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { }} > @@ -604,7 +598,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { onClick={() => setShowInactive(!showInactive)} > @@ -645,18 +639,18 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { noItemsMessage={ isLoading && agentsRequest.isInitialRequest ? ( ) : isUsingFilter ? ( clearFilters()}> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/agent_policy_selection.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/agent_policy_selection.tsx index 874d42a8db09..758497607c05 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/agent_policy_selection.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/agent_policy_selection.tsx @@ -155,7 +155,7 @@ export const EnrollmentStepAgentPolicy: React.FC = (props) => { prepend={ @@ -172,10 +172,9 @@ export const EnrollmentStepAgentPolicy: React.FC = (props) => { enrollmentAPIKeyId: undefined, }) } - aria-label={i18n.translate( - 'xpack.ingestManager.enrollmentStepAgentPolicy.policySelectAriaLabel', - { defaultMessage: 'Agent policy' } - )} + aria-label={i18n.translate('xpack.fleet.enrollmentStepAgentPolicy.policySelectAriaLabel', { + defaultMessage: 'Agent policy', + })} /> {selectedState.agentPolicyId && ( @@ -190,7 +189,7 @@ export const EnrollmentStepAgentPolicy: React.FC = (props) => { onClick={() => setIsAuthenticationSettingsOpen(!isAuthenticationSettingsOpen)} > @@ -207,7 +206,7 @@ export const EnrollmentStepAgentPolicy: React.FC = (props) => { prepend={ diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx index 05817f28f929..cc7c2ea77895 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx @@ -41,7 +41,7 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({

    @@ -49,7 +49,7 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({ @@ -57,13 +57,13 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({ setMode('managed')}> setMode('standalone')}> @@ -82,7 +82,7 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({ @@ -90,7 +90,7 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({ diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx index e620424f88f4..656493e31e5f 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/managed_instructions.tsx @@ -45,7 +45,7 @@ export const ManagedInstructions = React.memo(({ agentPolicies }) => { DownloadStep(), AgentPolicySelectionStep({ agentPolicies, setSelectedAPIKeyId }), { - title: i18n.translate('xpack.ingestManager.agentEnrollment.stepEnrollAndRunAgentTitle', { + title: i18n.translate('xpack.fleet.agentEnrollment.stepEnrollAndRunAgentTitle', { defaultMessage: 'Enroll and start the Elastic Agent', }), children: apiKey.data && ( @@ -62,7 +62,7 @@ export const ManagedInstructions = React.memo(({ agentPolicies }) => { <> @@ -74,13 +74,13 @@ export const ManagedInstructions = React.memo(({ agentPolicies }) => { ) : ( <> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx index 3e5cf236e63d..a2daf2d10c27 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/standalone_instructions.tsx @@ -75,14 +75,14 @@ export const StandaloneInstructions = React.memo(({ agentPolicies }) => { DownloadStep(), AgentPolicySelectionStep({ agentPolicies, setSelectedPolicyId }), { - title: i18n.translate('xpack.ingestManager.agentEnrollment.stepConfigureAgentTitle', { + title: i18n.translate('xpack.fleet.agentEnrollment.stepConfigureAgentTitle', { defaultMessage: 'Configure the agent', }), children: ( <> elastic-agent.yml, @@ -98,7 +98,7 @@ export const StandaloneInstructions = React.memo(({ agentPolicies }) => { {(copy) => ( @@ -108,7 +108,7 @@ export const StandaloneInstructions = React.memo(({ agentPolicies }) => { @@ -123,14 +123,14 @@ export const StandaloneInstructions = React.memo(({ agentPolicies }) => { ), }, { - title: i18n.translate('xpack.ingestManager.agentEnrollment.stepRunAgentTitle', { + title: i18n.translate('xpack.fleet.agentEnrollment.stepRunAgentTitle', { defaultMessage: 'Start the agent', }), children: ( <> @@ -140,7 +140,7 @@ export const StandaloneInstructions = React.memo(({ agentPolicies }) => { {(copy) => ( @@ -151,20 +151,20 @@ export const StandaloneInstructions = React.memo(({ agentPolicies }) => { ), }, { - title: i18n.translate('xpack.ingestManager.agentEnrollment.stepCheckForDataTitle', { + title: i18n.translate('xpack.fleet.agentEnrollment.stepCheckForDataTitle', { defaultMessage: 'Check for data', }), children: ( <> @@ -181,7 +181,7 @@ export const StandaloneInstructions = React.memo(({ agentPolicies }) => { <> diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx index 0ae61ff421ff..05ef733923d4 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/steps.tsx @@ -13,14 +13,14 @@ import { AgentPolicy } from '../../../../types'; export const DownloadStep = () => { return { - title: i18n.translate('xpack.ingestManager.agentEnrollment.stepDownloadAgentTitle', { + title: i18n.translate('xpack.fleet.agentEnrollment.stepDownloadAgentTitle', { defaultMessage: 'Download the Elastic Agent to your host', }), children: ( <> @@ -32,7 +32,7 @@ export const DownloadStep = () => { iconType="popout" > @@ -51,7 +51,7 @@ export const AgentPolicySelectionStep = ({ setSelectedPolicyId?: (policyId: string) => void; }) => { return { - title: i18n.translate('xpack.ingestManager.agentEnrollment.stepChooseAgentPolicyTitle', { + title: i18n.translate('xpack.fleet.agentEnrollment.stepChooseAgentPolicyTitle', { defaultMessage: 'Choose an agent policy', }), children: ( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_health.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_health.tsx index a16d4e7347ad..45017ac8532d 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_health.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_health.tsx @@ -15,56 +15,38 @@ interface Props { const Status = { Online: ( - + ), Offline: ( - + ), Inactive: ( - + ), Warning: ( - + ), Error: ( - + ), Degraded: ( - + ), Enrolling: ( @@ -72,17 +54,14 @@ const Status = { Unenrolling: ( ), Upgrading: ( - + ), }; @@ -121,7 +100,7 @@ export const AgentHealth: React.FunctionComponent = ({ agent }) => { msLastCheckIn ? ( <> , @@ -133,7 +112,7 @@ export const AgentHealth: React.FunctionComponent = ({ agent }) => { ) : ( ) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_policy_package_badges.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_policy_package_badges.tsx index 0a3d6d54da83..08835cc872b8 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_policy_package_badges.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_policy_package_badges.tsx @@ -25,7 +25,7 @@ export const AgentPolicyPackageBadges: React.FunctionComponent = ({ agent <> = ({ } setIsSubmitting(false); const successMessage = i18n.translate( - 'xpack.ingestManager.agentReassignPolicy.successSingleNotificationTitle', + 'xpack.fleet.agentReassignPolicy.successSingleNotificationTitle', { defaultMessage: 'Agent policy reassigned', } @@ -97,7 +97,7 @@ export const AgentReassignAgentPolicyFlyout: React.FunctionComponent = ({

    @@ -105,7 +105,7 @@ export const AgentReassignAgentPolicyFlyout: React.FunctionComponent = ({ = ({ @@ -146,7 +146,7 @@ export const AgentReassignAgentPolicyFlyout: React.FunctionComponent = ({ @@ -159,7 +159,7 @@ export const AgentReassignAgentPolicyFlyout: React.FunctionComponent = ({ isLoading={isSubmitting} > diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_unenroll_modal/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_unenroll_modal/index.tsx index d756b1f4daf0..74f2303c70c0 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_unenroll_modal/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_unenroll_modal/index.tsx @@ -45,21 +45,19 @@ export const AgentUnenrollAgentModal: React.FunctionComponent = ({ setIsSubmitting(false); if (forceUnenroll) { const successMessage = isSingleAgent - ? i18n.translate( - 'xpack.ingestManager.unenrollAgents.successForceSingleNotificationTitle', - { defaultMessage: 'Agent unenrolled' } - ) - : i18n.translate( - 'xpack.ingestManager.unenrollAgents.successForceMultiNotificationTitle', - { defaultMessage: 'Agents unenrolled' } - ); + ? i18n.translate('xpack.fleet.unenrollAgents.successForceSingleNotificationTitle', { + defaultMessage: 'Agent unenrolled', + }) + : i18n.translate('xpack.fleet.unenrollAgents.successForceMultiNotificationTitle', { + defaultMessage: 'Agents unenrolled', + }); notifications.toasts.addSuccess(successMessage); } else { const successMessage = isSingleAgent - ? i18n.translate('xpack.ingestManager.unenrollAgents.successSingleNotificationTitle', { + ? i18n.translate('xpack.fleet.unenrollAgents.successSingleNotificationTitle', { defaultMessage: 'Unenrolling agent', }) - : i18n.translate('xpack.ingestManager.unenrollAgents.successMultiNotificationTitle', { + : i18n.translate('xpack.fleet.unenrollAgents.successMultiNotificationTitle', { defaultMessage: 'Unenrolling agents', }); notifications.toasts.addSuccess(successMessage); @@ -68,7 +66,7 @@ export const AgentUnenrollAgentModal: React.FunctionComponent = ({ } catch (error) { setIsSubmitting(false); notifications.toasts.addError(error, { - title: i18n.translate('xpack.ingestManager.unenrollAgents.fatalErrorNotificationTitle', { + title: i18n.translate('xpack.fleet.unenrollAgents.fatalErrorNotificationTitle', { defaultMessage: 'Error unenrolling {count, plural, one {agent} other {agents}}', values: { count: agentCount }, }), @@ -82,12 +80,12 @@ export const AgentUnenrollAgentModal: React.FunctionComponent = ({ title={ isSingleAgent ? ( ) : ( @@ -97,7 +95,7 @@ export const AgentUnenrollAgentModal: React.FunctionComponent = ({ onConfirm={onSubmit} cancelButtonText={ } @@ -105,12 +103,12 @@ export const AgentUnenrollAgentModal: React.FunctionComponent = ({ confirmButtonText={ isSingleAgent ? ( ) : ( @@ -121,14 +119,14 @@ export const AgentUnenrollAgentModal: React.FunctionComponent = ({

    {isSingleAgent ? ( ) : ( @@ -138,7 +136,7 @@ export const AgentUnenrollAgentModal: React.FunctionComponent = ({ legend={{ children: ( @@ -149,7 +147,7 @@ export const AgentUnenrollAgentModal: React.FunctionComponent = ({ id="ingestManagerForceUnenrollAgents" label={ = ({ } setIsSubmitting(false); const successMessage = isSingleAgent - ? i18n.translate('xpack.ingestManager.upgradeAgents.successSingleNotificationTitle', { + ? i18n.translate('xpack.fleet.upgradeAgents.successSingleNotificationTitle', { defaultMessage: 'Upgrading agent', }) - : i18n.translate('xpack.ingestManager.upgradeAgents.successMultiNotificationTitle', { + : i18n.translate('xpack.fleet.upgradeAgents.successMultiNotificationTitle', { defaultMessage: 'Upgrading agents', }); notifications.toasts.addSuccess(successMessage); @@ -53,7 +53,7 @@ export const AgentUpgradeAgentModal: React.FunctionComponent = ({ } catch (error) { setIsSubmitting(false); notifications.toasts.addError(error, { - title: i18n.translate('xpack.ingestManager.upgradeAgents.fatalErrorNotificationTitle', { + title: i18n.translate('xpack.fleet.upgradeAgents.fatalErrorNotificationTitle', { defaultMessage: 'Error upgrading {count, plural, one {agent} other {agents}}', values: { count: agentCount }, }), @@ -67,12 +67,12 @@ export const AgentUpgradeAgentModal: React.FunctionComponent = ({ title={ isSingleAgent ? ( ) : ( @@ -82,7 +82,7 @@ export const AgentUpgradeAgentModal: React.FunctionComponent = ({ onConfirm={onSubmit} cancelButtonText={ } @@ -90,12 +90,12 @@ export const AgentUpgradeAgentModal: React.FunctionComponent = ({ confirmButtonText={ isSingleAgent ? ( ) : ( @@ -105,7 +105,7 @@ export const AgentUpgradeAgentModal: React.FunctionComponent = ({

    {isSingleAgent ? ( = ({ /> ) : ( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/list_layout.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/list_layout.tsx index 278beb5dfe35..bf0163fe904e 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/list_layout.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/list_layout.tsx @@ -53,7 +53,7 @@ export const ListLayout: React.FunctionComponent<{}> = ({ children }) => { titleSize="xs" textAlign="right" title={} - description={i18n.translate('xpack.ingestManager.agentListStatus.totalLabel', { + description={i18n.translate('xpack.fleet.agentListStatus.totalLabel', { defaultMessage: 'Agents', })} /> @@ -79,7 +79,7 @@ export const ListLayout: React.FunctionComponent<{}> = ({ children }) => { } - description={i18n.translate('xpack.ingestManager.agentListStatus.onlineLabel', { + description={i18n.translate('xpack.fleet.agentListStatus.onlineLabel', { defaultMessage: 'Online', })} /> @@ -89,7 +89,7 @@ export const ListLayout: React.FunctionComponent<{}> = ({ children }) => { textAlign="right" titleSize="xs" title={} - description={i18n.translate('xpack.ingestManager.agentListStatus.offlineLabel', { + description={i18n.translate('xpack.fleet.agentListStatus.offlineLabel', { defaultMessage: 'Offline', })} /> @@ -99,7 +99,7 @@ export const ListLayout: React.FunctionComponent<{}> = ({ children }) => { textAlign="right" titleSize="xs" title={} - description={i18n.translate('xpack.ingestManager.agentListStatus.errorLabel', { + description={i18n.translate('xpack.fleet.agentListStatus.errorLabel', { defaultMessage: 'Error', })} /> @@ -112,7 +112,7 @@ export const ListLayout: React.FunctionComponent<{}> = ({ children }) => { setIsEnrollmentFlyoutOpen(true)}> @@ -126,7 +126,7 @@ export const ListLayout: React.FunctionComponent<{}> = ({ children }) => {

    - +

    @@ -134,7 +134,7 @@ export const ListLayout: React.FunctionComponent<{}> = ({ children }) => {

    @@ -159,19 +159,14 @@ export const ListLayout: React.FunctionComponent<{}> = ({ children }) => { tabs={ ([ { - name: ( - - ), + name: , isSelected: routeMatch.path === PAGE_ROUTING_PATHS.fleet_agent_list, href: getHref('fleet_agent_list'), }, { name: ( ), diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/components/confirm_delete_modal.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/components/confirm_delete_modal.tsx index a115e03a369a..45fd380a06f3 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/components/confirm_delete_modal.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/components/confirm_delete_modal.tsx @@ -20,28 +20,22 @@ export const ConfirmEnrollmentTokenDelete = (props: Props) => { return ( = ({
    @@ -102,7 +102,7 @@ export const NewEnrollmentTokenFlyout: React.FunctionComponent = ({ @@ -118,7 +118,7 @@ export const NewEnrollmentTokenFlyout: React.FunctionComponent = ({ @@ -132,7 +132,7 @@ export const NewEnrollmentTokenFlyout: React.FunctionComponent = ({

    @@ -144,7 +144,7 @@ export const NewEnrollmentTokenFlyout: React.FunctionComponent = ({ diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/index.tsx index f447469a02df..7e5d07b2319d 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/enrollment_token_list_page/index.tsx @@ -73,10 +73,10 @@ const ApiKeyField: React.FunctionComponent<{ apiKeyId: string }> = ({ apiKeyId } = ({ apiKeyId } )} setState('CONFIRM_VISIBLE')} iconType="trash" color="danger" @@ -178,7 +175,7 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => { const columns = [ { field: 'name', - name: i18n.translate('xpack.ingestManager.enrollmentTokensList.nameTitle', { + name: i18n.translate('xpack.fleet.enrollmentTokensList.nameTitle', { defaultMessage: 'Name', }), render: (value: string) => ( @@ -189,7 +186,7 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => { }, { field: 'id', - name: i18n.translate('xpack.ingestManager.enrollmentTokensList.secretTitle', { + name: i18n.translate('xpack.fleet.enrollmentTokensList.secretTitle', { defaultMessage: 'Secret', }), width: '215px', @@ -199,7 +196,7 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => { }, { field: 'policy_id', - name: i18n.translate('xpack.ingestManager.enrollmentTokensList.policyTitle', { + name: i18n.translate('xpack.fleet.enrollmentTokensList.policyTitle', { defaultMessage: 'Agent policy', }), render: (policyId: string) => { @@ -214,7 +211,7 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => { }, { field: 'created_at', - name: i18n.translate('xpack.ingestManager.enrollmentTokensList.createdAtTitle', { + name: i18n.translate('xpack.fleet.enrollmentTokensList.createdAtTitle', { defaultMessage: 'Created on', }), width: '150px', @@ -226,7 +223,7 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => { }, { field: 'active', - name: i18n.translate('xpack.ingestManager.enrollmentTokensList.activeTitle', { + name: i18n.translate('xpack.fleet.enrollmentTokensList.activeTitle', { defaultMessage: 'Active', }), width: '70px', @@ -237,7 +234,7 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => { }, { field: 'actions', - name: i18n.translate('xpack.ingestManager.enrollmentTokensList.actionsTitle', { + name: i18n.translate('xpack.fleet.enrollmentTokensList.actionsTitle', { defaultMessage: 'Actions', }), width: '70px', @@ -267,7 +264,7 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => { )} @@ -289,7 +286,7 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => { setFlyoutOpen(true)}> @@ -302,12 +299,12 @@ export const EnrollmentTokenListPage: React.FunctionComponent<{}> = () => { noItemsMessage={ enrollmentAPIKeysRequest.isLoading && enrollmentAPIKeysRequest.isInitialRequest ? ( ) : ( ) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/enforce_security.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/enforce_security.tsx index e131da159d6c..7d547228f9c6 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/enforce_security.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/enforce_security.tsx @@ -11,14 +11,14 @@ import { NoDataLayout } from './components/no_data_layout'; export const EnforceSecurityPage = injectI18n(({ intl }) => (

    diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/invalid_license.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/invalid_license.tsx index 883e41fea95b..2632b6435cbd 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/invalid_license.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/invalid_license.tsx @@ -11,14 +11,14 @@ import { NoDataLayout } from './components/no_data_layout'; export const InvalidLicensePage = injectI18n(({ intl }) => (

    diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/no_access.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/no_access.tsx index 5a3afd621682..014ea6c04f2a 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/no_access.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/error_pages/no_access.tsx @@ -11,14 +11,14 @@ import { NoDataLayout } from './components/no_data_layout'; export const NoAccessPage = injectI18n(({ intl }) => (

    diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/setup_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/setup_page/index.tsx index bac551818ec8..884a2a12f71c 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/setup_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/setup_page/index.tsx @@ -86,7 +86,7 @@ export const SetupPage: React.FunctionComponent<{

    @@ -94,7 +94,7 @@ export const SetupPage: React.FunctionComponent<{ @@ -102,7 +102,7 @@ export const SetupPage: React.FunctionComponent<{ @@ -119,26 +119,26 @@ export const SetupPage: React.FunctionComponent<{ @@ -161,7 +161,7 @@ export const SetupPage: React.FunctionComponent<{ xpack.security.authc.api_key.enabled, @@ -173,7 +173,7 @@ export const SetupPage: React.FunctionComponent<{ external > @@ -188,13 +188,13 @@ xpack.security.authc.api_key.enabled: true`} @@ -216,10 +216,7 @@ xpack.security.authc.api_key.enabled: true`} target="_blank" external > - + ), tlsFlag: xpack.fleet.agents.tlsCheckDisabled, @@ -234,7 +231,7 @@ xpack.security.authc.api_key.enabled: true`} )} > @@ -260,7 +257,7 @@ xpack.encryptedSavedObjects.encryptionKey: "something_at_least_32_characters"`} diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_policy_section.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_policy_section.tsx index e54eff1cbd4a..c49f99cfe8a0 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_policy_section.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_policy_section.tsx @@ -32,14 +32,14 @@ export const OverviewPolicySection: React.FC<{ agentPolicies: AgentPolicy[] }> = return ( @@ -50,7 +50,7 @@ export const OverviewPolicySection: React.FC<{ agentPolicies: AgentPolicy[] }> = <> @@ -59,7 +59,7 @@ export const OverviewPolicySection: React.FC<{ agentPolicies: AgentPolicy[] }> = diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_section.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_section.tsx index 482105cdea30..5fbdf62d138d 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_section.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/agent_section.tsx @@ -25,15 +25,15 @@ export const OverviewAgentSection = () => { return ( @@ -44,7 +44,7 @@ export const OverviewAgentSection = () => { <> @@ -53,7 +53,7 @@ export const OverviewAgentSection = () => { @@ -62,7 +62,7 @@ export const OverviewAgentSection = () => { @@ -70,10 +70,7 @@ export const OverviewAgentSection = () => { - + diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/datastream_section.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/datastream_section.tsx index bece6ec074b8..3b645f7aa9d6 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/datastream_section.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/datastream_section.tsx @@ -46,14 +46,14 @@ export const OverviewDatastreamSection: React.FC = () => { return ( @@ -64,7 +64,7 @@ export const OverviewDatastreamSection: React.FC = () => { <> @@ -73,7 +73,7 @@ export const OverviewDatastreamSection: React.FC = () => { @@ -82,7 +82,7 @@ export const OverviewDatastreamSection: React.FC = () => { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/integration_section.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/integration_section.tsx index 1e138ae922af..1ba1424d21b3 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/integration_section.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/components/integration_section.tsx @@ -32,15 +32,15 @@ export const OverviewIntegrationSection: React.FC = () => { return ( @@ -51,7 +51,7 @@ export const OverviewIntegrationSection: React.FC = () => { <> @@ -60,7 +60,7 @@ export const OverviewIntegrationSection: React.FC = () => { @@ -69,7 +69,7 @@ export const OverviewIntegrationSection: React.FC = () => { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx index c2aa98358c3d..c997caa90c65 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx @@ -45,20 +45,17 @@ export const IngestManagerOverview: React.FunctionComponent = () => {

    - +

    {

    @@ -83,7 +80,7 @@ export const IngestManagerOverview: React.FunctionComponent = () => { setIsEnrollmentFlyoutOpen(true)}> diff --git a/x-pack/plugins/ingest_manager/public/plugin.ts b/x-pack/plugins/ingest_manager/public/plugin.ts index a6a514e85da0..6847a39819e8 100644 --- a/x-pack/plugins/ingest_manager/public/plugin.ts +++ b/x-pack/plugins/ingest_manager/public/plugin.ts @@ -82,7 +82,7 @@ export class IngestManagerPlugin core.application.register({ id: PLUGIN_ID, category: DEFAULT_APP_CATEGORIES.management, - title: i18n.translate('xpack.ingestManager.appTitle', { defaultMessage: 'Fleet' }), + title: i18n.translate('xpack.fleet.appTitle', { defaultMessage: 'Fleet' }), order: 9020, euiIconType: 'logoElastic', async mount(params: AppMountParameters) { @@ -109,10 +109,10 @@ export class IngestManagerPlugin deps.home.featureCatalogue.register({ id: 'ingestManager', - title: i18n.translate('xpack.ingestManager.featureCatalogueTitle', { + title: i18n.translate('xpack.fleet.featureCatalogueTitle', { defaultMessage: 'Add Elastic Agent', }), - description: i18n.translate('xpack.ingestManager.featureCatalogueDescription', { + description: i18n.translate('xpack.fleet.featureCatalogueDescription', { defaultMessage: 'Add and manage your fleet of Elastic Agents and integrations.', }), icon: 'indexManagementApp', diff --git a/x-pack/plugins/ingest_manager/server/services/agent_policy_update.ts b/x-pack/plugins/ingest_manager/server/services/agent_policy_update.ts index fe06de765bbf..1ad710ba70e2 100644 --- a/x-pack/plugins/ingest_manager/server/services/agent_policy_update.ts +++ b/x-pack/plugins/ingest_manager/server/services/agent_policy_update.ts @@ -23,6 +23,12 @@ const fakeRequest = ({ url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, } as unknown) as KibanaRequest; export async function agentPolicyUpdateEventHandler( diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_connected_agents.ts b/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_connected_agents.ts index 994ecc64c82a..b9ef36ecaae5 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_connected_agents.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_connected_agents.ts @@ -23,6 +23,12 @@ function getInternalUserSOClient() { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, } as unknown) as KibanaRequest; return appContextService.getInternalUserSOClient(fakeRequest); diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts b/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts index aa48d8fe18e9..c0e854000493 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts @@ -58,6 +58,12 @@ function getInternalUserSOClient() { url: '/', }, }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, } as unknown) as KibanaRequest; return appContextService.getInternalUserSOClient(fakeRequest); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/install.ts index 89811783a7f7..1002eedc4874 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/install.ts @@ -17,6 +17,7 @@ import { CallESAsCurrentUser } from '../../../../types'; import { getInstallation } from '../../packages'; import { deleteTransforms, deleteTransformRefs } from './remove'; import { getAsset } from './common'; +import { appContextService } from '../../../app_context'; interface TransformInstallation { installationName: string; @@ -29,6 +30,7 @@ export const installTransform = async ( callCluster: CallESAsCurrentUser, savedObjectsClient: SavedObjectsClientContract ) => { + const logger = appContextService.getLogger(); const installation = await getInstallation({ savedObjectsClient, pkgName: installablePackage.name, @@ -38,6 +40,9 @@ export const installTransform = async ( previousInstalledTransformEsAssets = installation.installed_es.filter( ({ type, id }) => type === ElasticsearchAssetType.transform ); + logger.info( + `Found previous transform references:\n ${JSON.stringify(previousInstalledTransformEsAssets)}` + ); } // delete all previous transform diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/remove.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/remove.ts index 5b5583a121e5..de7aeb816f76 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/remove.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/remove.ts @@ -24,6 +24,8 @@ export const deleteTransforms = async ( callCluster: CallESAsCurrentUser, transformIds: string[] ) => { + const logger = appContextService.getLogger(); + logger.info(`Deleting currently installed transform ids ${transformIds}`); await Promise.all( transformIds.map(async (transformId) => { // get the index the transform @@ -47,7 +49,7 @@ export const deleteTransforms = async ( path: `/_transform/${transformId}`, ignore: [404], }); - + logger.info(`Deleted: ${transformId}`); if (transformResponse?.transforms) { // expect this to be 1 for (const transform of transformResponse.transforms) { @@ -58,7 +60,7 @@ export const deleteTransforms = async ( }); } } else { - appContextService.getLogger().warn(`cannot find transform for ${transformId}`); + logger.warn(`cannot find transform for ${transformId}`); } }) ); diff --git a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/transform.test.ts b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/transform.test.ts index 2bf0ad12856f..7ca2a32cf770 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/transform.test.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/elasticsearch/transform/transform.test.ts @@ -4,6 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ +import { createAppContextStartContractMock } from '../../../../mocks'; + jest.mock('../../packages/get', () => { return { getInstallation: jest.fn(), getInstallationObject: jest.fn() }; }); @@ -21,11 +23,13 @@ import { getInstallation, getInstallationObject } from '../../packages'; import { getAsset } from './common'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { savedObjectsClientMock } from '../../../../../../../../src/core/server/saved_objects/service/saved_objects_client.mock'; +import { appContextService } from '../../../app_context'; describe('test transform install', () => { let legacyScopedClusterClient: jest.Mocked; let savedObjectsClient: jest.Mocked; beforeEach(() => { + appContextService.start(createAppContextStartContractMock()); legacyScopedClusterClient = { callAsInternalUser: jest.fn(), callAsCurrentUser: jest.fn(), diff --git a/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts b/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts index 2cf94e9c1607..cd0dcba7b97b 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/packages/get.ts @@ -86,7 +86,7 @@ export async function getPackageKeysByStatus( savedObjectsClient: SavedObjectsClientContract, status: InstallationStatus ) { - const allPackages = await getPackages({ savedObjectsClient }); + const allPackages = await getPackages({ savedObjectsClient, experimental: true }); return allPackages.reduce>((acc, pkg) => { if (pkg.status === status) { if (pkg.status === InstallationStatus.installed) { diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_clone/pipelines_clone.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_clone/pipelines_clone.tsx index 6dc7769ac02a..9465117b6b58 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_clone/pipelines_clone.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_clone/pipelines_clone.tsx @@ -9,10 +9,9 @@ import { RouteComponentProps } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { SectionLoading, useKibana } from '../../../shared_imports'; +import { SectionLoading, useKibana, attemptToURIDecode } from '../../../shared_imports'; import { PipelinesCreate } from '../pipelines_create'; -import { attemptToURIDecode } from '../shared'; export interface ParamProps { sourceName: string; diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx index 35ca1635ab9c..7e2e85ab23fb 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_edit/pipelines_edit.tsx @@ -18,11 +18,10 @@ import { import { EuiCallOut } from '@elastic/eui'; import { Pipeline } from '../../../../common/types'; -import { useKibana, SectionLoading } from '../../../shared_imports'; +import { useKibana, SectionLoading, attemptToURIDecode } from '../../../shared_imports'; import { getListPath } from '../../services/navigation'; import { PipelineForm } from '../../components'; -import { attemptToURIDecode } from '../shared'; interface MatchParams { name: string; diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/shared/attempt_to_uri_decode.ts b/x-pack/plugins/ingest_pipelines/public/application/sections/shared/attempt_to_uri_decode.ts deleted file mode 100644 index fe5a0d7932cb..000000000000 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/shared/attempt_to_uri_decode.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export const attemptToURIDecode = (value: string) => { - let result: string; - try { - result = decodeURI(decodeURIComponent(value)); - } catch (e) { - result = value; - } - return result; -}; diff --git a/x-pack/plugins/ingest_pipelines/public/shared_imports.ts b/x-pack/plugins/ingest_pipelines/public/shared_imports.ts index 13de8a74225a..bea3055c13b2 100644 --- a/x-pack/plugins/ingest_pipelines/public/shared_imports.ts +++ b/x-pack/plugins/ingest_pipelines/public/shared_imports.ts @@ -24,6 +24,7 @@ export { XJson, JsonEditor, OnJsonEditorUpdateHandler, + attemptToURIDecode, } from '../../../../src/plugins/es_ui_shared/public/'; export { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx index 5e5e9cda954e..63ee02ac0404 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx @@ -32,16 +32,11 @@ import { ReactExpressionRendererType, } from '../../../../../../src/plugins/expressions/public'; import { prependDatasourceExpression } from './expression_helpers'; -import { debouncedComponent } from '../../debounced_component'; import { trackUiEvent, trackSuggestionEvent } from '../../lens_ui_telemetry'; import { DataPublicPluginStart } from '../../../../../../src/plugins/data/public'; const MAX_SUGGESTIONS_DISPLAYED = 5; -// TODO: Remove this when upstream fix is merged https://github.com/elastic/eui/issues/2329 -// eslint-disable-next-line -const EuiPanelFixed = EuiPanel as React.ComponentType; - export interface SuggestionPanelProps { activeDatasourceId: string | null; datasourceMap: Record; @@ -82,6 +77,7 @@ const PreviewRenderer = ({ className="lnsSuggestionPanel__expressionRenderer" padding="s" expression={expression} + debounce={2000} renderError={() => { return (
    @@ -104,8 +100,6 @@ const PreviewRenderer = ({ ); }; -const DebouncedPreviewRenderer = debouncedComponent(PreviewRenderer, 2000); - const SuggestionPreview = ({ preview, ExpressionRenderer: ExpressionRendererComponent, @@ -126,7 +120,7 @@ const SuggestionPreview = ({ return (
    - {preview.expression ? ( - {preview.title} )} - +
    ); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts index 900cd02622aa..77dc6f97fb23 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts @@ -319,10 +319,10 @@ describe('IndexPattern Data Source', () => { "1", ], "metricsAtAllLevels": Array [ - true, + false, ], "partialRows": Array [ - true, + false, ], "timeFields": Array [ "timestamp", @@ -334,7 +334,7 @@ describe('IndexPattern Data Source', () => { Object { "arguments": Object { "idMap": Array [ - "{\\"col--1-col1\\":{\\"label\\":\\"Count of records\\",\\"dataType\\":\\"number\\",\\"isBucketed\\":false,\\"sourceField\\":\\"Records\\",\\"operationType\\":\\"count\\",\\"id\\":\\"col1\\"},\\"col-2-col2\\":{\\"label\\":\\"Date\\",\\"dataType\\":\\"date\\",\\"isBucketed\\":true,\\"operationType\\":\\"date_histogram\\",\\"sourceField\\":\\"timestamp\\",\\"params\\":{\\"interval\\":\\"1d\\"},\\"id\\":\\"col2\\"}}", + "{\\"col-0-col1\\":{\\"label\\":\\"Count of records\\",\\"dataType\\":\\"number\\",\\"isBucketed\\":false,\\"sourceField\\":\\"Records\\",\\"operationType\\":\\"count\\",\\"id\\":\\"col1\\"},\\"col-1-col2\\":{\\"label\\":\\"Date\\",\\"dataType\\":\\"date\\",\\"isBucketed\\":true,\\"operationType\\":\\"date_histogram\\",\\"sourceField\\":\\"timestamp\\",\\"params\\":{\\"interval\\":\\"1d\\"},\\"id\\":\\"col2\\"}}", ], }, "function": "lens_rename_columns", @@ -392,6 +392,58 @@ describe('IndexPattern Data Source', () => { expect(ast.chain[0].arguments.timeFields).toEqual(['timestamp', 'another_datefield']); }); + it('should rename the output from esaggs when using flat query', () => { + const queryBaseState: IndexPatternBaseState = { + currentIndexPatternId: '1', + layers: { + first: { + indexPatternId: '1', + columnOrder: ['bucket1', 'bucket2', 'metric'], + columns: { + metric: { + label: 'Count of records', + dataType: 'number', + isBucketed: false, + sourceField: 'Records', + operationType: 'count', + }, + bucket1: { + label: 'Date', + dataType: 'date', + isBucketed: true, + operationType: 'date_histogram', + sourceField: 'timestamp', + params: { + interval: '1d', + }, + }, + bucket2: { + label: 'Terms', + dataType: 'string', + isBucketed: true, + operationType: 'terms', + sourceField: 'geo.src', + params: { + orderBy: { type: 'alphabetical' }, + orderDirection: 'asc', + size: 10, + }, + }, + }, + }, + }, + }; + + const state = enrichBaseState(queryBaseState); + const ast = indexPatternDatasource.toExpression(state, 'first') as Ast; + expect(ast.chain[0].arguments.metricsAtAllLevels).toEqual([false]); + expect(JSON.parse(ast.chain[1].arguments.idMap[0] as string)).toEqual({ + 'col-0-bucket1': expect.any(Object), + 'col-1-bucket2': expect.any(Object), + 'col-2-metric': expect.any(Object), + }); + }); + it('should not put date fields used outside date_histograms to the esaggs timeFields parameter', async () => { const queryBaseState: IndexPatternBaseState = { currentIndexPatternId: '1', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts index e2c4323b56c2..ea7aa62054e5 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts @@ -29,34 +29,16 @@ function getExpressionForLayer( } const columnEntries = columnOrder.map((colId) => [colId, columns[colId]] as const); - const bucketsCount = columnEntries.filter(([, entry]) => entry.isBucketed).length; - const metricsCount = columnEntries.length - bucketsCount; if (columnEntries.length) { const aggs = columnEntries.map(([colId, col]) => { return getEsAggsConfig(col, colId); }); - /** - * Because we are turning on metrics at all levels, the sequence generation - * logic here is more complicated. Examples follow: - * - * Example 1: [Count] - * Output: [`col-0-count`] - * - * Example 2: [Terms, Terms, Count] - * Output: [`col-0-terms0`, `col-2-terms1`, `col-3-count`] - * - * Example 3: [Terms, Terms, Count, Max] - * Output: [`col-0-terms0`, `col-3-terms1`, `col-4-count`, `col-5-max`] - */ const idMap = columnEntries.reduce((currentIdMap, [colId, column], index) => { - const newIndex = column.isBucketed - ? index * (metricsCount + 1) // Buckets are spaced apart by N + 1 - : (index ? index + 1 : 0) - bucketsCount + (bucketsCount - 1) * (metricsCount + 1); return { ...currentIdMap, - [`col-${columnEntries.length === 1 ? 0 : newIndex}-${colId}`]: { + [`col-${columnEntries.length === 1 ? 0 : index}-${colId}`]: { ...column, id: colId, }, @@ -122,8 +104,8 @@ function getExpressionForLayer( function: 'esaggs', arguments: { index: [indexPattern.id], - metricsAtAllLevels: [true], - partialRows: [true], + metricsAtAllLevels: [false], + partialRows: [false], includeFormatHints: [true], timeFields: allDateHistogramFields, aggConfigs: [JSON.stringify(aggs)], diff --git a/x-pack/plugins/lens/public/pie_visualization/render_function.tsx b/x-pack/plugins/lens/public/pie_visualization/render_function.tsx index cb2458a76967..d4c85ce9b884 100644 --- a/x-pack/plugins/lens/public/pie_visualization/render_function.tsx +++ b/x-pack/plugins/lens/public/pie_visualization/render_function.tsx @@ -27,8 +27,8 @@ import { import { FormatFactory, LensFilterEvent } from '../types'; import { VisualizationContainer } from '../visualization_container'; import { CHART_NAMES, DEFAULT_PERCENT_DECIMALS } from './constants'; -import { ColumnGroups, PieExpressionProps } from './types'; -import { getSliceValueWithFallback, getFilterContext } from './render_helpers'; +import { PieExpressionProps } from './types'; +import { getSliceValue, getFilterContext } from './render_helpers'; import { EmptyPlaceholder } from '../shared_components'; import './visualization.scss'; import { desanitizeFilterContext } from '../utils'; @@ -72,21 +72,6 @@ export function PieComponent( }); } - // The datatable for pie charts should include subtotals, like this: - // [bucket, subtotal, bucket, count] - // But the user only configured [bucket, bucket, count] - const columnGroups: ColumnGroups = []; - firstTable.columns.forEach((col) => { - if (groups.includes(col.id)) { - columnGroups.push({ - col, - metrics: [], - }); - } else if (columnGroups.length > 0) { - columnGroups[columnGroups.length - 1].metrics.push(col); - } - }); - const fillLabel: Partial = { textInvertible: false, valueFont: { @@ -100,7 +85,9 @@ export function PieComponent( fillLabel.valueFormatter = () => ''; } - const layers: PartitionLayer[] = columnGroups.map(({ col }, layerIndex) => { + const bucketColumns = firstTable.columns.filter((col) => groups.includes(col.id)); + + const layers: PartitionLayer[] = bucketColumns.map((col, layerIndex) => { return { groupByRollup: (d: Datum) => d[col.id] ?? EMPTY_SLICE, showAccessor: (d: Datum) => d !== EMPTY_SLICE, @@ -116,7 +103,7 @@ export function PieComponent( fillLabel: isDarkMode && shape === 'treemap' && - layerIndex < columnGroups.length - 1 && + layerIndex < bucketColumns.length - 1 && categoryDisplay !== 'hide' ? { ...fillLabel, textColor: euiDarkVars.euiTextColor } : fillLabel, @@ -136,10 +123,10 @@ export function PieComponent( if (shape === 'treemap') { // Only highlight the innermost color of the treemap, as it accurately represents area - return layerIndex < columnGroups.length - 1 ? 'rgba(0,0,0,0)' : outputColor; + return layerIndex < bucketColumns.length - 1 ? 'rgba(0,0,0,0)' : outputColor; } - const lighten = (d.depth - 1) / (columnGroups.length * 2); + const lighten = (d.depth - 1) / (bucketColumns.length * 2); return color(outputColor, 'hsl').lighten(lighten).hex(); }, }, @@ -198,8 +185,6 @@ export function PieComponent( setState({ isReady: true }); }, []); - const reverseGroups = [...columnGroups].reverse(); - const hasNegative = firstTable.rows.some((row) => { const value = row[metricColumn.id]; return typeof value === 'number' && value < 0; @@ -243,16 +228,12 @@ export function PieComponent( showLegend={ !hideLabels && (legendDisplay === 'show' || - (legendDisplay === 'default' && columnGroups.length > 1 && shape !== 'treemap')) + (legendDisplay === 'default' && bucketColumns.length > 1 && shape !== 'treemap')) } legendPosition={legendPosition || Position.Right} legendMaxDepth={nestedLegend ? undefined : 1 /* Color is based only on first layer */} onElementClick={(args) => { - const context = getFilterContext( - args[0][0] as LayerValue[], - columnGroups.map(({ col }) => col.id), - firstTable - ); + const context = getFilterContext(args[0][0] as LayerValue[], groups, firstTable); onClickValue(desanitizeFilterContext(context)); }} @@ -262,7 +243,7 @@ export function PieComponent( getSliceValueWithFallback(d, reverseGroups, metricColumn)} + valueAccessor={(d: Datum) => getSliceValue(d, metricColumn)} percentFormatter={(d: number) => percentFormatter.convert(d / 100)} valueGetter={hideLabels || numberDisplay === 'value' ? undefined : 'percent'} valueFormatter={(d: number) => (hideLabels ? '' : formatters[metricColumn.id].convert(d))} diff --git a/x-pack/plugins/lens/public/pie_visualization/render_helpers.test.ts b/x-pack/plugins/lens/public/pie_visualization/render_helpers.test.ts index d9ccda2a99ab..22c63cd67281 100644 --- a/x-pack/plugins/lens/public/pie_visualization/render_helpers.test.ts +++ b/x-pack/plugins/lens/public/pie_visualization/render_helpers.test.ts @@ -5,86 +5,47 @@ */ import { Datatable } from 'src/plugins/expressions/public'; -import { getSliceValueWithFallback, getFilterContext } from './render_helpers'; -import { ColumnGroups } from './types'; +import { getSliceValue, getFilterContext } from './render_helpers'; describe('render helpers', () => { - describe('#getSliceValueWithFallback', () => { - describe('without fallback', () => { - const columnGroups: ColumnGroups = [ - { col: { id: 'a', name: 'A', meta: { type: 'string' } }, metrics: [] }, - { col: { id: 'b', name: 'C', meta: { type: 'string' } }, metrics: [] }, - ]; - - it('returns the metric when positive number', () => { - expect( - getSliceValueWithFallback({ a: 'Cat', b: 'Home', c: 5 }, columnGroups, { + describe('#getSliceValue', () => { + it('returns the metric when positive number', () => { + expect( + getSliceValue( + { a: 'Cat', b: 'Home', c: 5 }, + { id: 'c', name: 'C', meta: { type: 'number' }, - }) - ).toEqual(5); - }); + } + ) + ).toEqual(5); + }); - it('returns the metric when negative number', () => { - expect( - getSliceValueWithFallback({ a: 'Cat', b: 'Home', c: -100 }, columnGroups, { + it('returns the metric when negative number', () => { + expect( + getSliceValue( + { a: 'Cat', b: 'Home', c: -100 }, + { id: 'c', name: 'C', meta: { type: 'number' }, - }) - ).toEqual(-100); - }); + } + ) + ).toEqual(-100); + }); - it('returns epsilon when metric is 0 without fallback', () => { - expect( - getSliceValueWithFallback({ a: 'Cat', b: 'Home', c: 0 }, columnGroups, { + it('returns epsilon when metric is 0 without fallback', () => { + expect( + getSliceValue( + { a: 'Cat', b: 'Home', c: 0 }, + { id: 'c', name: 'C', meta: { type: 'number' }, - }) - ).toEqual(Number.EPSILON); - }); - }); - - describe('fallback behavior', () => { - const columnGroups: ColumnGroups = [ - { - col: { id: 'a', name: 'A', meta: { type: 'string' } }, - metrics: [{ id: 'a_subtotal', name: '', meta: { type: 'number' } }], - }, - { col: { id: 'b', name: 'C', meta: { type: 'string' } }, metrics: [] }, - ]; - - it('falls back to metric from previous column if available', () => { - expect( - getSliceValueWithFallback( - { a: 'Cat', a_subtotal: 5, b: 'Home', c: undefined }, - columnGroups, - { id: 'c', name: 'C', meta: { type: 'number' } } - ) - ).toEqual(5); - }); - - it('uses epsilon if fallback is 0', () => { - expect( - getSliceValueWithFallback( - { a: 'Cat', a_subtotal: 0, b: 'Home', c: undefined }, - columnGroups, - { id: 'c', name: 'C', meta: { type: 'number' } } - ) - ).toEqual(Number.EPSILON); - }); - - it('uses epsilon if fallback is missing', () => { - expect( - getSliceValueWithFallback( - { a: 'Cat', a_subtotal: undefined, b: 'Home', c: undefined }, - columnGroups, - { id: 'c', name: 'C', meta: { type: 'number' } } - ) - ).toEqual(Number.EPSILON); - }); + } + ) + ).toEqual(Number.EPSILON); }); }); diff --git a/x-pack/plugins/lens/public/pie_visualization/render_helpers.ts b/x-pack/plugins/lens/public/pie_visualization/render_helpers.ts index 26b4f9ccda85..978afcca6a55 100644 --- a/x-pack/plugins/lens/public/pie_visualization/render_helpers.ts +++ b/x-pack/plugins/lens/public/pie_visualization/render_helpers.ts @@ -6,22 +6,13 @@ import { Datum, LayerValue } from '@elastic/charts'; import { Datatable, DatatableColumn } from 'src/plugins/expressions/public'; -import { ColumnGroups } from './types'; import { LensFilterEvent } from '../types'; -export function getSliceValueWithFallback( - d: Datum, - reverseGroups: ColumnGroups, - metricColumn: DatatableColumn -) { +export function getSliceValue(d: Datum, metricColumn: DatatableColumn) { if (typeof d[metricColumn.id] === 'number' && d[metricColumn.id] !== 0) { return d[metricColumn.id]; } - // Sometimes there is missing data for outer groups - // When there is missing data, we fall back to the next groups - // This creates a sunburst effect - const hasMetric = reverseGroups.find((group) => group.metrics.length && d[group.metrics[0].id]); - return hasMetric ? d[hasMetric.metrics[0].id] || Number.EPSILON : Number.EPSILON; + return Number.EPSILON; } export function getFilterContext( diff --git a/x-pack/plugins/lens/public/pie_visualization/types.ts b/x-pack/plugins/lens/public/pie_visualization/types.ts index 0596e54870a9..54bececa13c2 100644 --- a/x-pack/plugins/lens/public/pie_visualization/types.ts +++ b/x-pack/plugins/lens/public/pie_visualization/types.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { DatatableColumn } from 'src/plugins/expressions/public'; import { LensMultiTable } from '../types'; export interface SharedLayerState { @@ -38,8 +37,3 @@ export interface PieExpressionProps { data: LensMultiTable; args: PieExpressionArgs; } - -export type ColumnGroups = Array<{ - col: DatatableColumn; - metrics: DatatableColumn[]; -}>; diff --git a/x-pack/plugins/licensing/public/services/feature_usage_service.mock.ts b/x-pack/plugins/licensing/public/services/feature_usage_service.mock.ts index b2390ea35c14..eb07a07d3b52 100644 --- a/x-pack/plugins/licensing/public/services/feature_usage_service.mock.ts +++ b/x-pack/plugins/licensing/public/services/feature_usage_service.mock.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { FeatureUsageService, diff --git a/x-pack/plugins/licensing/server/services/feature_usage_service.mock.ts b/x-pack/plugins/licensing/server/services/feature_usage_service.mock.ts index f247c6ffcb52..b882219b2e29 100644 --- a/x-pack/plugins/licensing/server/services/feature_usage_service.mock.ts +++ b/x-pack/plugins/licensing/server/services/feature_usage_service.mock.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import type { PublicMethodsOf } from '@kbn/utility-types'; import { FeatureUsageService, diff --git a/x-pack/plugins/maps/public/classes/tooltips/join_tooltip_property.ts b/x-pack/plugins/maps/public/classes/tooltips/join_tooltip_property.ts index fad6d6b84f77..efdede82a744 100644 --- a/x-pack/plugins/maps/public/classes/tooltips/join_tooltip_property.ts +++ b/x-pack/plugins/maps/public/classes/tooltips/join_tooltip_property.ts @@ -40,7 +40,8 @@ export class JoinTooltipProperty implements ITooltipProperty { async getESFilters(): Promise { const esFilters = []; if (this._tooltipProperty.isFilterable()) { - esFilters.push(...(await this._tooltipProperty.getESFilters())); + const filters = await this._tooltipProperty.getESFilters(); + esFilters.push(...filters); } for (let i = 0; i < this._leftInnerJoins.length; i++) { @@ -51,7 +52,8 @@ export class JoinTooltipProperty implements ITooltipProperty { this._tooltipProperty.getRawValue() ); if (esTooltipProperty) { - esFilters.push(...(await esTooltipProperty.getESFilters())); + const filters = await esTooltipProperty.getESFilters(); + esFilters.push(...filters); } } catch (e) { // eslint-disable-next-line no-console diff --git a/x-pack/plugins/maps/public/lazy_load_bundle/lazy/index.ts b/x-pack/plugins/maps/public/lazy_load_bundle/lazy/index.ts index 782d645dc230..067f213603fe 100644 --- a/x-pack/plugins/maps/public/lazy_load_bundle/lazy/index.ts +++ b/x-pack/plugins/maps/public/lazy_load_bundle/lazy/index.ts @@ -15,7 +15,7 @@ export * from '../../actions'; export * from '../../selectors/map_selectors'; export * from '../../routing/bootstrap/get_initial_layers'; export * from '../../embeddable/merge_input_with_saved_map'; -export * from '../../routing/maps_router'; +export { renderApp } from '../../routing/render_app'; export * from '../../classes/layers/solution_layers/security'; export { registerLayerWizard } from '../../classes/layers/layer_wizard_registry'; export { registerSource } from '../../classes/sources/source_registry'; diff --git a/x-pack/plugins/maps/public/routing/maps_router.tsx b/x-pack/plugins/maps/public/routing/render_app.tsx similarity index 81% rename from x-pack/plugins/maps/public/routing/maps_router.tsx rename to x-pack/plugins/maps/public/routing/render_app.tsx index d7e6e6e07995..65cccc53f504 100644 --- a/x-pack/plugins/maps/public/routing/maps_router.tsx +++ b/x-pack/plugins/maps/public/routing/render_app.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; -import { Router, Switch, Route, Redirect, RouteComponentProps } from 'react-router-dom'; +import { Router, Switch, Route, Redirect } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { Provider } from 'react-redux'; import { AppMountParameters } from 'kibana/public'; @@ -24,13 +24,12 @@ import { } from '../../../../../src/plugins/kibana_utils/public'; import { getStore } from './store_operations'; import { LoadListAndRender } from './routes/list/load_list_and_render'; -import { LoadMapAndRender } from './routes/maps_app/load_map_and_render'; +import { MapApp } from './routes/map_app'; export let goToSpecifiedPath: (path: string) => void; export let kbnUrlStateStorage: IKbnUrlStateStorage; export async function renderApp({ - appBasePath, element, history, onAppLeave, @@ -43,29 +42,6 @@ export async function renderApp({ ...withNotifyOnErrors(getToasts()), }); - render( - , - element - ); - - return () => { - unmountComponentAtNode(element); - }; -} - -interface Props { - history: AppMountParameters['history'] | RouteComponentProps['history']; - appBasePath: AppMountParameters['appBasePath']; - onAppLeave: AppMountParameters['onAppLeave']; - setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; -} - -const App: React.FC = ({ history, appBasePath, onAppLeave, setHeaderActionMenu }) => { const store = getStore(); const I18nContext = getCoreI18n().Context; @@ -88,7 +64,7 @@ const App: React.FC = ({ history, appBasePath, onAppLeave, setHeaderActio }); } - return ( + render( @@ -96,7 +72,7 @@ const App: React.FC = ({ history, appBasePath, onAppLeave, setHeaderActio ( - = ({ history, appBasePath, onAppLeave, setHeaderActio exact path={`/map`} render={() => ( - = ({ history, appBasePath, onAppLeave, setHeaderActio - + , + element ); -}; + + return () => { + unmountComponentAtNode(element); + }; +} diff --git a/x-pack/plugins/maps/public/routing/routes/list/maps_list_view.tsx b/x-pack/plugins/maps/public/routing/routes/list/maps_list_view.tsx index 3b0891a4fd44..ca92442ae93e 100644 --- a/x-pack/plugins/maps/public/routing/routes/list/maps_list_view.tsx +++ b/x-pack/plugins/maps/public/routing/routes/list/maps_list_view.tsx @@ -30,7 +30,7 @@ import { EuiBasicTableColumn, } from '@elastic/eui/src/components/basic_table/basic_table'; import { EuiTableSortingType } from '@elastic/eui'; -import { goToSpecifiedPath } from '../../maps_router'; +import { goToSpecifiedPath } from '../../render_app'; // @ts-expect-error import { addHelpMenuToAppChrome } from '../../../help_menu_util'; import { APP_ID, MAP_PATH } from '../../../../common/constants'; diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/get_breadcrumbs.test.tsx b/x-pack/plugins/maps/public/routing/routes/map_app/get_breadcrumbs.test.tsx similarity index 96% rename from x-pack/plugins/maps/public/routing/routes/maps_app/get_breadcrumbs.test.tsx rename to x-pack/plugins/maps/public/routing/routes/map_app/get_breadcrumbs.test.tsx index e8e0e583a7c6..3516daf52696 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/get_breadcrumbs.test.tsx +++ b/x-pack/plugins/maps/public/routing/routes/map_app/get_breadcrumbs.test.tsx @@ -7,7 +7,7 @@ import { getBreadcrumbs } from './get_breadcrumbs'; jest.mock('../../../kibana_services', () => {}); -jest.mock('../../maps_router', () => {}); +jest.mock('../../render_app', () => {}); const getHasUnsavedChanges = () => { return false; diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/get_breadcrumbs.tsx b/x-pack/plugins/maps/public/routing/routes/map_app/get_breadcrumbs.tsx similarity index 96% rename from x-pack/plugins/maps/public/routing/routes/maps_app/get_breadcrumbs.tsx rename to x-pack/plugins/maps/public/routing/routes/map_app/get_breadcrumbs.tsx index d9b60b670b93..88dba0f83ec2 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/get_breadcrumbs.tsx +++ b/x-pack/plugins/maps/public/routing/routes/map_app/get_breadcrumbs.tsx @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; import { getCoreOverlays, getNavigateToApp } from '../../../kibana_services'; -import { goToSpecifiedPath } from '../../maps_router'; +import { goToSpecifiedPath } from '../../render_app'; import { getAppTitle } from '../../../../common/i18n_getters'; export const unsavedChangesWarning = i18n.translate( diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/index.ts b/x-pack/plugins/maps/public/routing/routes/map_app/index.ts similarity index 94% rename from x-pack/plugins/maps/public/routing/routes/maps_app/index.ts rename to x-pack/plugins/maps/public/routing/routes/map_app/index.ts index 812d7fcf3098..0b9f0cfe33e4 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/index.ts +++ b/x-pack/plugins/maps/public/routing/routes/map_app/index.ts @@ -8,7 +8,7 @@ import { connect } from 'react-redux'; import { ThunkDispatch } from 'redux-thunk'; import { AnyAction } from 'redux'; import { Filter, Query, TimeRange } from 'src/plugins/data/public'; -import { MapsAppView } from './maps_app_view'; +import { MapApp } from './map_app'; import { getFlyoutDisplay, getIsFullScreen } from '../../../selectors/ui_selectors'; import { getFilters, @@ -99,5 +99,5 @@ function mapDispatchToProps(dispatch: ThunkDispatch { +export class MapApp extends React.Component { _globalSyncUnsubscribe: (() => void) | null = null; _globalSyncChangeMonitorSubscription: Subscription | null = null; _appSyncUnsubscribe: (() => void) | null = null; @@ -134,8 +139,6 @@ export class MapsAppView extends React.Component { this._initMap(); - this._setBreadcrumbs(); - this.props.onAppLeave((actions) => { if (this._hasUnsavedChanges()) { return actions.confirm(unsavedChangesWarning, unsavedChangesTitle); @@ -165,7 +168,11 @@ export class MapsAppView extends React.Component { } _hasUnsavedChanges = () => { - const savedLayerList = this.props.savedMap.getLayerList(); + if (!this.state.savedMap) { + return false; + } + + const savedLayerList = this.state.savedMap.getLayerList(); return !savedLayerList ? !_.isEqual(this.props.layerListConfigOnly, this.state.initialLayerListConfig) : // savedMap stores layerList as a JSON string using JSON.stringify. @@ -176,9 +183,9 @@ export class MapsAppView extends React.Component { !_.isEqual(JSON.parse(JSON.stringify(this.props.layerListConfigOnly)), savedLayerList); }; - _setBreadcrumbs = () => { + _setBreadcrumbs = (title: string) => { const breadcrumbs = getBreadcrumbs({ - title: this.props.savedMap.title, + title, getHasUnsavedChanges: this._hasUnsavedChanges, originatingApp: this.state.originatingApp, getAppNameFromId: this.props.stateTransfer.getAppNameFromId, @@ -255,13 +262,12 @@ export class MapsAppView extends React.Component { updateGlobalState(updatedGlobalState, !this.state.initialized); }; - _initMapAndLayerSettings() { + _initMapAndLayerSettings(savedMap: ISavedGisMap) { const globalState: MapsGlobalState = getGlobalState(); - const mapStateJSON = this.props.savedMap.mapStateJSON; let savedObjectFilters = []; - if (mapStateJSON) { - const mapState = JSON.parse(mapStateJSON); + if (savedMap.mapStateJSON) { + const mapState = JSON.parse(savedMap.mapStateJSON); if (mapState.filters) { savedObjectFilters = mapState.filters; } @@ -269,7 +275,7 @@ export class MapsAppView extends React.Component { const appFilters = this._appStateManager.getFilters() || []; const query = getInitialQuery({ - mapStateJSON, + mapStateJSON: savedMap.mapStateJSON, appState: this._appStateManager.getAppState(), }); if (query) { @@ -280,22 +286,19 @@ export class MapsAppView extends React.Component { filters: [..._.get(globalState, 'filters', []), ...appFilters, ...savedObjectFilters], query, time: getInitialTimeFilters({ - mapStateJSON, + mapStateJSON: savedMap.mapStateJSON, globalState, }), }); this._onRefreshConfigChange( getInitialRefreshConfig({ - mapStateJSON, + mapStateJSON: savedMap.mapStateJSON, globalState, }) ); - const layerList = getInitialLayers( - this.props.savedMap.layerListJSON, - getInitialLayersFromUrlParam() - ); + const layerList = getInitialLayers(savedMap.layerListJSON, getInitialLayersFromUrlParam()); this.props.replaceLayerList(layerList); this.setState({ initialLayerListConfig: copyPersistentState(layerList), @@ -345,13 +348,43 @@ export class MapsAppView extends React.Component { }); }; - _initMap() { - this._initMapAndLayerSettings(); + async _loadSavedMap(): Promise { + let savedMap: ISavedGisMap | null = null; + try { + savedMap = await getMapsSavedObjectLoader().get(this.props.savedMapId); + } catch (err) { + if (this._isMounted) { + getToasts().addWarning({ + title: i18n.translate('xpack.maps.loadMap.errorAttemptingToLoadSavedMap', { + defaultMessage: `Unable to load map`, + }), + text: `${err.message}`, + }); + goToSpecifiedPath('/'); + } + } + + return savedMap; + } + + async _initMap() { + const savedMap = await this._loadSavedMap(); + if (!this._isMounted || !savedMap) { + return; + } + + this._setBreadcrumbs(savedMap.title); + getCoreChrome().docTitle.change(savedMap.title); + if (this.props.savedMapId) { + getCoreChrome().recentlyAccessed.add(savedMap.getFullPath(), savedMap.title, savedMap.id!); + } + + this._initMapAndLayerSettings(savedMap); this.props.clearUi(); - if (this.props.savedMap.mapStateJSON) { - const mapState = JSON.parse(this.props.savedMap.mapStateJSON); + if (savedMap.mapStateJSON) { + const mapState = JSON.parse(savedMap.mapStateJSON); this.props.setGotoWithCenter({ lat: mapState.center.lat, lon: mapState.center.lon, @@ -362,22 +395,22 @@ export class MapsAppView extends React.Component { } } - if (this.props.savedMap.uiStateJSON) { - const uiState = JSON.parse(this.props.savedMap.uiStateJSON); + if (savedMap.uiStateJSON) { + const uiState = JSON.parse(savedMap.uiStateJSON); this.props.setIsLayerTOCOpen(_.get(uiState, 'isLayerTOCOpen', DEFAULT_IS_LAYER_TOC_OPEN)); this.props.setOpenTOCDetails(_.get(uiState, 'openTOCDetails', [])); } - this.setState({ initialized: true }); + this.setState({ initialized: true, savedMap }); } _renderTopNav() { - if (this.props.isFullScreen) { + if (this.props.isFullScreen || !this.state.savedMap) { return null; } const topNavConfig = getTopNavConfig({ - savedMap: this.props.savedMap, + savedMap: this.state.savedMap, isOpenSettingsDisabled: this.props.isOpenSettingsDisabled, isSaveDisabled: this.props.isSaveDisabled, enableFullScreen: this.props.enableFullScreen, @@ -452,18 +485,22 @@ export class MapsAppView extends React.Component { }; render() { - return this.state.initialized ? ( + if (!this.state.initialized || !this.state.savedMap) { + return null; + } + + return (
    {this._renderTopNav()}

    {`screenTitle placeholder`}

    - ) : null; + ); } } diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx b/x-pack/plugins/maps/public/routing/routes/map_app/top_nav_config.tsx similarity index 98% rename from x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx rename to x-pack/plugins/maps/public/routing/routes/map_app/top_nav_config.tsx index 917abebfb6b2..c60f44093541 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx +++ b/x-pack/plugins/maps/public/routing/routes/map_app/top_nav_config.tsx @@ -21,7 +21,7 @@ import { showSaveModal, } from '../../../../../../../src/plugins/saved_objects/public'; import { MAP_SAVED_OBJECT_TYPE } from '../../../../common/constants'; -import { goToSpecifiedPath } from '../../maps_router'; +import { goToSpecifiedPath } from '../../render_app'; import { ISavedGisMap } from '../../bootstrap/services/saved_gis_map'; import { EmbeddableStateTransfer } from '../../../../../../../src/plugins/embeddable/public'; @@ -43,7 +43,7 @@ export function getTopNavConfig({ enableFullScreen: () => void; openMapSettings: () => void; inspectorAdapters: Adapters; - setBreadcrumbs: () => void; + setBreadcrumbs: (title: string) => void; stateTransfer?: EmbeddableStateTransfer; originatingApp?: string; cutOriginatingAppConnection: () => void; @@ -104,7 +104,7 @@ export function getTopNavConfig({ }); getCoreChrome().docTitle.change(savedMap.title); - setBreadcrumbs(); + setBreadcrumbs(savedMap.title); goToSpecifiedPath(`/map/${savedObjectId}${window.location.hash}`); const newlyCreated = newCopyOnSave || isNewMap; diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.tsx b/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.tsx deleted file mode 100644 index b980756daad2..000000000000 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.tsx +++ /dev/null @@ -1,86 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { Redirect } from 'react-router-dom'; -import { AppMountParameters } from 'kibana/public'; -import { EmbeddableStateTransfer } from 'src/plugins/embeddable/public'; -import { getCoreChrome, getToasts } from '../../../kibana_services'; -import { getMapsSavedObjectLoader } from '../../bootstrap/services/gis_map_saved_object_loader'; -import { MapsAppView } from '.'; -import { ISavedGisMap } from '../../bootstrap/services/saved_gis_map'; - -interface Props { - savedMapId?: string; - onAppLeave: AppMountParameters['onAppLeave']; - stateTransfer: EmbeddableStateTransfer; - originatingApp?: string; - setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; -} - -interface State { - savedMap?: ISavedGisMap; - failedToLoad: boolean; -} - -export const LoadMapAndRender = class extends React.Component { - _isMounted: boolean = false; - state: State = { - savedMap: undefined, - failedToLoad: false, - }; - - componentDidMount() { - this._isMounted = true; - this._loadSavedMap(); - } - - componentWillUnmount() { - this._isMounted = false; - } - - async _loadSavedMap() { - try { - const savedMap = await getMapsSavedObjectLoader().get(this.props.savedMapId); - if (this._isMounted) { - getCoreChrome().docTitle.change(savedMap.title); - if (this.props.savedMapId) { - getCoreChrome().recentlyAccessed.add(savedMap.getFullPath(), savedMap.title, savedMap.id); - } - this.setState({ savedMap }); - } - } catch (err) { - if (this._isMounted) { - this.setState({ failedToLoad: true }); - getToasts().addWarning({ - title: i18n.translate('xpack.maps.loadMap.errorAttemptingToLoadSavedMap', { - defaultMessage: `Unable to load map`, - }), - text: `${err.message}`, - }); - } - } - } - - render() { - const { savedMap, failedToLoad } = this.state; - - if (failedToLoad) { - return ; - } - - return savedMap ? ( - - ) : null; - } -}; diff --git a/x-pack/plugins/maps/public/routing/state_syncing/app_sync.ts b/x-pack/plugins/maps/public/routing/state_syncing/app_sync.ts index b346822913be..498442040681 100644 --- a/x-pack/plugins/maps/public/routing/state_syncing/app_sync.ts +++ b/x-pack/plugins/maps/public/routing/state_syncing/app_sync.ts @@ -8,7 +8,7 @@ import { map } from 'rxjs/operators'; import { connectToQueryState, esFilters } from '../../../../../../src/plugins/data/public'; import { syncState, BaseStateContainer } from '../../../../../../src/plugins/kibana_utils/public'; import { getData } from '../../kibana_services'; -import { kbnUrlStateStorage } from '../maps_router'; +import { kbnUrlStateStorage } from '../render_app'; import { AppStateManager } from './app_state_manager'; export function startAppStateSyncing(appStateManager: AppStateManager) { diff --git a/x-pack/plugins/maps/public/routing/state_syncing/global_sync.ts b/x-pack/plugins/maps/public/routing/state_syncing/global_sync.ts index 1e779831c5e0..3f370d9aa99b 100644 --- a/x-pack/plugins/maps/public/routing/state_syncing/global_sync.ts +++ b/x-pack/plugins/maps/public/routing/state_syncing/global_sync.ts @@ -6,7 +6,7 @@ import { TimeRange, RefreshInterval, Filter } from 'src/plugins/data/public'; import { syncQueryStateWithUrl } from '../../../../../../src/plugins/data/public'; import { getData } from '../../kibana_services'; -import { kbnUrlStateStorage } from '../maps_router'; +import { kbnUrlStateStorage } from '../render_app'; export interface MapsGlobalState { time?: TimeRange; diff --git a/x-pack/plugins/ml/server/routes/data_frame_analytics.ts b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts index e0f1b01dafa1..48aed19ea905 100644 --- a/x-pack/plugins/ml/server/routes/data_frame_analytics.ts +++ b/x-pack/plugins/ml/server/routes/data_frame_analytics.ts @@ -456,16 +456,10 @@ export function dataFrameAnalyticsRoutes({ router, mlLicense }: RouteInitializat }, mlLicense.fullLicenseAPIGuard(async ({ client, request, response }) => { try { - const options: { id: string; force?: boolean | undefined } = { + const { body } = await client.asInternalUser.ml.stopDataFrameAnalytics({ id: request.params.analyticsId, - }; - // @ts-expect-error TODO: update types - if (request.url?.query?.force !== undefined) { - // @ts-expect-error TODO: update types - options.force = request.url.query.force; - } - - const { body } = await client.asInternalUser.ml.stopDataFrameAnalytics(options); + force: request.query.force, + }); return response.ok({ body, }); diff --git a/x-pack/plugins/observability/public/components/app/section/ux/mock_data/ux.mock.ts b/x-pack/plugins/observability/public/components/app/section/ux/mock_data/ux.mock.ts index e61564f9df75..017f385d3673 100644 --- a/x-pack/plugins/observability/public/components/app/section/ux/mock_data/ux.mock.ts +++ b/x-pack/plugins/observability/public/components/app/section/ux/mock_data/ux.mock.ts @@ -14,6 +14,7 @@ export const response: UxFetchDataResponse = { lcp: 1942.6666666666667, tbt: 281.55833333333334, fcp: 1487, + coreVitalPages: 100, lcpRanks: [65, 19, 16], fidRanks: [73, 11, 16], clsRanks: [86, 8, 6], diff --git a/x-pack/plugins/observability/public/components/shared/core_web_vitals/core_vital_item.tsx b/x-pack/plugins/observability/public/components/shared/core_web_vitals/core_vital_item.tsx index 0d0a388855ff..18831565b878 100644 --- a/x-pack/plugins/observability/public/components/shared/core_web_vitals/core_vital_item.tsx +++ b/x-pack/plugins/observability/public/components/shared/core_web_vitals/core_vital_item.tsx @@ -34,7 +34,7 @@ export interface Thresholds { interface Props { title: string; - value?: string; + value?: string | null; ranks?: number[]; loading: boolean; thresholds: Thresholds; @@ -88,14 +88,14 @@ export function CoreVitalItem({ const biggestValIndex = ranks.indexOf(Math.max(...ranks)); - if (value === undefined && ranks[0] === 100 && !loading) { + if ((value === null || value !== undefined) && ranks[0] === 100 && !loading) { return ; } return ( <> {title} diff --git a/x-pack/plugins/observability/public/components/shared/core_web_vitals/index.tsx b/x-pack/plugins/observability/public/components/shared/core_web_vitals/index.tsx index 6a507176e55f..f5683310c3b7 100644 --- a/x-pack/plugins/observability/public/components/shared/core_web_vitals/index.tsx +++ b/x-pack/plugins/observability/public/components/shared/core_web_vitals/index.tsx @@ -18,11 +18,12 @@ import { WebCoreVitalsTitle } from './web_core_vitals_title'; import { ServiceName } from './service_name'; export interface UXMetrics { - cls: string; - fid: number; - lcp: number; + cls: string | null; + fid?: number | null; + lcp?: number | null; tbt: number; - fcp: number; + fcp?: number | null; + coreVitalPages: number; lcpRanks: number[]; fidRanks: number[]; clsRanks: number[]; @@ -48,21 +49,35 @@ interface Props { data?: UXMetrics | null; displayServiceName?: boolean; serviceName?: string; + totalPageViews?: number; + displayTrafficMetric?: boolean; } -function formatValue(value?: number) { - if (typeof value === 'undefined') { - return undefined; +function formatValue(value?: number | null) { + if (typeof value === 'undefined' || value === null) { + return null; } return formatToSec(value, 'ms'); } -export function CoreVitals({ data, loading, displayServiceName, serviceName }: Props) { - const { lcp, lcpRanks, fid, fidRanks, cls, clsRanks } = data || {}; +export function CoreVitals({ + data, + loading, + displayServiceName, + serviceName, + totalPageViews, + displayTrafficMetric = false, +}: Props) { + const { lcp, lcpRanks, fid, fidRanks, cls, clsRanks, coreVitalPages } = data || {}; return ( <> - + {displayServiceName && } @@ -90,7 +105,7 @@ export function CoreVitals({ data, loading, displayServiceName, serviceName }: P setIsPopoverOpen(false); + const closeBrowserPopover = () => setIsBrowserPopoverOpen(false); return ( - -

    - {CORE_WEB_VITALS} - setIsPopoverOpen(true)} - color={'text'} - iconType={'questionInCircle'} - /> - } - closePopover={closePopover} - > -
    - + + + +

    + {CORE_WEB_VITALS} + setIsPopoverOpen(true)} + color={'text'} + iconType={'questionInCircle'} + /> + } + closePopover={closePopover} + > +
    + + {' '} + + {CORE_WEB_VITALS} + + +
    +
    +

    +
    +
    + {displayTrafficMetric && totalPageViews > 0 && ( + + {loading ? ( + + ) : ( + {(((coreVitalPages || 0) / totalPageViews) * 100).toFixed(0)}% + ), + }} /> - - {' '} - {CORE_WEB_VITALS} - + + setIsBrowserPopoverOpen(true)} + color={'text'} + iconType={'questionInCircle'} + /> + } + closePopover={closeBrowserPopover} + > +
    + + {' '} + + {BROWSER_CORE_WEB_VITALS} + + +
    +
    -
    -
    -

    -
    + )} +
    + )} + ); } diff --git a/x-pack/plugins/observability/public/data_handler.test.ts b/x-pack/plugins/observability/public/data_handler.test.ts index dae2f62777d3..8fdfc2bc622c 100644 --- a/x-pack/plugins/observability/public/data_handler.test.ts +++ b/x-pack/plugins/observability/public/data_handler.test.ts @@ -287,6 +287,7 @@ describe('registerDataHandler', () => { lcp: 1464.3333333333333, tbt: 232.92166666666665, fcp: 1154.8, + coreVitalPages: 100, lcpRanks: [73, 16, 11], fidRanks: [85, 4, 11], clsRanks: [88, 7, 5], @@ -314,6 +315,7 @@ describe('registerDataHandler', () => { lcp: 1464.3333333333333, tbt: 232.92166666666665, fcp: 1154.8, + coreVitalPages: 100, lcpRanks: [73, 16, 11], fidRanks: [85, 4, 11], clsRanks: [88, 7, 5], diff --git a/x-pack/plugins/reporting/server/core.ts b/x-pack/plugins/reporting/server/core.ts index abd86d51fb6b..d62adc62bc9a 100644 --- a/x-pack/plugins/reporting/server/core.ts +++ b/x-pack/plugins/reporting/server/core.ts @@ -210,11 +210,18 @@ export class ReportingCore { } public getFakeRequest(baseRequest: object, spaceId: string | undefined, logger = this.logger) { + // @ts-expect-error _core isn't supposed to be accessed - remove once we upgrade to hapi v18 const fakeRequest = KibanaRequest.from({ path: '/', route: { settings: {} }, url: { href: '/' }, raw: { req: { url: '/' } }, + // TODO: Remove once we upgrade to hapi v18 + _core: { + info: { + uri: 'http://localhost', + }, + }, ...baseRequest, } as Hapi.Request); diff --git a/x-pack/plugins/reporting/server/routes/lib/authorized_user_pre_routing.test.ts b/x-pack/plugins/reporting/server/routes/lib/authorized_user_pre_routing.test.ts index cee8a88000e2..cce002a0e693 100644 --- a/x-pack/plugins/reporting/server/routes/lib/authorized_user_pre_routing.test.ts +++ b/x-pack/plugins/reporting/server/routes/lib/authorized_user_pre_routing.test.ts @@ -27,7 +27,7 @@ const getMockContext = () => const getMockRequest = () => ({ - url: { port: '5601', query: '', path: '/foo' }, + url: { port: '5601', search: '', pathname: '/foo' }, route: { path: '/foo', options: {} }, } as KibanaRequest); diff --git a/x-pack/plugins/security/public/account_management/account_management_page.tsx b/x-pack/plugins/security/public/account_management/account_management_page.tsx index 6615e8fee941..2c870bf788ce 100644 --- a/x-pack/plugins/security/public/account_management/account_management_page.tsx +++ b/x-pack/plugins/security/public/account_management/account_management_page.tsx @@ -6,6 +6,7 @@ import React, { useEffect, useState } from 'react'; import ReactDOM from 'react-dom'; import { EuiPage, EuiPageBody, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { CoreStart, NotificationsStart } from 'src/core/public'; import { getUserDisplayName, AuthenticatedUser } from '../../common/model'; import { AuthenticationServiceSetup } from '../authentication'; diff --git a/x-pack/plugins/security/public/account_management/change_password/change_password.tsx b/x-pack/plugins/security/public/account_management/change_password/change_password.tsx index 5b27df24f975..031a70c49746 100644 --- a/x-pack/plugins/security/public/account_management/change_password/change_password.tsx +++ b/x-pack/plugins/security/public/account_management/change_password/change_password.tsx @@ -6,6 +6,7 @@ import React, { Component } from 'react'; import { EuiDescribedFormGroup } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotificationsSetup } from 'src/core/public'; import { AuthenticatedUser, canUserChangePassword } from '../../../common/model'; import { UserAPIClient } from '../../management/users'; diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx index 94f9de010cc2..192d554bdc87 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.test.tsx @@ -8,6 +8,7 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; import { ReactWrapper } from 'enzyme'; import { EuiCallOut } from '@elastic/eui'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotEnabled } from './not_enabled'; import { PermissionDenied } from './permission_denied'; diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx index 8621b01299e4..b4ea91ea024f 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx @@ -26,6 +26,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import moment from 'moment-timezone'; import { ApplicationStart, NotificationsStart } from 'src/core/public'; import { SectionLoading } from '../../../../../../../src/plugins/es_ui_shared/public'; diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/invalidate_provider/invalidate_provider.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/invalidate_provider/invalidate_provider.tsx index 1f47a426e6ae..3c1e608f9772 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/invalidate_provider/invalidate_provider.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/invalidate_provider/invalidate_provider.tsx @@ -6,6 +6,7 @@ import React, { Fragment, useRef, useState } from 'react'; import { EuiConfirmModal, EuiOverlayMask } from '@elastic/eui'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { i18n } from '@kbn/i18n'; import { NotificationsStart } from 'src/core/public'; import { ApiKeyToInvalidate } from '../../../../../common/model'; diff --git a/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.tsx b/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.tsx index 7abf34700ad7..49dd83ac1bd2 100644 --- a/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/components/delete_provider/delete_provider.tsx @@ -7,6 +7,7 @@ import React, { Fragment, useRef, useState, ReactElement } from 'react'; import { EuiConfirmModal, EuiOverlayMask } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotificationsStart } from 'src/core/public'; import { RoleMapping } from '../../../../../common/model'; import { RoleMappingsAPIClient } from '../../role_mappings_api_client'; diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx index 04dc9c6dfa95..aff8ed12bceb 100644 --- a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx @@ -5,6 +5,7 @@ */ import React from 'react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; import { findTestSubject } from 'test_utils/find_test_subject'; diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx index b4e3627039ec..30584348960a 100644 --- a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx @@ -19,6 +19,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotificationsStart, ScopedHistory } from 'src/core/public'; import { RoleMapping } from '../../../../common/model'; import { RuleEditorPanel } from './rule_editor_panel'; diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.test.tsx index 9b62ca27ca56..aaf223f5a8dc 100644 --- a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.test.tsx @@ -5,6 +5,7 @@ */ import React from 'react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { findTestSubject } from 'test_utils/find_test_subject'; import { Role, RoleMapping } from '../../../../../common/model'; diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.tsx index 3df9987141fb..faf0278e5d8f 100644 --- a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/mapping_info_panel/mapping_info_panel.tsx @@ -19,6 +19,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RoleMapping } from '../../../../../common/model'; import { RolesAPIClient } from '../../../roles'; import { diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.test.tsx index 62f53acb0546..29c5acdb1dda 100644 --- a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; import { findTestSubject } from 'test_utils/find_test_subject'; import { EuiComboBox } from '@elastic/eui'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RoleSelector } from './role_selector'; import { Role, RoleMapping } from '../../../../../common/model'; import { RoleTemplateEditor } from './role_template_editor'; diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.tsx index b0f558ee71be..163637abae1a 100644 --- a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/role_selector/role_selector.tsx @@ -8,6 +8,7 @@ import React, { Fragment } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFormRow, EuiHorizontalRule } from '@elastic/eui'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RoleMapping, Role, isRoleDeprecated } from '../../../../../common/model'; import { RolesAPIClient } from '../../../roles'; import { AddRoleTemplateButton } from './add_role_template_button'; diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx index cf0cb21598c6..98e59eb95f0d 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx @@ -24,6 +24,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotificationsStart, ApplicationStart, ScopedHistory } from 'src/core/public'; import { RoleMapping, Role } from '../../../../common/model'; import { EmptyPrompt } from './empty_prompt'; 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 650d7c9c86c2..d24191c54bd9 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 @@ -30,6 +30,7 @@ import React, { useRef, useState, } from 'react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Capabilities, FatalErrorsSetup, diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/elasticsearch_privileges.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/elasticsearch_privileges.tsx index 46e0183b2f38..8fc09ce16740 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/elasticsearch_privileges.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/elasticsearch_privileges.tsx @@ -17,6 +17,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import React, { Component, Fragment } from 'react'; import { Role, BuiltinESPrivileges } from '../../../../../../common/model'; import { SecurityLicense } from '../../../../../../common/licensing'; diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privileges.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privileges.tsx index e4a2bbd260de..5bc957993dd4 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privileges.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/es/index_privileges.tsx @@ -5,6 +5,7 @@ */ import _ from 'lodash'; import React, { Component, Fragment } from 'react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Role, RoleIndexPrivilege, diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx index d1b266d2a68f..a6429a87101b 100644 --- a/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_grid/confirm_delete/confirm_delete.tsx @@ -18,6 +18,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotificationsStart } from 'src/core/public'; import { RolesAPIClient } from '../../roles_api_client'; diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx index eb6d25c9ef5a..1ee621f9ba12 100644 --- a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx @@ -5,6 +5,7 @@ */ import { EuiIcon, EuiBasicTable } from '@elastic/eui'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ReactWrapper } from 'enzyme'; import React from 'react'; import { mountWithIntl } from 'test_utils/enzyme_helpers'; diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx index 1e733dfa0767..be23aace106d 100644 --- a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx @@ -25,6 +25,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotificationsStart } from 'src/core/public'; import { ScopedHistory } from 'kibana/public'; import { diff --git a/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx index 5d889abdf46c..c7ecdd1bc556 100644 --- a/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx +++ b/x-pack/plugins/security/public/management/users/components/change_password_form/change_password_form.tsx @@ -15,6 +15,7 @@ import { import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import React, { ChangeEvent, Component } from 'react'; import { NotificationsStart } from 'src/core/public'; import { User } from '../../../../../common/model'; diff --git a/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.tsx b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.tsx index a6fbc6be945c..5d3e6d40f2c2 100644 --- a/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.tsx +++ b/x-pack/plugins/security/public/management/users/components/confirm_delete_users/confirm_delete_users.tsx @@ -8,6 +8,7 @@ import React, { Component, Fragment } from 'react'; import { EuiOverlayMask, EuiConfirmModal } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotificationsStart } from 'src/core/public'; import { UserAPIClient } from '../..'; diff --git a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx index 9a62187cffd3..dc0c3336cb85 100644 --- a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx @@ -30,6 +30,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotificationsStart, ScopedHistory } from 'src/core/public'; import { User, EditUser, Role, isRoleDeprecated } from '../../../../common/model'; import { AuthenticationServiceSetup } from '../../../authentication'; diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx index debe1c5e82d3..2b7ed0079f29 100644 --- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx @@ -23,6 +23,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { NotificationsStart, ApplicationStart, ScopedHistory } from 'src/core/public'; import { User, Role } from '../../../../common/model'; import { ConfirmDeleteUsers } from '../components'; diff --git a/x-pack/plugins/security/server/audit/audit_events.test.ts b/x-pack/plugins/security/server/audit/audit_events.test.ts index ae40429eea1b..f153b9efb9d4 100644 --- a/x-pack/plugins/security/server/audit/audit_events.test.ts +++ b/x-pack/plugins/security/server/audit/audit_events.test.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { URL } from 'url'; import { EventOutcome, SavedObjectAction, @@ -192,11 +193,48 @@ describe('#httpRequestEvent', () => { }, "message": "User is requesting [/path] endpoint", "url": Object { - "domain": undefined, + "domain": "localhost", "path": "/path", "port": undefined, "query": undefined, - "scheme": undefined, + "scheme": "http:", + }, + } + `); + }); + + test('uses original URL if rewritten', () => { + expect( + httpRequestEvent({ + request: httpServerMock.createKibanaRequest({ + path: '/path', + query: { query: 'param' }, + kibanaRequestState: { + requestId: '123', + requestUuid: '123e4567-e89b-12d3-a456-426614174000', + rewrittenUrl: new URL('http://localhost/original/path?query=param'), + }, + }), + }) + ).toMatchInlineSnapshot(` + Object { + "event": Object { + "action": "http_request", + "category": "web", + "outcome": "unknown", + }, + "http": Object { + "request": Object { + "method": "get", + }, + }, + "message": "User is requesting [/original/path] endpoint", + "url": Object { + "domain": "localhost", + "path": "/original/path", + "port": undefined, + "query": "query=param", + "scheme": "http:", }, } `); diff --git a/x-pack/plugins/security/server/audit/audit_events.ts b/x-pack/plugins/security/server/audit/audit_events.ts index 48a3b1e7e85b..d91c18bf82e0 100644 --- a/x-pack/plugins/security/server/audit/audit_events.ts +++ b/x-pack/plugins/security/server/audit/audit_events.ts @@ -105,10 +105,10 @@ export interface HttpRequestParams { } export function httpRequestEvent({ request }: HttpRequestParams): AuditEvent { - const { pathname, search } = request.url; + const url = request.rewrittenUrl ?? request.url; return { - message: `User is requesting [${pathname}] endpoint`, + message: `User is requesting [${url.pathname}] endpoint`, event: { action: 'http_request', category: EventCategory.WEB, @@ -120,11 +120,11 @@ export function httpRequestEvent({ request }: HttpRequestParams): AuditEvent { }, }, url: { - domain: request.url.hostname, - path: pathname, - port: request.url.port ? parseInt(request.url.port, 10) : undefined, - query: search?.slice(1) || undefined, - scheme: request.url.protocol, + domain: url.hostname, + path: url.pathname, + port: url.port ? parseInt(url.port, 10) : undefined, + query: url.search ? url.search.slice(1) : undefined, + scheme: url.protocol, }, }; } diff --git a/x-pack/plugins/security/server/authentication/authenticator.test.ts b/x-pack/plugins/security/server/authentication/authenticator.test.ts index e5bb00cdc056..51c937f1edcb 100644 --- a/x-pack/plugins/security/server/authentication/authenticator.test.ts +++ b/x-pack/plugins/security/server/authentication/authenticator.test.ts @@ -10,7 +10,7 @@ jest.mock('./providers/saml'); jest.mock('./providers/http'); import Boom from 'boom'; - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { loggingSystemMock, httpServiceMock, diff --git a/x-pack/plugins/security/server/authentication/authenticator.ts b/x-pack/plugins/security/server/authentication/authenticator.ts index 0523ebaffb9d..80aeb4f8b295 100644 --- a/x-pack/plugins/security/server/authentication/authenticator.ts +++ b/x-pack/plugins/security/server/authentication/authenticator.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { KibanaRequest, LoggerFactory, @@ -333,7 +333,7 @@ export class Authenticator { this.logger.debug('Redirecting request to Login Selector.'); return AuthenticationResult.redirectTo( `${this.options.basePath.serverBasePath}/login?next=${encodeURIComponent( - `${this.options.basePath.get(request)}${request.url.path}` + `${this.options.basePath.get(request)}${request.url.pathname}${request.url.search}` )}` ); } @@ -728,7 +728,7 @@ export class Authenticator { preAccessRedirectURL = `${preAccessRedirectURL}?next=${encodeURIComponent( authenticationResult.redirectURL || redirectURL || - `${this.options.basePath.get(request)}${request.url.path}` + `${this.options.basePath.get(request)}${request.url.pathname}${request.url.search}` )}`; } else if (redirectURL && !authenticationResult.redirectURL) { preAccessRedirectURL = redirectURL; diff --git a/x-pack/plugins/security/server/authentication/index.test.ts b/x-pack/plugins/security/server/authentication/index.test.ts index 6f8f17a0a3c7..b5ce5283df8c 100644 --- a/x-pack/plugins/security/server/authentication/index.test.ts +++ b/x-pack/plugins/security/server/authentication/index.test.ts @@ -8,6 +8,7 @@ jest.mock('./api_keys'); jest.mock('./authenticator'); import Boom from 'boom'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { loggingSystemMock, diff --git a/x-pack/plugins/security/server/authentication/index.ts b/x-pack/plugins/security/server/authentication/index.ts index ab8e42a6a72d..68d3e622a657 100644 --- a/x-pack/plugins/security/server/authentication/index.ts +++ b/x-pack/plugins/security/server/authentication/index.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { UnwrapPromise } from '@kbn/utility-types'; +import type { PublicMethodsOf, UnwrapPromise } from '@kbn/utility-types'; import { ILegacyClusterClient, KibanaRequest, diff --git a/x-pack/plugins/security/server/authentication/providers/base.ts b/x-pack/plugins/security/server/authentication/providers/base.ts index 7b2ad510db96..6b13c32a2f1e 100644 --- a/x-pack/plugins/security/server/authentication/providers/base.ts +++ b/x-pack/plugins/security/server/authentication/providers/base.ts @@ -5,6 +5,7 @@ */ import { deepFreeze } from '@kbn/std'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { KibanaRequest, Logger, diff --git a/x-pack/plugins/security/server/authentication/providers/basic.test.ts b/x-pack/plugins/security/server/authentication/providers/basic.test.ts index 2481844abb38..87002ebed567 100644 --- a/x-pack/plugins/security/server/authentication/providers/basic.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/basic.test.ts @@ -101,13 +101,13 @@ describe('BasicAuthenticationProvider', () => { await expect( provider.authenticate( httpServerMock.createKibanaRequest({ - path: '/s/foo/some-path # that needs to be encoded', + path: '/s/foo/some path that needs to be encoded', }), null ) ).resolves.toEqual( AuthenticationResult.redirectTo( - '/mock-server-basepath/login?next=%2Fmock-server-basepath%2Fs%2Ffoo%2Fsome-path%20%23%20that%20needs%20to%20be%20encoded' + '/mock-server-basepath/login?next=%2Fmock-server-basepath%2Fs%2Ffoo%2Fsome%2520path%2520that%2520needs%2520to%2520be%2520encoded' ) ); }); diff --git a/x-pack/plugins/security/server/authentication/providers/basic.ts b/x-pack/plugins/security/server/authentication/providers/basic.ts index 35ab2d242659..28b671346ee7 100644 --- a/x-pack/plugins/security/server/authentication/providers/basic.ts +++ b/x-pack/plugins/security/server/authentication/providers/basic.ts @@ -90,7 +90,9 @@ export class BasicAuthenticationProvider extends BaseAuthenticationProvider { * @param [state] Optional state object associated with the provider. */ public async authenticate(request: KibanaRequest, state?: ProviderState | null) { - this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); + this.logger.debug( + `Trying to authenticate user request to ${request.url.pathname}${request.url.search}.` + ); if (HTTPAuthorizationHeader.parseFromRequest(request) != null) { this.logger.debug('Cannot authenticate requests with `Authorization` header.'); @@ -106,7 +108,9 @@ export class BasicAuthenticationProvider extends BaseAuthenticationProvider { this.logger.debug('Redirecting request to Login page.'); const basePath = this.options.basePath.get(request); return AuthenticationResult.redirectTo( - `${basePath}/login?next=${encodeURIComponent(`${basePath}${request.url.path}`)}` + `${basePath}/login?next=${encodeURIComponent( + `${basePath}${request.url.pathname}${request.url.search}` + )}` ); } @@ -119,7 +123,7 @@ export class BasicAuthenticationProvider extends BaseAuthenticationProvider { * @param [state] Optional state object associated with the provider. */ public async logout(request: KibanaRequest, state?: ProviderState | null) { - this.logger.debug(`Trying to log user out via ${request.url.path}.`); + this.logger.debug(`Trying to log user out via ${request.url.pathname}${request.url.search}.`); // Having a `null` state means that provider was specifically called to do a logout, but when // session isn't defined then provider is just being probed whether or not it can perform logout. diff --git a/x-pack/plugins/security/server/authentication/providers/http.ts b/x-pack/plugins/security/server/authentication/providers/http.ts index 3e33a52cbbc6..933685d68978 100644 --- a/x-pack/plugins/security/server/authentication/providers/http.ts +++ b/x-pack/plugins/security/server/authentication/providers/http.ts @@ -56,7 +56,9 @@ export class HTTPAuthenticationProvider extends BaseAuthenticationProvider { * @param request Request instance. */ public async authenticate(request: KibanaRequest) { - this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); + this.logger.debug( + `Trying to authenticate user request to ${request.url.pathname}${request.url.search}.` + ); const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request); if (authorizationHeader == null) { @@ -72,12 +74,12 @@ export class HTTPAuthenticationProvider extends BaseAuthenticationProvider { try { const user = await this.getUser(request); this.logger.debug( - `Request to ${request.url.path} has been authenticated via authorization header with "${authorizationHeader.scheme}" scheme.` + `Request to ${request.url.pathname}${request.url.search} has been authenticated via authorization header with "${authorizationHeader.scheme}" scheme.` ); return AuthenticationResult.succeeded(user); } catch (err) { this.logger.debug( - `Failed to authenticate request to ${request.url.path} via authorization header with "${authorizationHeader.scheme}" scheme: ${err.message}` + `Failed to authenticate request to ${request.url.pathname}${request.url.search} via authorization header with "${authorizationHeader.scheme}" scheme: ${err.message}` ); return AuthenticationResult.failed(err); } diff --git a/x-pack/plugins/security/server/authentication/providers/kerberos.ts b/x-pack/plugins/security/server/authentication/providers/kerberos.ts index 5b593851cc2f..d7de71f4da9e 100644 --- a/x-pack/plugins/security/server/authentication/providers/kerberos.ts +++ b/x-pack/plugins/security/server/authentication/providers/kerberos.ts @@ -65,7 +65,9 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { * @param [state] Optional state object associated with the provider. */ public async authenticate(request: KibanaRequest, state?: ProviderState | null) { - this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); + this.logger.debug( + `Trying to authenticate user request to ${request.url.pathname}${request.url.search}.` + ); const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request); if (authorizationHeader && authorizationHeader.scheme.toLowerCase() !== 'negotiate') { @@ -100,7 +102,7 @@ export class KerberosAuthenticationProvider extends BaseAuthenticationProvider { * @param state State value previously stored by the provider. */ public async logout(request: KibanaRequest, state?: ProviderState | null) { - this.logger.debug(`Trying to log user out via ${request.url.path}.`); + this.logger.debug(`Trying to log user out via ${request.url.pathname}${request.url.search}.`); // Having a `null` state means that provider was specifically called to do a logout, but when // session isn't defined then provider is just being probed whether or not it can perform logout. diff --git a/x-pack/plugins/security/server/authentication/providers/oidc.ts b/x-pack/plugins/security/server/authentication/providers/oidc.ts index 75c909cdcd94..9570c59f8ea1 100644 --- a/x-pack/plugins/security/server/authentication/providers/oidc.ts +++ b/x-pack/plugins/security/server/authentication/providers/oidc.ts @@ -166,7 +166,9 @@ export class OIDCAuthenticationProvider extends BaseAuthenticationProvider { * @param [state] Optional state object associated with the provider. */ public async authenticate(request: KibanaRequest, state?: ProviderState | null) { - this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); + this.logger.debug( + `Trying to authenticate user request to ${request.url.pathname}${request.url.search}.` + ); if (HTTPAuthorizationHeader.parseFromRequest(request) != null) { this.logger.debug('Cannot authenticate requests with `Authorization` header.'); @@ -418,7 +420,7 @@ export class OIDCAuthenticationProvider extends BaseAuthenticationProvider { * @param state State value previously stored by the provider. */ public async logout(request: KibanaRequest, state?: ProviderState | null) { - this.logger.debug(`Trying to log user out via ${request.url.path}.`); + this.logger.debug(`Trying to log user out via ${request.url.pathname}${request.url.search}.`); // Having a `null` state means that provider was specifically called to do a logout, but when // session isn't defined then provider is just being probed whether or not it can perform logout. @@ -477,7 +479,7 @@ export class OIDCAuthenticationProvider extends BaseAuthenticationProvider { `${ this.options.basePath.serverBasePath }/internal/security/capture-url?next=${encodeURIComponent( - `${this.options.basePath.get(request)}${request.url.path}` + `${this.options.basePath.get(request)}${request.url.pathname}${request.url.search}` )}&providerType=${encodeURIComponent(this.type)}&providerName=${encodeURIComponent( this.options.name )}`, diff --git a/x-pack/plugins/security/server/authentication/providers/pki.ts b/x-pack/plugins/security/server/authentication/providers/pki.ts index f3cc21500df2..6dcb448e0815 100644 --- a/x-pack/plugins/security/server/authentication/providers/pki.ts +++ b/x-pack/plugins/security/server/authentication/providers/pki.ts @@ -61,7 +61,9 @@ export class PKIAuthenticationProvider extends BaseAuthenticationProvider { * @param [state] Optional state object associated with the provider. */ public async authenticate(request: KibanaRequest, state?: ProviderState | null) { - this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); + this.logger.debug( + `Trying to authenticate user request to ${request.url.pathname}${request.url.search}.` + ); if (HTTPAuthorizationHeader.parseFromRequest(request) != null) { this.logger.debug('Cannot authenticate requests with `Authorization` header.'); @@ -105,7 +107,7 @@ export class PKIAuthenticationProvider extends BaseAuthenticationProvider { * @param state State value previously stored by the provider. */ public async logout(request: KibanaRequest, state?: ProviderState | null) { - this.logger.debug(`Trying to log user out via ${request.url.path}.`); + this.logger.debug(`Trying to log user out via ${request.url.pathname}${request.url.search}.`); // Having a `null` state means that provider was specifically called to do a logout, but when // session isn't defined then provider is just being probed whether or not it can perform logout. diff --git a/x-pack/plugins/security/server/authentication/providers/saml.ts b/x-pack/plugins/security/server/authentication/providers/saml.ts index cf6772332b8b..59a1782c1f1f 100644 --- a/x-pack/plugins/security/server/authentication/providers/saml.ts +++ b/x-pack/plugins/security/server/authentication/providers/saml.ts @@ -193,7 +193,9 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider { * @param [state] Optional state object associated with the provider. */ public async authenticate(request: KibanaRequest, state?: ProviderState | null) { - this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); + this.logger.debug( + `Trying to authenticate user request to ${request.url.pathname}${request.url.search}` + ); if (HTTPAuthorizationHeader.parseFromRequest(request) != null) { this.logger.debug('Cannot authenticate requests with `Authorization` header.'); @@ -232,7 +234,7 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider { * @param state State value previously stored by the provider. */ public async logout(request: KibanaRequest, state?: ProviderState | null) { - this.logger.debug(`Trying to log user out via ${request.url.path}.`); + this.logger.debug(`Trying to log user out via ${request.url.pathname}${request.url.search}.`); // Normally when there is no active session in Kibana, `logout` method shouldn't do anything // and user will eventually be redirected to the home page to log in. But when SAML SLO is @@ -631,7 +633,7 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider { `${ this.options.basePath.serverBasePath }/internal/security/capture-url?next=${encodeURIComponent( - `${this.options.basePath.get(request)}${request.url.path}` + `${this.options.basePath.get(request)}${request.url.pathname}${request.url.search}` )}&providerType=${encodeURIComponent(this.type)}&providerName=${encodeURIComponent( this.options.name )}`, diff --git a/x-pack/plugins/security/server/authentication/providers/token.test.ts b/x-pack/plugins/security/server/authentication/providers/token.test.ts index 0264edf4fc08..ffb1c89b24e4 100644 --- a/x-pack/plugins/security/server/authentication/providers/token.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/token.test.ts @@ -173,13 +173,13 @@ describe('TokenAuthenticationProvider', () => { await expect( provider.authenticate( httpServerMock.createKibanaRequest({ - path: '/s/foo/some-path # that needs to be encoded', + path: '/s/foo/some path that needs to be encoded', }), null ) ).resolves.toEqual( AuthenticationResult.redirectTo( - '/mock-server-basepath/login?next=%2Fmock-server-basepath%2Fs%2Ffoo%2Fsome-path%20%23%20that%20needs%20to%20be%20encoded' + '/mock-server-basepath/login?next=%2Fmock-server-basepath%2Fs%2Ffoo%2Fsome%2520path%2520that%2520needs%2520to%2520be%2520encoded' ) ); }); diff --git a/x-pack/plugins/security/server/authentication/providers/token.ts b/x-pack/plugins/security/server/authentication/providers/token.ts index 869fd69173e2..7dace488bc95 100644 --- a/x-pack/plugins/security/server/authentication/providers/token.ts +++ b/x-pack/plugins/security/server/authentication/providers/token.ts @@ -92,7 +92,9 @@ export class TokenAuthenticationProvider extends BaseAuthenticationProvider { * @param [state] Optional state object associated with the provider. */ public async authenticate(request: KibanaRequest, state?: ProviderState | null) { - this.logger.debug(`Trying to authenticate user request to ${request.url.path}.`); + this.logger.debug( + `Trying to authenticate user request to ${request.url.pathname}${request.url.search}.` + ); if (HTTPAuthorizationHeader.parseFromRequest(request) != null) { this.logger.debug('Cannot authenticate requests with `Authorization` header.'); @@ -126,7 +128,7 @@ export class TokenAuthenticationProvider extends BaseAuthenticationProvider { * @param state State value previously stored by the provider. */ public async logout(request: KibanaRequest, state?: ProviderState | null) { - this.logger.debug(`Trying to log user out via ${request.url.path}.`); + this.logger.debug(`Trying to log user out via ${request.url.pathname}${request.url.search}.`); // Having a `null` state means that provider was specifically called to do a logout, but when // session isn't defined then provider is just being probed whether or not it can perform logout. @@ -241,7 +243,9 @@ export class TokenAuthenticationProvider extends BaseAuthenticationProvider { * @param request Request instance. */ private getLoginPageURL(request: KibanaRequest) { - const nextURL = encodeURIComponent(`${this.options.basePath.get(request)}${request.url.path}`); + const nextURL = encodeURIComponent( + `${this.options.basePath.get(request)}${request.url.pathname}${request.url.search}` + ); return `${this.options.basePath.get(request)}/login?next=${nextURL}`; } } diff --git a/x-pack/plugins/security/server/authorization/api_authorization.ts b/x-pack/plugins/security/server/authorization/api_authorization.ts index 813ed8d064d9..9cf090ab271a 100644 --- a/x-pack/plugins/security/server/authorization/api_authorization.ts +++ b/x-pack/plugins/security/server/authorization/api_authorization.ts @@ -33,11 +33,13 @@ export function initAPIAuthorization( // we've actually authorized the request if (checkPrivilegesResponse.hasAllRequested) { - logger.debug(`User authorized for "${request.url.path}"`); + logger.debug(`User authorized for "${request.url.pathname}${request.url.search}"`); return toolkit.next(); } - logger.warn(`User not authorized for "${request.url.path}": responding with 403`); + logger.warn( + `User not authorized for "${request.url.pathname}${request.url.search}": responding with 403` + ); return response.forbidden(); }); } diff --git a/x-pack/plugins/security/server/authorization/authorization_service.tsx b/x-pack/plugins/security/server/authorization/authorization_service.tsx index 9547295af4df..a45bca90d8b5 100644 --- a/x-pack/plugins/security/server/authorization/authorization_service.tsx +++ b/x-pack/plugins/security/server/authorization/authorization_service.tsx @@ -168,7 +168,7 @@ export class AuthorizationService { http.registerOnPreResponse((request, preResponse, toolkit) => { if (preResponse.statusCode === 403 && canRedirectRequest(request)) { const basePath = http.basePath.get(request); - const next = `${basePath}${request.url.path}`; + const next = `${basePath}${request.url.pathname}${request.url.search}`; const regularBundlePath = `${basePath}/${buildNumber}/bundles`; const logoutUrl = http.basePath.prepend( diff --git a/x-pack/plugins/security/server/routes/authentication/oidc.ts b/x-pack/plugins/security/server/routes/authentication/oidc.ts index 5d8a7ae7bdfe..7eaa619b330e 100644 --- a/x-pack/plugins/security/server/routes/authentication/oidc.ts +++ b/x-pack/plugins/security/server/routes/authentication/oidc.ts @@ -135,7 +135,7 @@ export function defineOIDCRoutes({ loginAttempt = { type: OIDCLogin.LoginWithAuthorizationCodeFlow, // We pass the path only as we can't be sure of the full URL and Elasticsearch doesn't need it anyway. - authenticationResponseURI: request.url.path!, + authenticationResponseURI: request.url.pathname + request.url.search, }; } else if (request.query.iss) { logger.warn( diff --git a/x-pack/plugins/security/server/routes/index.ts b/x-pack/plugins/security/server/routes/index.ts index 7880e95240ff..079c9e8ab9ce 100644 --- a/x-pack/plugins/security/server/routes/index.ts +++ b/x-pack/plugins/security/server/routes/index.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { KibanaFeature } from '../../../features/server'; import { HttpResources, diff --git a/x-pack/plugins/security/server/routes/session_management/info.test.ts b/x-pack/plugins/security/server/routes/session_management/info.test.ts index fa9cba61df01..a104336f2e6b 100644 --- a/x-pack/plugins/security/server/routes/session_management/info.test.ts +++ b/x-pack/plugins/security/server/routes/session_management/info.test.ts @@ -11,6 +11,7 @@ import { RequestHandlerContext, RouteConfig, } from '../../../../../../src/core/server'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { Session } from '../../session_management'; import { defineSessionInfoRoutes } from './info'; diff --git a/x-pack/plugins/security/server/routes/users/change_password.test.ts b/x-pack/plugins/security/server/routes/users/change_password.test.ts index 51bee1c74afa..5e0f0a6005fb 100644 --- a/x-pack/plugins/security/server/routes/users/change_password.test.ts +++ b/x-pack/plugins/security/server/routes/users/change_password.test.ts @@ -6,6 +6,7 @@ import { errors } from 'elasticsearch'; import { ObjectType } from '@kbn/config-schema'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ILegacyClusterClient, IRouter, diff --git a/x-pack/plugins/security/server/routes/views/access_agreement.test.ts b/x-pack/plugins/security/server/routes/views/access_agreement.test.ts index 9b73358223b3..b513230b3ba6 100644 --- a/x-pack/plugins/security/server/routes/views/access_agreement.test.ts +++ b/x-pack/plugins/security/server/routes/views/access_agreement.test.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { RequestHandler, RouteConfig, diff --git a/x-pack/plugins/security/server/routes/views/logged_out.test.ts b/x-pack/plugins/security/server/routes/views/logged_out.test.ts index c160c4a26a18..31096bc33d68 100644 --- a/x-pack/plugins/security/server/routes/views/logged_out.test.ts +++ b/x-pack/plugins/security/server/routes/views/logged_out.test.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { HttpResourcesRequestHandler, RouteConfig } from '../../../../../../src/core/server'; import { Session } from '../../session_management'; import { defineLoggedOutRoutes } from './logged_out'; diff --git a/x-pack/plugins/security/server/routes/views/login.test.ts b/x-pack/plugins/security/server/routes/views/login.test.ts index fee3adbb19f9..b90a44be7aad 100644 --- a/x-pack/plugins/security/server/routes/views/login.test.ts +++ b/x-pack/plugins/security/server/routes/views/login.test.ts @@ -100,7 +100,7 @@ describe('Login view routes', () => { auth: { isAuthenticated: true }, }); (request as any).url = new URL( - `${request.url.path}${request.url.search}`, + `${request.url.pathname}${request.url.search}`, 'https://kibana.co' ); license.getFeatures.mockReturnValue({ showLogin: true } as any); @@ -114,7 +114,7 @@ describe('Login view routes', () => { // Redirect if `showLogin` is `false` even if user is not authenticated. request = httpServerMock.createKibanaRequest({ query, auth: { isAuthenticated: false } }); (request as any).url = new URL( - `${request.url.path}${request.url.search}`, + `${request.url.pathname}${request.url.search}`, 'https://kibana.co' ); license.getFeatures.mockReturnValue({ showLogin: false } as any); diff --git a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts index c7a3f31cc517..85e8e21da81b 100644 --- a/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts +++ b/x-pack/plugins/security/server/saved_objects/secure_saved_objects_client_wrapper.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SavedObjectsBaseOptions, SavedObjectsBulkCreateObject, diff --git a/x-pack/plugins/security/server/session_management/session.mock.ts b/x-pack/plugins/security/server/session_management/session.mock.ts index c09d24ba315c..973341acbfce 100644 --- a/x-pack/plugins/security/server/session_management/session.mock.ts +++ b/x-pack/plugins/security/server/session_management/session.mock.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { mockAuthenticatedUser } from '../../common/model/authenticated_user.mock'; import { Session, SessionValue } from './session'; import { sessionIndexMock } from './session_index.mock'; diff --git a/x-pack/plugins/security/server/session_management/session.test.ts b/x-pack/plugins/security/server/session_management/session.test.ts index c4d2342df36d..3010e70c3142 100644 --- a/x-pack/plugins/security/server/session_management/session.test.ts +++ b/x-pack/plugins/security/server/session_management/session.test.ts @@ -6,6 +6,7 @@ import crypto from 'crypto'; import nodeCrypto from '@elastic/node-crypto'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { ConfigSchema, createConfig } from '../config'; import { Session, SessionValueContentToEncrypt } from './session'; import { SessionIndex } from './session_index'; diff --git a/x-pack/plugins/security/server/session_management/session.ts b/x-pack/plugins/security/server/session_management/session.ts index 57c650914766..a85369a6f403 100644 --- a/x-pack/plugins/security/server/session_management/session.ts +++ b/x-pack/plugins/security/server/session_management/session.ts @@ -5,6 +5,7 @@ */ import nodeCrypto, { Crypto } from '@elastic/node-crypto'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { promisify } from 'util'; import { randomBytes, createHash } from 'crypto'; import { Duration } from 'moment'; diff --git a/x-pack/plugins/security/server/session_management/session_cookie.mock.ts b/x-pack/plugins/security/server/session_management/session_cookie.mock.ts index 026117f22756..998bc0ff01b2 100644 --- a/x-pack/plugins/security/server/session_management/session_cookie.mock.ts +++ b/x-pack/plugins/security/server/session_management/session_cookie.mock.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SessionCookie, SessionCookieValue } from './session_cookie'; export const sessionCookieMock = { diff --git a/x-pack/plugins/security/server/session_management/session_index.mock.ts b/x-pack/plugins/security/server/session_management/session_index.mock.ts index 81dbe4b7410b..ee8f5063655c 100644 --- a/x-pack/plugins/security/server/session_management/session_index.mock.ts +++ b/x-pack/plugins/security/server/session_management/session_index.mock.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { PublicMethodsOf } from '@kbn/utility-types'; import { SessionIndex, SessionIndexValue } from './session_index'; export const sessionIndexMock = { diff --git a/x-pack/plugins/security/server/session_management/session_index.test.ts b/x-pack/plugins/security/server/session_management/session_index.test.ts index f4ff5a8bddb7..cba63412bf50 100644 --- a/x-pack/plugins/security/server/session_management/session_index.test.ts +++ b/x-pack/plugins/security/server/session_management/session_index.test.ts @@ -155,6 +155,17 @@ describe('Session index', () => { await sessionIndex.initialize(); }); + + it('works properly after failure', async () => { + const unexpectedError = new Error('Uh! Oh!'); + mockClusterClient.callAsInternalUser.mockImplementationOnce(() => + Promise.reject(unexpectedError) + ); + mockClusterClient.callAsInternalUser.mockImplementationOnce(() => Promise.resolve(true)); + + await expect(sessionIndex.initialize()).rejects.toBe(unexpectedError); + await expect(sessionIndex.initialize()).resolves.toBe(undefined); + }); }); describe('cleanUp', () => { diff --git a/x-pack/plugins/security/server/session_management/session_index.ts b/x-pack/plugins/security/server/session_management/session_index.ts index 191e71f14d66..ee503acc0d3a 100644 --- a/x-pack/plugins/security/server/session_management/session_index.ts +++ b/x-pack/plugins/security/server/session_management/session_index.ts @@ -276,7 +276,7 @@ export class SessionIndex { } const sessionIndexTemplateName = `${this.options.kibanaIndexName}_security_session_index_template_${SESSION_INDEX_TEMPLATE_VERSION}`; - return (this.indexInitialization = new Promise(async (resolve) => { + return (this.indexInitialization = new Promise(async (resolve, reject) => { // Check if required index template exists. let indexTemplateExists = false; try { @@ -288,7 +288,7 @@ export class SessionIndex { this.options.logger.error( `Failed to check if session index template exists: ${err.message}` ); - throw err; + return reject(err); } // Create index template if it doesn't exist. @@ -303,7 +303,7 @@ export class SessionIndex { this.options.logger.debug('Successfully created session index template.'); } catch (err) { this.options.logger.error(`Failed to create session index template: ${err.message}`); - throw err; + return reject(err); } } @@ -316,7 +316,7 @@ export class SessionIndex { }); } catch (err) { this.options.logger.error(`Failed to check if session index exists: ${err.message}`); - throw err; + return reject(err); } // Create index if it doesn't exist. @@ -334,13 +334,14 @@ export class SessionIndex { this.options.logger.debug('Session index already exists.'); } else { this.options.logger.error(`Failed to create session index: ${err.message}`); - throw err; + return reject(err); } } } // Notify any consumers that are awaiting on this promise and immediately reset it. resolve(); + }).finally(() => { this.indexInitialization = undefined; })); } diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts index 07d0d63e5705..db841d2a732c 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts @@ -30,8 +30,7 @@ import { loginAndWaitForPage } from '../tasks/login'; import { DETECTIONS_URL } from '../urls/navigation'; -// FLAKY: https://github.com/elastic/kibana/issues/77957 -describe.skip('Alerts', () => { +describe('Alerts', () => { context('Closing alerts', () => { beforeEach(() => { esArchiverLoad('alerts'); diff --git a/x-pack/plugins/security_solution/cypress/integration/overview.spec.ts b/x-pack/plugins/security_solution/cypress/integration/overview.spec.ts index 7ccd588e16a8..542cf4ad8178 100644 --- a/x-pack/plugins/security_solution/cypress/integration/overview.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/overview.spec.ts @@ -12,7 +12,7 @@ import { loginAndWaitForPage } from '../tasks/login'; import { OVERVIEW_URL } from '../urls/navigation'; import { esArchiverUnload, esArchiverLoad } from '../tasks/es_archiver'; -describe('Overview Page', () => { +describe.skip('Overview Page', () => { before(() => { cy.stubSearchStrategyApi('overviewHostQuery', 'overview_search_strategy'); cy.stubSearchStrategyApi('overviewNetworkQuery', 'overview_search_strategy'); @@ -35,7 +35,7 @@ describe('Overview Page', () => { }); }); - describe('with no data', () => { + describe.skip('with no data', () => { before(() => { esArchiverUnload('auditbeat'); loginAndWaitForPage(OVERVIEW_URL); diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_local_storage.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timeline_local_storage.spec.ts index c2ff2c58687f..383ebe222058 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timeline_local_storage.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timeline_local_storage.spec.ts @@ -13,8 +13,7 @@ import { TABLE_COLUMN_EVENTS_MESSAGE } from '../screens/hosts/external_events'; import { waitsForEventsToBeLoaded, openEventsViewerFieldsBrowser } from '../tasks/hosts/events'; import { removeColumn, resetFields } from '../tasks/timeline'; -// FLAKY: https://github.com/elastic/kibana/issues/75794 -describe.skip('persistent timeline', () => { +describe('persistent timeline', () => { before(() => { loginAndWaitForPage(HOSTS_URL); openEvents(); diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts b/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts index f68ad88f578c..0d0ea8460edf 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts @@ -47,9 +47,9 @@ export const RULE_CHECKBOX = '.euiTableRow .euiCheckbox__input'; export const RULE_NAME = '[data-test-subj="ruleName"]'; -export const RULE_SWITCH = '[data-test-subj="rule-switch"]'; +export const RULE_SWITCH = '[data-test-subj="ruleSwitch"]'; -export const RULE_SWITCH_LOADER = '[data-test-subj="rule-switch-loader"]'; +export const RULE_SWITCH_LOADER = '[data-test-subj="ruleSwitchLoader"]'; export const RULES_TABLE = '[data-test-subj="rules-table"]'; diff --git a/x-pack/plugins/security_solution/public/cases/components/create/translations.ts b/x-pack/plugins/security_solution/public/cases/components/create/translations.ts index 222f8913b3fb..38916dbddc7d 100644 --- a/x-pack/plugins/security_solution/public/cases/components/create/translations.ts +++ b/x-pack/plugins/security_solution/public/cases/components/create/translations.ts @@ -18,6 +18,6 @@ export const STEP_ONE_TITLE = i18n.translate( export const STEP_TWO_TITLE = i18n.translate( 'xpack.securitySolution.components.create.stepTwoTitle', { - defaultMessage: 'External incident management system fields', + defaultMessage: 'External Connector Fields', } ); diff --git a/x-pack/plugins/security_solution/public/cases/pages/translations.ts b/x-pack/plugins/security_solution/public/cases/pages/translations.ts index 5b595c5892ef..8ba4c4faf187 100644 --- a/x-pack/plugins/security_solution/public/cases/pages/translations.ts +++ b/x-pack/plugins/security_solution/public/cases/pages/translations.ts @@ -224,7 +224,7 @@ export const GO_TO_DOCUMENTATION = i18n.translate( ); export const CONNECTORS = i18n.translate('xpack.securitySolution.case.caseView.connectors', { - defaultMessage: 'External incident management system', + defaultMessage: 'External Incident Management System', }); export const EDIT_CONNECTOR = i18n.translate('xpack.securitySolution.case.caseView.editConnector', { diff --git a/x-pack/plugins/security_solution/public/cases/translations.ts b/x-pack/plugins/security_solution/public/cases/translations.ts index 003439422442..a0b5f71db7df 100644 --- a/x-pack/plugins/security_solution/public/cases/translations.ts +++ b/x-pack/plugins/security_solution/public/cases/translations.ts @@ -224,7 +224,7 @@ export const GO_TO_DOCUMENTATION = i18n.translate( ); export const CONNECTORS = i18n.translate('xpack.securitySolution.case.caseView.connectors', { - defaultMessage: 'External incident management system', + defaultMessage: 'External Incident Management System', }); export const EDIT_CONNECTOR = i18n.translate('xpack.securitySolution.case.caseView.editConnector', { diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/__snapshots__/index.test.tsx.snap deleted file mode 100644 index 604f86866d56..000000000000 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/__snapshots__/index.test.tsx.snap +++ /dev/null @@ -1,20 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`RuleSwitch renders correctly against snapshot 1`] = ` - - - - - -`; diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/index.test.tsx index 104eff34c91b..910a28927fd9 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/index.test.tsx @@ -4,16 +4,173 @@ * you may not use this file except in compliance with the Elastic License. */ -import { shallow } from 'enzyme'; +import { mount } from 'enzyme'; import React from 'react'; +import { ThemeProvider } from 'styled-components'; +import euiLightVars from '@elastic/eui/dist/eui_theme_light.json'; +import { waitFor } from '@testing-library/react'; +import { enableRules } from '../../../containers/detection_engine/rules'; +import { enableRulesAction } from '../../../pages/detection_engine/rules/all/actions'; import { RuleSwitchComponent } from './index'; +import { getRulesSchemaMock } from '../../../../../common/detection_engine/schemas/response/rules_schema.mocks'; +import { RulesSchema } from '../../../../../common/detection_engine/schemas/response/rules_schema'; +import { useStateToaster, displayErrorToast } from '../../../../common/components/toasters'; + +jest.mock('../../../../common/components/toasters'); +jest.mock('../../../containers/detection_engine/rules'); +jest.mock('../../../pages/detection_engine/rules/all/actions'); describe('RuleSwitch', () => { - test('renders correctly against snapshot', () => { - const wrapper = shallow( - + beforeEach(() => { + (useStateToaster as jest.Mock).mockImplementation(() => [[], jest.fn()]); + (enableRules as jest.Mock).mockResolvedValue([getRulesSchemaMock()]); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('it renders loader if "isLoading" is true', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="ruleSwitchLoader"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="ruleSwitch"]').exists()).toBeFalsy(); + }); + + test('it renders switch disabled if "isDisabled" is true', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + + expect(wrapper.find('[data-test-subj="ruleSwitch"]').at(0).props().disabled).toBeTruthy(); + }); + + test('it renders switch enabled if "enabled" is true', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + expect(wrapper.find('[data-test-subj="ruleSwitch"]').at(0).props().checked).toBeTruthy(); + }); + + test('it renders switch disabled if "enabled" is false', () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + expect(wrapper.find('[data-test-subj="ruleSwitch"]').at(0).props().checked).toBeFalsy(); + }); + + test('it renders an off switch enabled on click', async () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + wrapper.find('[data-test-subj="ruleSwitch"]').at(2).simulate('click'); + + await waitFor(() => { + wrapper.update(); + expect(wrapper.find('[data-test-subj="ruleSwitch"]').at(1).props().checked).toBeTruthy(); + }); + }); + + test('it renders an on switch off on click', async () => { + const rule: RulesSchema = { ...getRulesSchemaMock(), enabled: false }; + + (enableRules as jest.Mock).mockResolvedValue([rule]); + + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + wrapper.find('[data-test-subj="ruleSwitch"]').at(2).simulate('click'); + + await waitFor(() => { + wrapper.update(); + expect(wrapper.find('[data-test-subj="ruleSwitch"]').at(1).props().checked).toBeFalsy(); + }); + }); + + test('it dispatches error toaster if "enableRules" call rejects', async () => { + const mockError = new Error('uh oh'); + (enableRules as jest.Mock).mockRejectedValue(mockError); + + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + ); - expect(wrapper).toMatchSnapshot(); + wrapper.find('[data-test-subj="ruleSwitch"]').at(2).simulate('click'); + + await waitFor(() => { + wrapper.update(); + expect(displayErrorToast).toHaveBeenCalledTimes(1); + }); + }); + + test('it dispatches error toaster if "enableRules" call resolves with some errors', async () => { + (enableRules as jest.Mock).mockResolvedValue([ + getRulesSchemaMock(), + { error: { status_code: 400, message: 'error' } }, + { error: { status_code: 400, message: 'error' } }, + ]); + + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + wrapper.find('[data-test-subj="ruleSwitch"]').at(2).simulate('click'); + + await waitFor(() => { + wrapper.update(); + expect(displayErrorToast).toHaveBeenCalledTimes(1); + }); + }); + + test('it invokes "enableRulesAction" if dispatch is passed through', async () => { + const wrapper = mount( + ({ eui: euiLightVars, darkMode: false })}> + + + ); + wrapper.find('[data-test-subj="ruleSwitch"]').at(2).simulate('click'); + + await waitFor(() => { + wrapper.update(); + expect(enableRulesAction).toHaveBeenCalledTimes(1); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/index.tsx index 73d66bf024a6..1a9bcca7eb60 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/index.tsx @@ -13,7 +13,7 @@ import { } from '@elastic/eui'; import { isEmpty } from 'lodash/fp'; import styled from 'styled-components'; -import React, { useCallback, useState, useEffect } from 'react'; +import React, { useMemo, useCallback, useState, useEffect } from 'react'; import * as i18n from '../../../pages/detection_engine/rules/translations'; import { enableRules } from '../../../containers/detection_engine/rules'; @@ -63,8 +63,11 @@ export const RuleSwitchComponent = ({ if (dispatch != null) { await enableRulesAction([id], event.target.checked!, dispatch, dispatchToaster); } else { + const enabling = event.target.checked!; + const title = enabling + ? i18n.BATCH_ACTION_ACTIVATE_SELECTED_ERROR(1) + : i18n.BATCH_ACTION_DEACTIVATE_SELECTED_ERROR(1); try { - const enabling = event.target.checked!; const response = await enableRules({ ids: [id], enabled: enabling, @@ -73,9 +76,7 @@ export const RuleSwitchComponent = ({ if (errors.length > 0) { setMyIsLoading(false); - const title = enabling - ? i18n.BATCH_ACTION_ACTIVATE_SELECTED_ERROR(1) - : i18n.BATCH_ACTION_DEACTIVATE_SELECTED_ERROR(1); + displayErrorToast( title, errors.map((e) => e.error.message), @@ -88,8 +89,9 @@ export const RuleSwitchComponent = ({ onChange(rule.enabled); } } - } catch { + } catch (err) { setMyIsLoading(false); + displayErrorToast(title, err.message, dispatchToaster); } } setMyIsLoading(false); @@ -105,21 +107,22 @@ export const RuleSwitchComponent = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [enabled]); - useEffect(() => { + const showLoader = useMemo((): boolean => { if (myIsLoading !== isLoading) { - setMyIsLoading(isLoading ?? false); + return isLoading ?? false; } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isLoading]); + + return myIsLoading; + }, [myIsLoading, isLoading]); return ( - {myIsLoading ? ( - + {showLoader ? ( + ) : ( search: rule.id, searchFields: ['alertId'], }); - return transformValidateBulkError( - rule.id, - rule, - ruleActions, - ruleStatuses.saved_objects[0] - ); + return transformValidateBulkError(rule.id, rule, ruleActions, ruleStatuses); } else { return getIdBulkError({ id, ruleId }); } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts index 8828bbe6c982..ddc2ade9b5ac 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.ts @@ -50,7 +50,6 @@ export const updateRulesBulkRoute = (router: IRouter, ml: SetupPlugins['ml']) => if (!siemClient || !alertsClient) { return siemResponse.error({ statusCode: 404 }); } - const mlAuthz = buildMlAuthz({ license: context.licensing.license, ml, request }); const ruleStatusClient = ruleStatusSavedObjectsClientFactory(savedObjectsClient); const rules = await Promise.all( @@ -192,12 +191,7 @@ export const updateRulesBulkRoute = (router: IRouter, ml: SetupPlugins['ml']) => search: rule.id, searchFields: ['alertId'], }); - return transformValidateBulkError( - rule.id, - rule, - ruleActions, - ruleStatuses.saved_objects[0] - ); + return transformValidateBulkError(rule.id, rule, ruleActions, ruleStatuses); } else { return getIdBulkError({ id, ruleId }); } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.test.ts index 06ec22b2f61b..6bdbfedf625d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.test.ts @@ -9,13 +9,13 @@ import { transformValidateFindAlerts, transformValidateBulkError, } from './validate'; -import { getResult } from '../__mocks__/request_responses'; import { FindResult } from '../../../../../../alerts/server'; import { BulkError } from '../utils'; -import { RulesSchema } from '../../../../../common/detection_engine/schemas/response/rules_schema'; +import { RulesSchema } from '../../../../../common/detection_engine/schemas/response'; +import { getResult, getFindResultStatus } from '../__mocks__/request_responses'; import { getListArrayMock } from '../../../../../common/detection_engine/schemas/types/lists.mock'; -export const ruleOutput: RulesSchema = { +export const ruleOutput = (): RulesSchema => ({ actions: [], author: ['Elastic'], created_at: '2019-12-13T16:40:33.400Z', @@ -80,14 +80,14 @@ export const ruleOutput: RulesSchema = { note: '# Investigative notes', timeline_title: 'some-timeline-title', timeline_id: 'some-timeline-id', -}; +}); describe('validate', () => { describe('transformValidate', () => { test('it should do a validation correctly of a partial alert', () => { const ruleAlert = getResult(); const [validated, errors] = transformValidate(ruleAlert); - expect(validated).toEqual(ruleOutput); + expect(validated).toEqual(ruleOutput()); expect(errors).toEqual(null); }); @@ -103,14 +103,35 @@ describe('validate', () => { describe('transformValidateFindAlerts', () => { test('it should do a validation correctly of a find alert', () => { - const findResult: FindResult = { data: [getResult()], page: 1, perPage: 0, total: 0 }; + const findResult: FindResult = { + data: [getResult()], + page: 1, + perPage: 0, + total: 0, + }; const [validated, errors] = transformValidateFindAlerts(findResult, []); - expect(validated).toEqual({ data: [ruleOutput], page: 1, perPage: 0, total: 0 }); + const expected: { + page: number; + perPage: number; + total: number; + data: Array>; + } | null = { + data: [ruleOutput()], + page: 1, + perPage: 0, + total: 0, + }; + expect(validated).toEqual(expected); expect(errors).toEqual(null); }); test('it should do an in-validation correctly of a partial alert', () => { - const findResult: FindResult = { data: [getResult()], page: 1, perPage: 0, total: 0 }; + const findResult: FindResult = { + data: [getResult()], + page: 1, + perPage: 0, + total: 0, + }; // @ts-expect-error delete findResult.page; const [validated, errors] = transformValidateFindAlerts(findResult, []); @@ -123,7 +144,7 @@ describe('validate', () => { test('it should do a validation correctly of a rule id', () => { const ruleAlert = getResult(); const validatedOrError = transformValidateBulkError('rule-1', ruleAlert); - expect(validatedOrError).toEqual(ruleOutput); + expect(validatedOrError).toEqual(ruleOutput()); }); test('it should do an in-validation correctly of a rule id', () => { @@ -140,5 +161,34 @@ describe('validate', () => { }; expect(validatedOrError).toEqual(expected); }); + + test('it should do a validation correctly of a rule id with ruleStatus passed in', () => { + const ruleStatus = getFindResultStatus(); + const ruleAlert = getResult(); + const validatedOrError = transformValidateBulkError('rule-1', ruleAlert, null, ruleStatus); + const expected: RulesSchema = { + ...ruleOutput(), + status: 'succeeded', + status_date: '2020-02-18T15:26:49.783Z', + last_success_at: '2020-02-18T15:26:49.783Z', + last_success_message: 'succeeded', + }; + expect(validatedOrError).toEqual(expected); + }); + + test('it should return error object if "alert" is not expected alert type', () => { + const ruleAlert = getResult(); + // @ts-expect-error + delete ruleAlert.alertTypeId; + const validatedOrError = transformValidateBulkError('rule-1', ruleAlert); + const expected: BulkError = { + error: { + message: 'Internal error transforming', + status_code: 500, + }, + rule_id: 'rule-1', + }; + expect(validatedOrError).toEqual(expected); + }); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts index 983382b28ab3..27100eaebea1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts @@ -22,6 +22,7 @@ import { isAlertType, IRuleSavedAttributesSavedObjectAttributes, isRuleStatusFindType, + IRuleStatusSOAttributes, } from '../../rules/types'; import { createBulkErrorObject, BulkError } from '../utils'; import { transformFindAlerts, transform, transformAlertToRule } from './utils'; @@ -74,7 +75,7 @@ export const transformValidateBulkError = ( ruleId: string, alert: PartialAlert, ruleActions?: RuleActions | null, - ruleStatus?: unknown + ruleStatus?: SavedObjectsFindResponse ): RulesSchema | BulkError => { if (isAlertType(alert)) { if (isRuleStatusFindType(ruleStatus) && ruleStatus?.saved_objects.length > 0) { diff --git a/x-pack/plugins/security_solution/server/usage/detections/detections_helpers.ts b/x-pack/plugins/security_solution/server/usage/detections/detections_helpers.ts index 5cf17af2fa9c..6387839db3bf 100644 --- a/x-pack/plugins/security_solution/server/usage/detections/detections_helpers.ts +++ b/x-pack/plugins/security_solution/server/usage/detections/detections_helpers.ts @@ -172,7 +172,7 @@ export const getMlJobsUsage = async (ml: MlPluginSetup | undefined): Promise { const serverBasePath = http.basePath.serverBasePath; - const path = request.url.pathname!; + const path = request.url.pathname; const spaceId = spacesService.getSpaceId(request); diff --git a/x-pack/plugins/spaces/server/lib/request_interceptors/on_request_interceptor.ts b/x-pack/plugins/spaces/server/lib/request_interceptors/on_request_interceptor.ts index 6408803c2114..a3335b1e075f 100644 --- a/x-pack/plugins/spaces/server/lib/request_interceptors/on_request_interceptor.ts +++ b/x-pack/plugins/spaces/server/lib/request_interceptors/on_request_interceptor.ts @@ -9,8 +9,6 @@ import { LifecycleResponseFactory, CoreSetup, } from 'src/core/server'; -import { format } from 'url'; -import { modifyUrl } from '../utils/url'; import { getSpaceIdFromPath } from '../../../common'; export interface OnRequestInterceptorDeps { @@ -34,16 +32,9 @@ export function initSpacesOnRequestInterceptor({ http }: OnRequestInterceptorDep http.basePath.set(request, reqBasePath); - const newLocation = (path && path.substr(reqBasePath.length)) || '/'; + const newPathname = path.substr(reqBasePath.length) || '/'; - const newUrl = modifyUrl(format(request.url), (parts) => { - return { - ...parts, - pathname: newLocation, - }; - }); - - return toolkit.rewriteUrl(newUrl); + return toolkit.rewriteUrl(`${newPathname}${request.url.search}`); } return toolkit.next(); diff --git a/x-pack/plugins/spaces/server/spaces_service/spaces_service.test.ts b/x-pack/plugins/spaces/server/spaces_service/spaces_service.test.ts index b48bf971d0c1..d1e1d8113494 100644 --- a/x-pack/plugins/spaces/server/spaces_service/spaces_service.test.ts +++ b/x-pack/plugins/spaces/server/spaces_service/spaces_service.test.ts @@ -58,7 +58,7 @@ const createService = async (serverBasePath: string = '') => { serverBasePath, } as HttpServiceSetup['basePath']; httpSetup.basePath.get = jest.fn().mockImplementation((request: KibanaRequest) => { - const { spaceId } = getSpaceIdFromPath(request.url.path); + const { spaceId } = getSpaceIdFromPath(request.url.pathname); if (spaceId !== DEFAULT_SPACE_ID) { return `/s/${spaceId}`; @@ -83,7 +83,7 @@ describe('SpacesService', () => { const spacesServiceSetup = await createService(); const request: KibanaRequest = { - url: { path: '/app/kibana' }, + url: { pathname: '/app/kibana' }, } as KibanaRequest; expect(spacesServiceSetup.getSpaceId(request)).toEqual(DEFAULT_SPACE_ID); @@ -93,7 +93,7 @@ describe('SpacesService', () => { const spacesServiceSetup = await createService(); const request: KibanaRequest = { - url: { path: '/s/foo/app/kibana' }, + url: { pathname: '/s/foo/app/kibana' }, } as KibanaRequest; expect(spacesServiceSetup.getSpaceId(request)).toEqual('foo'); @@ -140,7 +140,7 @@ describe('SpacesService', () => { const spacesServiceSetup = await createService(); const request: KibanaRequest = { - url: { path: '/app/kibana' }, + url: { pathname: '/app/kibana' }, } as KibanaRequest; expect(spacesServiceSetup.isInDefaultSpace(request)).toEqual(true); @@ -150,7 +150,7 @@ describe('SpacesService', () => { const spacesServiceSetup = await createService(); const request: KibanaRequest = { - url: { path: '/s/foo/app/kibana' }, + url: { pathname: '/s/foo/app/kibana' }, } as KibanaRequest; expect(spacesServiceSetup.isInDefaultSpace(request)).toEqual(false); diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts index e33a3e775ca9..2f0cf3cbbcd1 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type.test.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { Writable } from '@kbn/utility-types'; import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; import { getAlertType } from './alert_type'; import { Params } from './alert_type_params'; diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type_params.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type_params.test.ts index c209894fb6e8..3b771403b8b1 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type_params.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/alert_type_params.test.ts @@ -7,6 +7,7 @@ import { ParamsSchema, Params } from './alert_type_params'; import { runTests } from './lib/core_query_types.test'; import { TypeOf } from '@kbn/config-schema'; +import type { Writable } from '@kbn/utility-types'; const DefaultParams: Writable> = { index: 'index-name', diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/lib/core_query_types.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/lib/core_query_types.test.ts index 6c9c3542aea0..be8e61eac8cb 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/lib/core_query_types.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/lib/core_query_types.test.ts @@ -7,6 +7,7 @@ // tests of common properties on time_series_query and alert_type_params import { ObjectType } from '@kbn/config-schema'; +import type { Writable } from '@kbn/utility-types'; import { CoreQueryParams } from './core_query_types'; import { MAX_GROUPS } from '../index'; diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/lib/time_series_types.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/lib/time_series_types.test.ts index ec164122032c..58f7652eaf07 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/lib/time_series_types.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/lib/time_series_types.test.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import type { Writable } from '@kbn/utility-types'; import { TimeSeriesQuerySchema, TimeSeriesQuery } from './time_series_types'; import { runTests } from './core_query_types.test'; import { TypeOf } from '@kbn/config-schema'; diff --git a/x-pack/plugins/task_manager/server/monitoring/index.ts b/x-pack/plugins/task_manager/server/monitoring/index.ts index 8e71ce2519a7..0a4c8c56a5a7 100644 --- a/x-pack/plugins/task_manager/server/monitoring/index.ts +++ b/x-pack/plugins/task_manager/server/monitoring/index.ts @@ -28,12 +28,20 @@ export { export function createMonitoringStats( taskPollingLifecycle: TaskPollingLifecycle, taskStore: TaskStore, + elasticsearchAndSOAvailability$: Observable, config: TaskManagerConfig, managedConfig: ManagedConfiguration, logger: Logger ): Observable { return createMonitoringStatsStream( - createAggregators(taskPollingLifecycle, taskStore, config, managedConfig, logger), + createAggregators( + taskPollingLifecycle, + taskStore, + elasticsearchAndSOAvailability$, + config, + managedConfig, + logger + ), config ); } diff --git a/x-pack/plugins/task_manager/server/monitoring/monitoring_stats_stream.ts b/x-pack/plugins/task_manager/server/monitoring/monitoring_stats_stream.ts index 374660a257c5..524afb8d78e2 100644 --- a/x-pack/plugins/task_manager/server/monitoring/monitoring_stats_stream.ts +++ b/x-pack/plugins/task_manager/server/monitoring/monitoring_stats_stream.ts @@ -63,6 +63,7 @@ export interface RawMonitoringStats { export function createAggregators( taskPollingLifecycle: TaskPollingLifecycle, taskStore: TaskStore, + elasticsearchAndSOAvailability$: Observable, config: TaskManagerConfig, managedConfig: ManagedConfiguration, logger: Logger @@ -72,6 +73,7 @@ export function createAggregators( createTaskRunAggregator(taskPollingLifecycle, config.monitored_stats_running_average_window), createWorkloadAggregator( taskStore, + elasticsearchAndSOAvailability$, config.monitored_aggregated_stats_refresh_rate, config.poll_interval, logger diff --git a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.test.ts b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.test.ts index d9af3307e75c..cb6e48530b02 100644 --- a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.test.ts +++ b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.test.ts @@ -17,6 +17,8 @@ import { ESSearchResponse } from '../../../apm/typings/elasticsearch'; import { AggregationResultOf } from '../../../apm/typings/elasticsearch/aggregations'; import { times } from 'lodash'; import { taskStoreMock } from '../task_store.mock'; +import { of, Subject } from 'rxjs'; +import { sleep } from '../test_utils'; type MockESResult = ESSearchResponse< ConcreteTaskInstance, @@ -75,6 +77,7 @@ describe('Workload Statistics Aggregator', () => { const workloadAggregator = createWorkloadAggregator( taskStore, + of(true), 10, 3000, loggingSystemMock.create().get() @@ -231,6 +234,7 @@ describe('Workload Statistics Aggregator', () => { const workloadAggregator = createWorkloadAggregator( taskStore, + of(true), 10, 3000, loggingSystemMock.create().get() @@ -252,12 +256,51 @@ describe('Workload Statistics Aggregator', () => { }); }); + test('skips summary of the workload when services are unavailable', async () => { + const taskStore = taskStoreMock.create({}); + taskStore.aggregate.mockResolvedValue(mockAggregatedResult()); + + const availability$ = new Subject(); + + const workloadAggregator = createWorkloadAggregator( + taskStore, + availability$, + 10, + 3000, + loggingSystemMock.create().get() + ); + + return new Promise(async (resolve) => { + workloadAggregator.pipe(first()).subscribe((result) => { + expect(result.key).toEqual('workload'); + expect(result.value).toMatchObject({ + count: 4, + task_types: { + actions_telemetry: { count: 2, status: { idle: 2 } }, + alerting_telemetry: { count: 1, status: { idle: 1 } }, + session_cleanup: { count: 1, status: { idle: 1 } }, + }, + }); + resolve(); + }); + + availability$.next(false); + + await sleep(10); + expect(taskStore.aggregate).not.toHaveBeenCalled(); + await sleep(10); + expect(taskStore.aggregate).not.toHaveBeenCalled(); + availability$.next(true); + }); + }); + test('returns a count of the overdue workload', async () => { const taskStore = taskStoreMock.create({}); taskStore.aggregate.mockResolvedValue(mockAggregatedResult()); const workloadAggregator = createWorkloadAggregator( taskStore, + of(true), 10, 3000, loggingSystemMock.create().get() @@ -280,6 +323,7 @@ describe('Workload Statistics Aggregator', () => { const workloadAggregator = createWorkloadAggregator( taskStore, + of(true), 10, 3000, loggingSystemMock.create().get() @@ -307,6 +351,7 @@ describe('Workload Statistics Aggregator', () => { const workloadAggregator = createWorkloadAggregator( taskStore, + of(true), 60 * 1000, 3000, loggingSystemMock.create().get() @@ -344,6 +389,7 @@ describe('Workload Statistics Aggregator', () => { const workloadAggregator = createWorkloadAggregator( taskStore, + of(true), 15 * 60 * 1000, 3000, loggingSystemMock.create().get() @@ -392,7 +438,7 @@ describe('Workload Statistics Aggregator', () => { }) ); const logger = loggingSystemMock.create().get(); - const workloadAggregator = createWorkloadAggregator(taskStore, 10, 3000, logger); + const workloadAggregator = createWorkloadAggregator(taskStore, of(true), 10, 3000, logger); return new Promise((resolve, reject) => { workloadAggregator.pipe(take(2), bufferCount(2)).subscribe((results) => { diff --git a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts index fe70f24684ad..17448ea412ae 100644 --- a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts +++ b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { timer } from 'rxjs'; -import { mergeMap, map, catchError } from 'rxjs/operators'; +import { combineLatest, Observable, timer } from 'rxjs'; +import { mergeMap, map, filter, catchError } from 'rxjs/operators'; import { Logger } from 'src/core/server'; import { JsonObject } from 'src/plugins/kibana_utils/common'; import { keyBy, mapValues } from 'lodash'; @@ -94,6 +94,7 @@ const MAX_SHCEDULE_DENSITY_BUCKETS = 50; export function createWorkloadAggregator( taskStore: TaskStore, + elasticsearchAndSOAvailability$: Observable, refreshInterval: number, pollInterval: number, logger: Logger @@ -105,7 +106,8 @@ export function createWorkloadAggregator( MAX_SHCEDULE_DENSITY_BUCKETS ); - return timer(0, refreshInterval).pipe( + return combineLatest([timer(0, refreshInterval), elasticsearchAndSOAvailability$]).pipe( + filter(([, areElasticsearchAndSOAvailable]) => areElasticsearchAndSOAvailable), mergeMap(() => taskStore.aggregate({ aggs: { diff --git a/x-pack/plugins/task_manager/server/plugin.test.ts b/x-pack/plugins/task_manager/server/plugin.test.ts index 8388468164a4..9a1d83f6195a 100644 --- a/x-pack/plugins/task_manager/server/plugin.test.ts +++ b/x-pack/plugins/task_manager/server/plugin.test.ts @@ -4,9 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { TaskManagerPlugin } from './plugin'; +import { TaskManagerPlugin, getElasticsearchAndSOAvailability } from './plugin'; import { coreMock } from '../../../../src/core/server/mocks'; import { TaskManagerConfig } from './config'; +import { Subject } from 'rxjs'; +import { bufferCount, take } from 'rxjs/operators'; +import { CoreStatus, ServiceStatusLevels } from 'src/core/server'; describe('TaskManagerPlugin', () => { describe('setup', () => { @@ -88,4 +91,99 @@ describe('TaskManagerPlugin', () => { ); }); }); + + describe('getElasticsearchAndSOAvailability', () => { + test('returns true when both services are available', async () => { + const core$ = new Subject(); + + const availability = getElasticsearchAndSOAvailability(core$) + .pipe(take(1), bufferCount(1)) + .toPromise(); + + core$.next(mockCoreStatusAvailability({ elasticsearch: true, savedObjects: true })); + + expect(await availability).toEqual([true]); + }); + + test('returns false when both services are unavailable', async () => { + const core$ = new Subject(); + + const availability = getElasticsearchAndSOAvailability(core$) + .pipe(take(1), bufferCount(1)) + .toPromise(); + + core$.next(mockCoreStatusAvailability({ elasticsearch: false, savedObjects: false })); + + expect(await availability).toEqual([false]); + }); + + test('returns false when one service is unavailable but the other is available', async () => { + const core$ = new Subject(); + + const availability = getElasticsearchAndSOAvailability(core$) + .pipe(take(1), bufferCount(1)) + .toPromise(); + + core$.next(mockCoreStatusAvailability({ elasticsearch: true, savedObjects: false })); + + expect(await availability).toEqual([false]); + }); + + test('shift back and forth between values as status changes', async () => { + const core$ = new Subject(); + + const availability = getElasticsearchAndSOAvailability(core$) + .pipe(take(3), bufferCount(3)) + .toPromise(); + + core$.next(mockCoreStatusAvailability({ elasticsearch: true, savedObjects: false })); + + core$.next(mockCoreStatusAvailability({ elasticsearch: true, savedObjects: true })); + + core$.next(mockCoreStatusAvailability({ elasticsearch: false, savedObjects: false })); + + expect(await availability).toEqual([false, true, false]); + }); + + test(`skips values when the status hasn't changed`, async () => { + const core$ = new Subject(); + + const availability = getElasticsearchAndSOAvailability(core$) + .pipe(take(3), bufferCount(3)) + .toPromise(); + + core$.next(mockCoreStatusAvailability({ elasticsearch: true, savedObjects: false })); + + // still false, so shouldn't emit a second time + core$.next(mockCoreStatusAvailability({ elasticsearch: false, savedObjects: true })); + + core$.next(mockCoreStatusAvailability({ elasticsearch: true, savedObjects: true })); + + // shouldn't emit as already true + core$.next(mockCoreStatusAvailability({ elasticsearch: true, savedObjects: true })); + + core$.next(mockCoreStatusAvailability({ elasticsearch: false, savedObjects: false })); + + expect(await availability).toEqual([false, true, false]); + }); + }); }); + +function mockCoreStatusAvailability({ + elasticsearch, + savedObjects, +}: { + elasticsearch: boolean; + savedObjects: boolean; +}) { + return { + elasticsearch: { + level: elasticsearch ? ServiceStatusLevels.available : ServiceStatusLevels.unavailable, + summary: '', + }, + savedObjects: { + level: savedObjects ? ServiceStatusLevels.available : ServiceStatusLevels.unavailable, + summary: '', + }, + }; +} diff --git a/x-pack/plugins/task_manager/server/plugin.ts b/x-pack/plugins/task_manager/server/plugin.ts index 0e7abb817490..70688cd169d7 100644 --- a/x-pack/plugins/task_manager/server/plugin.ts +++ b/x-pack/plugins/task_manager/server/plugin.ts @@ -3,9 +3,17 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { PluginInitializerContext, Plugin, CoreSetup, Logger, CoreStart } from 'src/core/server'; -import { combineLatest, Subject } from 'rxjs'; -import { first, map } from 'rxjs/operators'; +import { combineLatest, Observable, Subject } from 'rxjs'; +import { first, map, distinctUntilChanged } from 'rxjs/operators'; +import { + PluginInitializerContext, + Plugin, + CoreSetup, + Logger, + CoreStart, + ServiceStatusLevels, + CoreStatus, +} from '../../../../src/core/server'; import { TaskDefinition } from './task'; import { TaskPollingLifecycle } from './polling_lifecycle'; import { TaskManagerConfig } from './config'; @@ -37,6 +45,7 @@ export class TaskManagerPlugin private logger: Logger; private definitions: TaskTypeDictionary; private middleware: Middleware = createInitialMiddleware(); + private elasticsearchAndSOAvailability$?: Observable; private monitoringStats$ = new Subject(); constructor(private readonly initContext: PluginInitializerContext) { @@ -51,6 +60,8 @@ export class TaskManagerPlugin .pipe(first()) .toPromise(); + this.elasticsearchAndSOAvailability$ = getElasticsearchAndSOAvailability(core.status.core$); + setupSavedObjects(core.savedObjects, this.config); this.taskManagerId = this.initContext.env.instanceUuid; @@ -115,19 +126,20 @@ export class TaskManagerPlugin startingPollInterval: this.config!.poll_interval, }); - const taskPollingLifecycle = new TaskPollingLifecycle({ + this.taskPollingLifecycle = new TaskPollingLifecycle({ config: this.config!, definitions: this.definitions, logger: this.logger, taskStore, middleware: this.middleware, + elasticsearchAndSOAvailability$: this.elasticsearchAndSOAvailability$!, ...managedConfiguration, }); - this.taskPollingLifecycle = taskPollingLifecycle; createMonitoringStats( - taskPollingLifecycle, + this.taskPollingLifecycle, taskStore, + this.elasticsearchAndSOAvailability$!, this.config!, managedConfiguration, this.logger @@ -137,12 +149,9 @@ export class TaskManagerPlugin logger: this.logger, taskStore, middleware: this.middleware, - taskPollingLifecycle, + taskPollingLifecycle: this.taskPollingLifecycle, }); - // start polling for work - taskPollingLifecycle.start(); - return { fetch: (opts: SearchOpts): Promise => taskStore.fetch(opts), get: (id: string) => taskStore.get(id), @@ -153,12 +162,6 @@ export class TaskManagerPlugin }; } - public stop() { - if (this.taskPollingLifecycle) { - this.taskPollingLifecycle.stop(); - } - } - /** * Ensures task manager hasn't started * @@ -171,3 +174,16 @@ export class TaskManagerPlugin } } } + +export function getElasticsearchAndSOAvailability( + core$: Observable +): Observable { + return core$.pipe( + map( + ({ elasticsearch, savedObjects }) => + elasticsearch.level === ServiceStatusLevels.available && + savedObjects.level === ServiceStatusLevels.available + ), + distinctUntilChanged() + ); +} diff --git a/x-pack/plugins/task_manager/server/polling_lifecycle.mock.ts b/x-pack/plugins/task_manager/server/polling_lifecycle.mock.ts index 9df1e06165bc..286e29194d6e 100644 --- a/x-pack/plugins/task_manager/server/polling_lifecycle.mock.ts +++ b/x-pack/plugins/task_manager/server/polling_lifecycle.mock.ts @@ -10,7 +10,6 @@ import { of, Observable } from 'rxjs'; export const taskPollingLifecycleMock = { create(opts: { isStarted?: boolean; events$?: Observable }) { return ({ - start: jest.fn(), attemptToRun: jest.fn(), get isStarted() { return opts.isStarted ?? true; @@ -18,7 +17,6 @@ export const taskPollingLifecycleMock = { get events() { return opts.events$ ?? of(); }, - stop: jest.fn(), } as unknown) as jest.Mocked; }, }; diff --git a/x-pack/plugins/task_manager/server/polling_lifecycle.test.ts b/x-pack/plugins/task_manager/server/polling_lifecycle.test.ts index 5f2e774177fd..0f807976970c 100644 --- a/x-pack/plugins/task_manager/server/polling_lifecycle.test.ts +++ b/x-pack/plugins/task_manager/server/polling_lifecycle.test.ts @@ -6,7 +6,7 @@ import _ from 'lodash'; import sinon from 'sinon'; -import { of } from 'rxjs'; +import { of, Subject } from 'rxjs'; import { TaskPollingLifecycle, claimAvailableTasks } from './polling_lifecycle'; import { createInitialMiddleware } from './lib/middleware'; @@ -55,15 +55,64 @@ describe('TaskPollingLifecycle', () => { afterEach(() => clock.restore()); describe('start', () => { - test('begins polling once start is called', () => { - const taskManager = new TaskPollingLifecycle(taskManagerOpts); + test('begins polling once the ES and SavedObjects services are available', () => { + const elasticsearchAndSOAvailability$ = new Subject(); + new TaskPollingLifecycle({ + elasticsearchAndSOAvailability$, + ...taskManagerOpts, + }); + + clock.tick(150); + expect(mockTaskStore.claimAvailableTasks).not.toHaveBeenCalled(); + + elasticsearchAndSOAvailability$.next(true); + + clock.tick(150); + expect(mockTaskStore.claimAvailableTasks).toHaveBeenCalled(); + }); + }); + + describe('stop', () => { + test('stops polling once the ES and SavedObjects services become unavailable', () => { + const elasticsearchAndSOAvailability$ = new Subject(); + new TaskPollingLifecycle({ + elasticsearchAndSOAvailability$, + ...taskManagerOpts, + }); + + elasticsearchAndSOAvailability$.next(true); + + clock.tick(150); + expect(mockTaskStore.claimAvailableTasks).toHaveBeenCalled(); + elasticsearchAndSOAvailability$.next(false); + + mockTaskStore.claimAvailableTasks.mockClear(); clock.tick(150); expect(mockTaskStore.claimAvailableTasks).not.toHaveBeenCalled(); + }); + + test('restarts polling once the ES and SavedObjects services become available again', () => { + const elasticsearchAndSOAvailability$ = new Subject(); + new TaskPollingLifecycle({ + elasticsearchAndSOAvailability$, + ...taskManagerOpts, + }); + + elasticsearchAndSOAvailability$.next(true); - taskManager.start(); + clock.tick(150); + expect(mockTaskStore.claimAvailableTasks).toHaveBeenCalled(); + elasticsearchAndSOAvailability$.next(false); + mockTaskStore.claimAvailableTasks.mockClear(); clock.tick(150); + + expect(mockTaskStore.claimAvailableTasks).not.toHaveBeenCalled(); + + elasticsearchAndSOAvailability$.next(true); + clock.tick(150); + expect(mockTaskStore.claimAvailableTasks).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/task_manager/server/polling_lifecycle.ts b/x-pack/plugins/task_manager/server/polling_lifecycle.ts index ba19cb63fffa..ccba750401f2 100644 --- a/x-pack/plugins/task_manager/server/polling_lifecycle.ts +++ b/x-pack/plugins/task_manager/server/polling_lifecycle.ts @@ -48,6 +48,7 @@ export type TaskPollingLifecycleOpts = { taskStore: TaskStore; config: TaskManagerConfig; middleware: Middleware; + elasticsearchAndSOAvailability$: Observable; } & ManagedConfiguration; export type TaskLifecycleEvent = @@ -72,8 +73,6 @@ export class TaskPollingLifecycle { private events$ = new Subject(); // all on-demand requests we wish to pipe into the poller private claimRequests$ = new Subject>(); - // the task poller that polls for work on fixed intervals and on demand - private poller$: Observable>>; // our subscription to the poller private pollingSubscription: Subscription = Subscription.EMPTY; @@ -84,36 +83,50 @@ export class TaskPollingLifecycle { * enabling the task manipulation methods, and beginning the background polling * mechanism. */ - constructor(opts: TaskPollingLifecycleOpts) { - const { logger, middleware, maxWorkersConfiguration$, pollIntervalConfiguration$ } = opts; + constructor({ + logger, + middleware, + maxWorkersConfiguration$, + pollIntervalConfiguration$, + // Elasticsearch and SavedObjects availability status + elasticsearchAndSOAvailability$, + config, + taskStore, + definitions, + }: TaskPollingLifecycleOpts) { this.logger = logger; this.middleware = middleware; + this.definitions = definitions; + this.store = taskStore; - this.definitions = opts.definitions; - this.store = opts.taskStore; // pipe store events into the lifecycle event stream this.store.events.subscribe((event) => this.events$.next(event)); this.bufferedStore = new BufferedTaskStore(this.store, { - bufferMaxOperations: opts.config.max_workers, - logger: this.logger, + bufferMaxOperations: config.max_workers, + logger, }); this.pool = new TaskPool({ - logger: this.logger, + logger, maxWorkers$: maxWorkersConfiguration$, }); const { max_poll_inactivity_cycles: maxPollInactivityCycles, poll_interval: pollInterval, - } = opts.config; - this.poller$ = createObservableMonitor>, Error>( + } = config; + + // the task poller that polls for work on fixed intervals and on demand + const poller$: Observable + >> = createObservableMonitor>, Error>( () => createTaskPoller({ - logger: this.logger, + logger, pollInterval$: pollIntervalConfiguration$, - bufferCapacity: opts.config.request_capacity, + bufferCapacity: config.request_capacity, getCapacity: () => this.pool.availableWorkers, pollRequests$: this.claimRequests$, work: this.pollForWork, @@ -133,10 +146,20 @@ export class TaskPollingLifecycle { // operation than just timing out the `work` internally) inactivityTimeout: pollInterval * (maxPollInactivityCycles + 1), onError: (error) => { - this.logger.error(`[Task Poller Monitor]: ${error.message}`); + logger.error(`[Task Poller Monitor]: ${error.message}`); }, } ); + + elasticsearchAndSOAvailability$.subscribe((areESAndSOAvailable) => { + if (areESAndSOAvailable && !this.isStarted) { + // start polling for work + this.pollingSubscription = this.subscribeToPoller(poller$); + } else if (!areESAndSOAvailable && this.isStarted) { + this.pollingSubscription.unsubscribe(); + this.pool.cancelRunningTasks(); + } + }); } public get events(): Observable { @@ -184,39 +207,24 @@ export class TaskPollingLifecycle { ); }; - /** - * Starts up the task manager and starts picking up tasks. - */ - public start() { - if (!this.isStarted) { - this.pollingSubscription = this.poller$ - .pipe( - tap( - mapErr((error: PollingError) => { - if (error.type === PollingErrorType.RequestCapacityReached) { - pipe( - error.data, - mapOptional((id) => this.emitEvent(asTaskRunRequestEvent(id, asErr(error)))) - ); - } - this.logger.error(error.message); - }) - ) + private subscribeToPoller(poller$: Observable>>) { + return poller$ + .pipe( + tap( + mapErr((error: PollingError) => { + if (error.type === PollingErrorType.RequestCapacityReached) { + pipe( + error.data, + mapOptional((id) => this.emitEvent(asTaskRunRequestEvent(id, asErr(error)))) + ); + } + this.logger.error(error.message); + }) ) - .subscribe((event: Result>) => { - this.emitEvent(asTaskPollingCycleEvent(event)); - }); - } - } - - /** - * Stops the task manager and cancels running tasks. - */ - public stop() { - if (this.isStarted) { - this.pollingSubscription.unsubscribe(); - this.pool.cancelRunningTasks(); - } + ) + .subscribe((event: Result>) => { + this.emitEvent(asTaskPollingCycleEvent(event)); + }); } } diff --git a/x-pack/plugins/task_manager/server/routes/_mock_handler_arguments.ts b/x-pack/plugins/task_manager/server/routes/_mock_handler_arguments.ts index c9f4de25afaf..2affbc7dbf7e 100644 --- a/x-pack/plugins/task_manager/server/routes/_mock_handler_arguments.ts +++ b/x-pack/plugins/task_manager/server/routes/_mock_handler_arguments.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import type { MethodKeysOf } from '@kbn/utility-types'; import { RequestHandlerContext, KibanaRequest, KibanaResponseFactory } from 'kibana/server'; import { identity } from 'lodash'; import { httpServerMock } from '../../../../../src/core/server/mocks'; diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 396a06205eaa..2b3ff6c8a0ae 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -1706,6 +1706,16 @@ "properties": { "overview": { "type": "long" + }, + "setup_guide": { + "type": "long" + } + } + }, + "ui_error": { + "properties": { + "cannot_connect": { + "type": "long" } } }, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 00e483fa079c..8bd3b0fcb7ed 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -5036,10 +5036,8 @@ "xpack.apm.rum.filters.url.noResults": "結果がありません", "xpack.apm.rum.jsErrors.errorMessage": "エラーメッセージ", "xpack.apm.rum.jsErrors.errorRate": "エラー率", - "xpack.apm.rum.jsErrors.errorRateValue": "{errorRate} %", "xpack.apm.rum.jsErrors.impactedPageLoads": "影響を受けるページ読み込み数", "xpack.apm.rum.jsErrors.totalErrors": "合計エラー数", - "xpack.apm.rum.userExperienceMetrics": "ユーザーエクスペリエンスメトリック", "xpack.apm.rum.uxMetrics.longestLongTasks": "最長タスク時間", "xpack.apm.rum.uxMetrics.noOfLongTasks": "時間がかかるタスク数", "xpack.apm.rum.uxMetrics.sumLongTasks": "時間がかかるタスクの合計時間", @@ -7210,6 +7208,578 @@ "xpack.fileUpload.jsonUploadAndParse.writingToIndex": "インデックスに書き込み中", "xpack.fileUpload.noIndexSuppliedErrorMessage": "インデックスが指定されていません。", "xpack.fileUpload.patternReader.featuresOmitted": "ジオメトリのない一部の機能は省略されました", + "xpack.fleet.agentBulkActions.agentsSelected": "{count, plural, one {#個のエージェント} other {#個のエージェント}}が選択されました", + "xpack.fleet.agentBulkActions.clearSelection": "選択した項目をクリア", + "xpack.fleet.agentBulkActions.reassignPolicy": "新しいポリシーに割り当てる", + "xpack.fleet.agentBulkActions.selectAll": "すべてのページのすべての項目を選択", + "xpack.fleet.agentBulkActions.totalAgents": "{count, plural, one {#個のエージェント} other {#個のエージェント}}を表示しています", + "xpack.fleet.agentBulkActions.totalAgentsWithLimit": "{count}/{total}個のエージェントを表示しています", + "xpack.fleet.agentBulkActions.unenrollAgents": "エージェントの登録を解除", + "xpack.fleet.agentBulkActions.upgradeAgents": "エージェントをアップグレード", + "xpack.fleet.agentDetails.actionsButton": "アクション", + "xpack.fleet.agentDetails.agentDetailsTitle": "エージェント'{id}'", + "xpack.fleet.agentDetails.agentNotFoundErrorDescription": "エージェントID {agentId}が見つかりません", + "xpack.fleet.agentDetails.agentNotFoundErrorTitle": "エージェントが見つかりません", + "xpack.fleet.agentDetails.agentPolicyLabel": "エージェントポリシー", + "xpack.fleet.agentDetails.agentVersionLabel": "エージェントバージョン", + "xpack.fleet.agentDetails.hostIdLabel": "エージェントID", + "xpack.fleet.agentDetails.hostNameLabel": "ホスト名", + "xpack.fleet.agentDetails.localMetadataSectionSubtitle": "メタデータを読み込み中", + "xpack.fleet.agentDetails.metadataSectionTitle": "メタデータ", + "xpack.fleet.agentDetails.platformLabel": "プラットフォーム", + "xpack.fleet.agentDetails.policyLabel": "ポリシー", + "xpack.fleet.agentDetails.releaseLabel": "エージェントリリース", + "xpack.fleet.agentDetails.statusLabel": "ステータス", + "xpack.fleet.agentDetails.subTabs.activityLogTab": "アクティビティログ", + "xpack.fleet.agentDetails.subTabs.detailsTab": "エージェントの詳細", + "xpack.fleet.agentDetails.unexceptedErrorTitle": "エージェントの読み込み中にエラーが発生しました", + "xpack.fleet.agentDetails.upgradeAvailableTooltip": "アップグレードが利用可能です", + "xpack.fleet.agentDetails.userProvidedMetadataSectionSubtitle": "ユーザー提供メタデータ", + "xpack.fleet.agentDetails.versionLabel": "エージェントバージョン", + "xpack.fleet.agentDetails.viewAgentListTitle": "すべてのエージェントを表示", + "xpack.fleet.agentEnrollment.agentDescription": "Elasticエージェントをホストに追加し、データを収集して、Elastic Stackに送信します。", + "xpack.fleet.agentEnrollment.agentsNotInitializedText": "エージェントを登録する前に、{link}。", + "xpack.fleet.agentEnrollment.cancelButtonLabel": "キャンセル", + "xpack.fleet.agentEnrollment.continueButtonLabel": "続行", + "xpack.fleet.agentEnrollment.copyPolicyButton": "クリップボードにコピー", + "xpack.fleet.agentEnrollment.copyRunInstructionsButton": "クリップボードにコピー", + "xpack.fleet.agentEnrollment.downloadDescription": "Elasticエージェントダウンロードページでは、エージェントバイナリと検証署名をダウンロードできます。", + "xpack.fleet.agentEnrollment.downloadLink": "ダウンロードページに移動", + "xpack.fleet.agentEnrollment.downloadPolicyButton": "ダウンロードポリシー", + "xpack.fleet.agentEnrollment.enrollFleetTabLabel": "Fleetで登録", + "xpack.fleet.agentEnrollment.enrollStandaloneTabLabel": "スタンドアロンで実行", + "xpack.fleet.agentEnrollment.flyoutTitle": "エージェントの追加", + "xpack.fleet.agentEnrollment.goToDataStreamsLink": "データストリーム", + "xpack.fleet.agentEnrollment.managedDescription": "ElasticエージェントをFleetに登録して、自動的に更新をデプロイしたり、一元的にエージェントを管理したりします。", + "xpack.fleet.agentEnrollment.setUpAgentsLink": "Elasticエージェントの集中管理を設定", + "xpack.fleet.agentEnrollment.standaloneDescription": "Elasticエージェントをスタンドアロンで実行して、エージェントがインストールされているホストで、手動でエージェントを構成および更新します。", + "xpack.fleet.agentEnrollment.stepCheckForDataDescription": "エージェントがデータの送信を開始します。{link}に移動して、データを表示してください。", + "xpack.fleet.agentEnrollment.stepCheckForDataTitle": "データを確認", + "xpack.fleet.agentEnrollment.stepChooseAgentPolicyTitle": "エージェントポリシーを選択", + "xpack.fleet.agentEnrollment.stepConfigureAgentDescription": "Elasticエージェントがインストールされているホストで、このポリシーを{fileName}にコピーします。Elasticsearch資格情報を使用するには、{fileName}ぎ{outputSection}セクションで、{ESUsernameVariable}と{ESPasswordVariable}を変更します。", + "xpack.fleet.agentEnrollment.stepConfigureAgentTitle": "エージェントの構成", + "xpack.fleet.agentEnrollment.stepDownloadAgentTitle": "Elasticエージェントをホストにダウンロード", + "xpack.fleet.agentEnrollment.stepEnrollAndRunAgentTitle": "Elasticエージェントを登録して実行", + "xpack.fleet.agentEnrollment.stepRunAgentDescription": "エージェントのディレクトリから、このコマンドを実行し、Elasticエージェントを、インストール、登録、起動します。このコマンドを再利用すると、複数のホストでエージェントを設定できます。管理者権限が必要です。", + "xpack.fleet.agentEnrollment.stepRunAgentTitle": "エージェントの起動", + "xpack.fleet.agentEventsList.collapseDetailsAriaLabel": "詳細を非表示", + "xpack.fleet.agentEventsList.expandDetailsAriaLabel": "詳細を表示", + "xpack.fleet.agentEventsList.messageColumnTitle": "メッセージ", + "xpack.fleet.agentEventsList.messageDetailsTitle": "メッセージ", + "xpack.fleet.agentEventsList.payloadDetailsTitle": "ペイロード", + "xpack.fleet.agentEventsList.refreshButton": "更新", + "xpack.fleet.agentEventsList.searchPlaceholderText": "アクティビティログを検索", + "xpack.fleet.agentEventsList.subtypeColumnTitle": "サブタイプ", + "xpack.fleet.agentEventsList.timestampColumnTitle": "タイムスタンプ", + "xpack.fleet.agentEventsList.typeColumnTitle": "タイプ", + "xpack.fleet.agentEventSubtype.acknowledgedLabel": "認識", + "xpack.fleet.agentEventSubtype.dataDumpLabel": "データダンプ", + "xpack.fleet.agentEventSubtype.degradedLabel": "劣化", + "xpack.fleet.agentEventSubtype.failedLabel": "失敗", + "xpack.fleet.agentEventSubtype.inProgressLabel": "進行中", + "xpack.fleet.agentEventSubtype.policyLabel": "ポリシー", + "xpack.fleet.agentEventSubtype.runningLabel": "実行中", + "xpack.fleet.agentEventSubtype.startingLabel": "開始中", + "xpack.fleet.agentEventSubtype.stoppedLabel": "停止", + "xpack.fleet.agentEventSubtype.stoppingLabel": "停止中", + "xpack.fleet.agentEventSubtype.unknownLabel": "不明", + "xpack.fleet.agentEventSubtype.updatingLabel": "更新中", + "xpack.fleet.agentEventType.actionLabel": "アクション", + "xpack.fleet.agentEventType.actionResultLabel": "アクション結果", + "xpack.fleet.agentEventType.errorLabel": "エラー", + "xpack.fleet.agentEventType.stateLabel": "ステータス", + "xpack.fleet.agentHealth.checkInTooltipText": "前回のチェックイン {lastCheckIn}", + "xpack.fleet.agentHealth.degradedStatusText": "劣化", + "xpack.fleet.agentHealth.enrollingStatusText": "登録中", + "xpack.fleet.agentHealth.errorStatusText": "エラー", + "xpack.fleet.agentHealth.inactiveStatusText": "非アクティブ", + "xpack.fleet.agentHealth.noCheckInTooltipText": "チェックインしない", + "xpack.fleet.agentHealth.offlineStatusText": "オフライン", + "xpack.fleet.agentHealth.onlineStatusText": "オンライン", + "xpack.fleet.agentHealth.unenrollingStatusText": "登録解除中", + "xpack.fleet.agentHealth.updatingStatusText": "更新中", + "xpack.fleet.agentHealth.warningStatusText": "エラー", + "xpack.fleet.agentList.actionsColumnTitle": "アクション", + "xpack.fleet.agentList.addButton": "エージェントの追加", + "xpack.fleet.agentList.agentUpgradeLabel": "アップグレードが利用可能です", + "xpack.fleet.agentList.clearFiltersLinkText": "フィルターを消去", + "xpack.fleet.agentList.enrollButton": "エージェントの追加", + "xpack.fleet.agentList.forceUnenrollOneButton": "強制的に登録解除する", + "xpack.fleet.agentList.hostColumnTitle": "ホスト", + "xpack.fleet.agentList.lastCheckinTitle": "前回のアクティビティ", + "xpack.fleet.agentList.loadingAgentsMessage": "エージェントを読み込み中...", + "xpack.fleet.agentList.noAgentsPrompt": "エージェントが登録されていません", + "xpack.fleet.agentList.noFilteredAgentsPrompt": "エージェントが見つかりません。{clearFiltersLink}", + "xpack.fleet.agentList.outOfDateLabel": "最新ではありません", + "xpack.fleet.agentList.policyColumnTitle": "エージェントポリシー", + "xpack.fleet.agentList.policyFilterText": "エージェントポリシー", + "xpack.fleet.agentList.reassignActionText": "新しいポリシーに割り当てる", + "xpack.fleet.agentList.revisionNumber": "rev. {revNumber}", + "xpack.fleet.agentList.showInactiveSwitchLabel": "非アクティブ", + "xpack.fleet.agentList.showUpgradeableFilterLabel": "アップグレードが利用可能です", + "xpack.fleet.agentList.statusColumnTitle": "ステータス", + "xpack.fleet.agentList.statusErrorFilterText": "エラー", + "xpack.fleet.agentList.statusFilterText": "ステータス", + "xpack.fleet.agentList.statusOfflineFilterText": "オフライン", + "xpack.fleet.agentList.statusOnlineFilterText": "オンライン", + "xpack.fleet.agentList.statusUpdatingFilterText": "更新中", + "xpack.fleet.agentList.unenrollOneButton": "エージェントの登録解除", + "xpack.fleet.agentList.upgradeOneButton": "エージェントをアップグレード", + "xpack.fleet.agentList.versionTitle": "バージョン", + "xpack.fleet.agentList.viewActionText": "エージェントを表示", + "xpack.fleet.agentListStatus.errorLabel": "エラー", + "xpack.fleet.agentListStatus.offlineLabel": "オフライン", + "xpack.fleet.agentListStatus.onlineLabel": "オンライン", + "xpack.fleet.agentListStatus.totalLabel": "エージェント", + "xpack.fleet.agentPolicy.confirmModalCalloutDescription": "選択されたエージェントポリシー{policyName}が一部のエージェントですでに使用されていることをFleetが検出しました。このアクションの結果として、Fleetはこのポリシーで使用されているすべてのエージェントに更新をデプロイします。", + "xpack.fleet.agentPolicy.confirmModalCancelButtonLabel": "キャンセル", + "xpack.fleet.agentPolicy.confirmModalConfirmButtonLabel": "変更を保存してデプロイ", + "xpack.fleet.agentPolicy.confirmModalDescription": "このアクションは元に戻せません。続行していいですか?", + "xpack.fleet.agentPolicy.confirmModalTitle": "変更を保存してデプロイ", + "xpack.fleet.agentPolicy.linkedAgentCountText": "{count, plural, one {#件のエージェント} other {#件のエージェント}}", + "xpack.fleet.agentPolicyActionMenu.buttonText": "アクション", + "xpack.fleet.agentPolicyActionMenu.copyPolicyActionText": "ポリシーをコピー", + "xpack.fleet.agentPolicyActionMenu.enrollAgentActionText": "エージェントの追加", + "xpack.fleet.agentPolicyActionMenu.viewPolicyText": "ポリシーを表示", + "xpack.fleet.agentPolicyForm.advancedOptionsToggleLabel": "高度なオプション", + "xpack.fleet.agentPolicyForm.descriptionFieldLabel": "説明", + "xpack.fleet.agentPolicyForm.descriptionFieldPlaceholder": "どのようにこのポリシーを使用しますか?", + "xpack.fleet.agentPolicyForm.monitoringDescription": "パフォーマンスのデバッグと追跡のために、エージェントに関するデータを収集します。", + "xpack.fleet.agentPolicyForm.monitoringLabel": "アラート監視", + "xpack.fleet.agentPolicyForm.monitoringLogsFieldLabel": "エージェントログを収集", + "xpack.fleet.agentPolicyForm.monitoringLogsTooltipText": "このポリシーを使用するElasticエージェントからログを収集します。", + "xpack.fleet.agentPolicyForm.monitoringMetricsFieldLabel": "エージェントメトリックを収集", + "xpack.fleet.agentPolicyForm.monitoringMetricsTooltipText": "このポリシーを使用するElasticエージェントからメトリックを収集します。", + "xpack.fleet.agentPolicyForm.nameFieldLabel": "名前", + "xpack.fleet.agentPolicyForm.nameFieldPlaceholder": "名前を選択", + "xpack.fleet.agentPolicyForm.nameRequiredErrorMessage": "エージェントポリシー名が必要です。", + "xpack.fleet.agentPolicyForm.namespaceFieldDescription": "このポリシーを使用する統合にデフォルトの名前空間を適用します。統合はその独自の名前空間を指定できます。", + "xpack.fleet.agentPolicyForm.namespaceFieldLabel": "デフォルト名前空間", + "xpack.fleet.agentPolicyForm.systemMonitoringFieldLabel": "システム監視", + "xpack.fleet.agentPolicyForm.systemMonitoringText": "システムメトリックを収集", + "xpack.fleet.agentPolicyForm.systemMonitoringTooltipText": "このオプションを有効にすると、システムメトリックと情報を収集する統合でポリシーをブートストラップできます。", + "xpack.fleet.agentPolicyList.actionsColumnTitle": "アクション", + "xpack.fleet.agentPolicyList.addButton": "エージェントポリシーを作成", + "xpack.fleet.agentPolicyList.agentsColumnTitle": "エージェント", + "xpack.fleet.agentPolicyList.clearFiltersLinkText": "フィルターを消去", + "xpack.fleet.agentPolicyList.descriptionColumnTitle": "説明", + "xpack.fleet.agentPolicyList.loadingAgentPoliciesMessage": "エージェントポリシーの読み込み中...", + "xpack.fleet.agentPolicyList.nameColumnTitle": "名前", + "xpack.fleet.agentPolicyList.noAgentPoliciesPrompt": "エージェントポリシーがありません", + "xpack.fleet.agentPolicyList.noFilteredAgentPoliciesPrompt": "エージェントポリシーが見つかりません。{clearFiltersLink}", + "xpack.fleet.agentPolicyList.packagePoliciesCountColumnTitle": "羹合", + "xpack.fleet.agentPolicyList.pageSubtitle": "エージェントポリシーを使用すると、エージェントとエージェントが収集するデータを管理できます。", + "xpack.fleet.agentPolicyList.pageTitle": "エージェントポリシー", + "xpack.fleet.agentPolicyList.reloadAgentPoliciesButtonText": "再読み込み", + "xpack.fleet.agentPolicyList.revisionNumber": "rev. {revNumber}", + "xpack.fleet.agentPolicyList.updatedOnColumnTitle": "最終更新日", + "xpack.fleet.agentReassignPolicy.cancelButtonLabel": "キャンセル", + "xpack.fleet.agentReassignPolicy.continueButtonLabel": "ポリシーの割り当て", + "xpack.fleet.agentReassignPolicy.flyoutDescription": "選択した{count, plural, one {エージェント} other {エージェント}}を割り当てる新しいエージェントポリシーを選択します。", + "xpack.fleet.agentReassignPolicy.flyoutTitle": "新しいエージェントポリシーを割り当てる", + "xpack.fleet.agentReassignPolicy.policyDescription": "選択したエージェントポリシーは、{count, plural, one {{countValue}個の統合} other {{countValue}個の統合}}のデータを収集します。", + "xpack.fleet.agentReassignPolicy.selectPolicyLabel": "エージェントポリシー", + "xpack.fleet.agentReassignPolicy.successSingleNotificationTitle": "エージェントポリシーが再割り当てされました", + "xpack.fleet.agents.pageSubtitle": "ポリシーの更新を管理し、任意のサイズのエージェントのグループにデプロイします。", + "xpack.fleet.agents.pageTitle": "エージェント", + "xpack.fleet.alphaMessageDescription": "Ingest Managerは本番環境用ではありません。", + "xpack.fleet.alphaMessageLinkText": "詳細を参照してください。", + "xpack.fleet.alphaMessageTitle": "ベータリリース", + "xpack.fleet.alphaMessaging.docsLink": "ドキュメンテーション", + "xpack.fleet.alphaMessaging.feedbackText": "{docsLink}をご覧ください。質問やフィードバックについては、{forumLink}にアクセスしてください。", + "xpack.fleet.alphaMessaging.flyoutTitle": "このリリースについて", + "xpack.fleet.alphaMessaging.forumLink": "ディスカッションフォーラム", + "xpack.fleet.alphaMessaging.introText": "Ingest Managerは開発中であり、本番環境用ではありません。このベータリリースは、ユーザーがIngest Managerと新しいElasticエージェントをテストしてフィードバックを提供することを目的としています。このプラグインには、サポートSLAが適用されません。", + "xpack.fleet.alphaMessging.closeFlyoutLabel": "閉じる", + "xpack.fleet.appNavigation.agentsLinkText": "エージェント", + "xpack.fleet.appNavigation.dataStreamsLinkText": "データストリーム", + "xpack.fleet.appNavigation.epmLinkText": "羹合", + "xpack.fleet.appNavigation.overviewLinkText": "概要", + "xpack.fleet.appNavigation.policiesLinkText": "ポリシー", + "xpack.fleet.appNavigation.sendFeedbackButton": "フィードバックを送信", + "xpack.fleet.appNavigation.settingsButton": "設定", + "xpack.fleet.appTitle": "Fleet", + "xpack.fleet.betaBadge.labelText": "ベータ", + "xpack.fleet.betaBadge.tooltipText": "このプラグインは本番環境用ではありません。バグについてはディスカッションフォーラムで報告してください。", + "xpack.fleet.breadcrumbs.addPackagePolicyPageTitle": "統合の追加", + "xpack.fleet.breadcrumbs.agentsPageTitle": "エージェント", + "xpack.fleet.breadcrumbs.allIntegrationsPageTitle": "すべて", + "xpack.fleet.breadcrumbs.appTitle": "Fleet", + "xpack.fleet.breadcrumbs.datastreamsPageTitle": "データストリーム", + "xpack.fleet.breadcrumbs.editPackagePolicyPageTitle": "統合の編集", + "xpack.fleet.breadcrumbs.enrollmentTokensPageTitle": "登録トークン", + "xpack.fleet.breadcrumbs.installedIntegrationsPageTitle": "インストール済み", + "xpack.fleet.breadcrumbs.integrationsPageTitle": "羹合", + "xpack.fleet.breadcrumbs.overviewPageTitle": "概要", + "xpack.fleet.breadcrumbs.policiesPageTitle": "ポリシー", + "xpack.fleet.copyAgentPolicy.confirmModal.cancelButtonLabel": "キャンセル", + "xpack.fleet.copyAgentPolicy.confirmModal.confirmButtonLabel": "ポリシーをコピー", + "xpack.fleet.copyAgentPolicy.confirmModal.copyPolicyPrompt": "新しいエージェントポリシーの名前と説明を選択してください。", + "xpack.fleet.copyAgentPolicy.confirmModal.copyPolicyTitle": "「{name}」エージェントポリシーをコピー", + "xpack.fleet.copyAgentPolicy.confirmModal.defaultNewPolicyName": "{name}(コピー)", + "xpack.fleet.copyAgentPolicy.confirmModal.newDescriptionLabel": "説明", + "xpack.fleet.copyAgentPolicy.confirmModal.newNameLabel": "新しいポリシー名", + "xpack.fleet.copyAgentPolicy.failureNotificationTitle": "エージェントポリシー「{id}」のコピーエラー", + "xpack.fleet.copyAgentPolicy.fatalErrorNotificationTitle": "エージェントポリシーのコピーエラー", + "xpack.fleet.copyAgentPolicy.successNotificationTitle": "エージェントポリシーがコピーされました", + "xpack.fleet.createAgentPolicy.cancelButtonLabel": "キャンセル", + "xpack.fleet.createAgentPolicy.errorNotificationTitle": "エージェントポリシーを作成できません", + "xpack.fleet.createAgentPolicy.flyoutTitle": "エージェントポリシーを作成", + "xpack.fleet.createAgentPolicy.flyoutTitleDescription": "エージェントポリシーは、エージェントのグループ全体にわたる設定を管理する目的で使用されます。エージェントポリシーに統合を追加すると、エージェントで収集するデータを指定できます。エージェントポリシーの編集時には、フリートを使用して、指定したエージェントのグループに更新をデプロイできます。", + "xpack.fleet.createAgentPolicy.submitButtonLabel": "エージェントポリシーを作成", + "xpack.fleet.createAgentPolicy.successNotificationTitle": "エージェントポリシー「{name}」が作成されました", + "xpack.fleet.createPackagePolicy.addedNotificationMessage": "Fleetは'{agentPolicyName}'ポリシーで使用されているすべてのエージェントに更新をデプロイします。", + "xpack.fleet.createPackagePolicy.addedNotificationTitle": "「{packagePolicyName}」統合が追加されました。", + "xpack.fleet.createPackagePolicy.agentPolicyNameLabel": "エージェントポリシー", + "xpack.fleet.createPackagePolicy.cancelButton": "キャンセル", + "xpack.fleet.createPackagePolicy.cancelLinkText": "キャンセル", + "xpack.fleet.createPackagePolicy.errorOnSaveText": "統合ポリシーにはエラーがあります。保存前に修正してください。", + "xpack.fleet.createPackagePolicy.pageDescriptionfromPackage": "次の手順に従い、この統合をエージェントポリシーに追加します。", + "xpack.fleet.createPackagePolicy.pageDescriptionfromPolicy": "選択したエージェントポリシーの統合を構成します。", + "xpack.fleet.createPackagePolicy.pageTitle": "統合の追加", + "xpack.fleet.createPackagePolicy.pageTitleWithPackageName": "{packageName}統合の追加", + "xpack.fleet.createPackagePolicy.saveButton": "統合の保存", + "xpack.fleet.createPackagePolicy.stepConfigure.advancedOptionsToggleLinkText": "高度なオプション", + "xpack.fleet.createPackagePolicy.stepConfigure.errorCountText": "{count, plural, one {件のエラー} other {件のエラー}}", + "xpack.fleet.createPackagePolicy.stepConfigure.hideStreamsAriaLabel": "{type}入力を非表示", + "xpack.fleet.createPackagePolicy.stepConfigure.inputSettingsDescription": "次の設定は以下のすべての入力に適用されます。", + "xpack.fleet.createPackagePolicy.stepConfigure.inputSettingsTitle": "設定", + "xpack.fleet.createPackagePolicy.stepConfigure.inputVarFieldOptionalLabel": "オプション", + "xpack.fleet.createPackagePolicy.stepConfigure.integrationSettingsSectionDescription": "この統合の使用方法を識別できるように、名前と説明を選択してください。", + "xpack.fleet.createPackagePolicy.stepConfigure.integrationSettingsSectionTitle": "統合設定", + "xpack.fleet.createPackagePolicy.stepConfigure.noPolicyOptionsMessage": "構成するものがありません", + "xpack.fleet.createPackagePolicy.stepConfigure.packagePolicyDescriptionInputLabel": "説明", + "xpack.fleet.createPackagePolicy.stepConfigure.packagePolicyNameInputLabel": "統合名", + "xpack.fleet.createPackagePolicy.stepConfigure.packagePolicyNamespaceInputLabel": "名前空間", + "xpack.fleet.createPackagePolicy.stepConfigure.showStreamsAriaLabel": "{type}入力を表示", + "xpack.fleet.createPackagePolicy.stepConfigure.toggleAdvancedOptionsButtonText": "高度なオプション", + "xpack.fleet.createPackagePolicy.stepConfigurePackagePolicyTitle": "統合の構成", + "xpack.fleet.createPackagePolicy.stepSelectAgentPolicyTitle": "エージェントポリシーを選択", + "xpack.fleet.createPackagePolicy.stepSelectPackage.errorLoadingPackagesTitle": "統合の読み込みエラー", + "xpack.fleet.createPackagePolicy.stepSelectPackage.errorLoadingPolicyTitle": "エージェントポリシー情報の読み込みエラー", + "xpack.fleet.createPackagePolicy.stepSelectPackage.errorLoadingSelectedPackageTitle": "選択した統合の読み込みエラー", + "xpack.fleet.createPackagePolicy.stepSelectPackage.filterPackagesInputPlaceholder": "統合を検索", + "xpack.fleet.createPackagePolicy.stepSelectPackageTitle": "統合を選択", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.addButton": "エージェントポリシーを作成", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.agentPolicyAgentsCountText": "{count, plural, one {#個のエージェント} other {#個のエージェント}}が登録されました", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.agentPolicyAgentsDescriptionText": "選択したエージェントポリシーで{count, plural, one {#個のエージェント} other {#個のエージェント}}が登録されました。", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.agentPolicyLabel": "エージェントポリシー", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.agentPolicyPlaceholderText": "この統合を追加するエージェントポリシーを選択", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingAgentPoliciesTitle": "エージェントポリシーの読み込みエラー", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingPackageTitle": "パッケージ情報の読み込みエラー", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingSelectedAgentPolicyTitle": "選択したエージェントポリシーの読み込みエラー", + "xpack.fleet.dataStreamList.actionsColumnTitle": "アクション", + "xpack.fleet.dataStreamList.datasetColumnTitle": "データセット", + "xpack.fleet.dataStreamList.integrationColumnTitle": "羹合", + "xpack.fleet.dataStreamList.lastActivityColumnTitle": "前回のアクティビティ", + "xpack.fleet.dataStreamList.loadingDataStreamsMessage": "データストリームを読み込んでいます...", + "xpack.fleet.dataStreamList.namespaceColumnTitle": "名前空間", + "xpack.fleet.dataStreamList.noDataStreamsPrompt": "データストリームがありません", + "xpack.fleet.dataStreamList.noFilteredDataStreamsMessage": "一致するデータストリームが見つかりません", + "xpack.fleet.dataStreamList.pageSubtitle": "エージェントが作成したデータを管理します。", + "xpack.fleet.dataStreamList.pageTitle": "データストリーム", + "xpack.fleet.dataStreamList.reloadDataStreamsButtonText": "再読み込み", + "xpack.fleet.dataStreamList.searchPlaceholderTitle": "データストリームをフィルター", + "xpack.fleet.dataStreamList.sizeColumnTitle": "サイズ", + "xpack.fleet.dataStreamList.typeColumnTitle": "タイプ", + "xpack.fleet.dataStreamList.viewDashboardActionText": "ダッシュボードを表示", + "xpack.fleet.dataStreamList.viewDashboardsActionText": "ダッシュボードを表示", + "xpack.fleet.dataStreamList.viewDashboardsPanelTitle": "ダッシュボードを表示", + "xpack.fleet.defaultSearchPlaceholderText": "検索", + "xpack.fleet.deleteAgentPolicy.confirmModal.affectedAgentsMessage": "{agentsCount, plural, one {#個のエージェントは} other {#個のエージェントは}}このエージェントポリシーに割り当てられました。このポリシーを削除する前に、これらのエージェントの割り当てを解除します。", + "xpack.fleet.deleteAgentPolicy.confirmModal.affectedAgentsTitle": "使用中のポリシー", + "xpack.fleet.deleteAgentPolicy.confirmModal.cancelButtonLabel": "キャンセル", + "xpack.fleet.deleteAgentPolicy.confirmModal.confirmButtonLabel": "ポリシーを削除", + "xpack.fleet.deleteAgentPolicy.confirmModal.deletePolicyTitle": "このエージェントポリシーを削除しますか?", + "xpack.fleet.deleteAgentPolicy.confirmModal.irreversibleMessage": "この操作は元に戻すことができません。", + "xpack.fleet.deleteAgentPolicy.confirmModal.loadingAgentsCountMessage": "影響があるエージェントの数を確認中...", + "xpack.fleet.deleteAgentPolicy.confirmModal.loadingButtonLabel": "読み螟み中...", + "xpack.fleet.deleteAgentPolicy.failureSingleNotificationTitle": "エージェントポリシー「{id}」の削除エラー", + "xpack.fleet.deleteAgentPolicy.fatalErrorNotificationTitle": "エージェントポリシーの削除エラー", + "xpack.fleet.deleteAgentPolicy.successSingleNotificationTitle": "エージェントポリシー「{id}」が削除されました", + "xpack.fleet.deletePackagePolicy.confirmModal.affectedAgentsMessage": "{agentPolicyName}が一部のエージェントですでに使用されていることをFleetが検出しました。", + "xpack.fleet.deletePackagePolicy.confirmModal.affectedAgentsTitle": "このアクションは {agentsCount} {agentsCount, plural, one {# エージェント} other {# エージェント}}に影響します", + "xpack.fleet.deletePackagePolicy.confirmModal.cancelButtonLabel": "キャンセル", + "xpack.fleet.deletePackagePolicy.confirmModal.deleteMultipleTitle": "{count, plural, one {個の統合} other {個の統合}}を削除しますか?", + "xpack.fleet.deletePackagePolicy.confirmModal.generalMessage": "このアクションは元に戻せません。続行していいですか?", + "xpack.fleet.deletePackagePolicy.confirmModal.loadingAgentsCountMessage": "影響があるエージェントを確認中...", + "xpack.fleet.deletePackagePolicy.confirmModal.loadingButtonLabel": "読み螟み中...", + "xpack.fleet.deletePackagePolicy.failureMultipleNotificationTitle": "{count}個の統合の削除エラー", + "xpack.fleet.deletePackagePolicy.failureSingleNotificationTitle": "統合「{id}」の削除エラー", + "xpack.fleet.deletePackagePolicy.fatalErrorNotificationTitle": "統合の削除エラー", + "xpack.fleet.deletePackagePolicy.successMultipleNotificationTitle": "{count}個の統合を削除しました", + "xpack.fleet.deletePackagePolicy.successSingleNotificationTitle": "統合「{id}」を削除しました", + "xpack.fleet.disabledSecurityDescription": "Elastic Fleet を使用するには、Kibana と Elasticsearch でセキュリティを有効にする必要があります。", + "xpack.fleet.disabledSecurityTitle": "セキュリティが有効ではありません", + "xpack.fleet.editAgentPolicy.cancelButtonText": "キャンセル", + "xpack.fleet.editAgentPolicy.errorNotificationTitle": "エージェントポリシーを更新できません", + "xpack.fleet.editAgentPolicy.saveButtonText": "変更を保存", + "xpack.fleet.editAgentPolicy.savingButtonText": "保存中…", + "xpack.fleet.editAgentPolicy.successNotificationTitle": "正常に「{name}」設定を更新しました", + "xpack.fleet.editAgentPolicy.unsavedChangesText": "保存されていない変更があります", + "xpack.fleet.editPackagePolicy.cancelButton": "キャンセル", + "xpack.fleet.editPackagePolicy.errorLoadingDataMessage": "この統合情報の読み込みエラーが発生しました", + "xpack.fleet.editPackagePolicy.errorLoadingDataTitle": "データの読み込み中にエラーが発生", + "xpack.fleet.editPackagePolicy.failedConflictNotificationMessage": "データが最新ではありません。最新のポリシーを取得するには、ページを更新してください。", + "xpack.fleet.editPackagePolicy.failedNotificationTitle": "「{packagePolicyName}」の更新エラー", + "xpack.fleet.editPackagePolicy.pageDescription": "統合設定を修正し、選択したエージェントポリシーに変更をデプロイします。", + "xpack.fleet.editPackagePolicy.pageTitle": "統合の編集", + "xpack.fleet.editPackagePolicy.pageTitleWithPackageName": "{packageName}統合の編集", + "xpack.fleet.editPackagePolicy.saveButton": "統合の保存", + "xpack.fleet.editPackagePolicy.updatedNotificationMessage": "Fleetは'{agentPolicyName}'ポリシーで使用されているすべてのエージェントに更新をデプロイします", + "xpack.fleet.editPackagePolicy.updatedNotificationTitle": "正常に「{packagePolicyName}」を更新しました", + "xpack.fleet.enrollemntAPIKeyList.emptyMessage": "登録トークンが見つかりません。", + "xpack.fleet.enrollemntAPIKeyList.loadingTokensMessage": "登録トークンを読み込んでいます...", + "xpack.fleet.enrollmentInstructions.descriptionText": "エージェントのディレクトリから、該当するコマンドを実行し、Elasticエージェントをインストール、登録、起動します。これらのコマンドを再利用すると、複数のホストでエージェントを設定できます。管理者権限が必要です。", + "xpack.fleet.enrollmentInstructions.linuxMacOSTitle": "Linux、MacOS", + "xpack.fleet.enrollmentInstructions.moreInstructionsLink": "Elasticエージェントドキュメント", + "xpack.fleet.enrollmentInstructions.moreInstructionsText": "手順とオプションの詳細については、{link}を参照してください。", + "xpack.fleet.enrollmentInstructions.windowsTitle": "Windows", + "xpack.fleet.enrollmentStepAgentPolicy.enrollmentTokenSelectLabel": "登録トークン", + "xpack.fleet.enrollmentStepAgentPolicy.policySelectAriaLabel": "エージェントポリシー", + "xpack.fleet.enrollmentStepAgentPolicy.policySelectLabel": "エージェントポリシー", + "xpack.fleet.enrollmentStepAgentPolicy.showAuthenticationSettingsButton": "認証設定", + "xpack.fleet.enrollmentTokenDeleteModal.cancelButton": "キャンセル", + "xpack.fleet.enrollmentTokenDeleteModal.deleteButton": "登録トークンを取り消し", + "xpack.fleet.enrollmentTokenDeleteModal.description": "{keyName}を取り消してよろしいですか?このトークンを使用するエージェントは、ポリシーにアクセスしたり、データを送信したりできなくなります。 ", + "xpack.fleet.enrollmentTokenDeleteModal.title": "登録トークンを取り消し", + "xpack.fleet.enrollmentTokensList.actionsTitle": "アクション", + "xpack.fleet.enrollmentTokensList.activeTitle": "アクティブ", + "xpack.fleet.enrollmentTokensList.createdAtTitle": "作成日時", + "xpack.fleet.enrollmentTokensList.hideTokenButtonLabel": "トークンを非表示", + "xpack.fleet.enrollmentTokensList.nameTitle": "名前", + "xpack.fleet.enrollmentTokensList.newKeyButton": "登録トークンを作成", + "xpack.fleet.enrollmentTokensList.pageDescription": "登録トークンを作成して取り消します。登録トークンを使用すると、1つ以上のエージェントをFleetに登録し、データを送信できます。", + "xpack.fleet.enrollmentTokensList.policyTitle": "エージェントポリシー", + "xpack.fleet.enrollmentTokensList.revokeTokenButtonLabel": "トークンを取り消す", + "xpack.fleet.enrollmentTokensList.secretTitle": "シークレット", + "xpack.fleet.enrollmentTokensList.showTokenButtonLabel": "トークンを表示", + "xpack.fleet.epm.addPackagePolicyButtonText": "{packageName}の追加", + "xpack.fleet.epm.assetGroupTitle": "{assetType}アセット", + "xpack.fleet.epm.browseAllButtonText": "すべての統合を参照", + "xpack.fleet.epm.illustrationAltText": "統合の例", + "xpack.fleet.epm.loadingIntegrationErrorTitle": "統合詳細の読み込みエラー", + "xpack.fleet.epm.packageDetailsNav.overviewLinkText": "概要", + "xpack.fleet.epm.packageDetailsNav.packagePoliciesLinkText": "使用", + "xpack.fleet.epm.packageDetailsNav.settingsLinkText": "設定", + "xpack.fleet.epm.pageSubtitle": "一般的なアプリやサービスの統合を参照する", + "xpack.fleet.epm.pageTitle": "羹合", + "xpack.fleet.epm.releaseBadge.betaDescription": "この統合は本番環境用ではありません。", + "xpack.fleet.epm.releaseBadge.betaLabel": "ベータ", + "xpack.fleet.epm.releaseBadge.experimentalDescription": "この統合は、急に変更されたり、将来のリリースで削除されたりする可能性があります。", + "xpack.fleet.epm.releaseBadge.experimentalLabel": "実験的", + "xpack.fleet.epm.screenshotsTitle": "スクリーンショット", + "xpack.fleet.epm.updateAvailableTooltip": "更新が利用可能です", + "xpack.fleet.epm.versionLabel": "バージョン", + "xpack.fleet.epmList.allFilterLinkText": "すべて", + "xpack.fleet.epmList.allPackagesFilterLinkText": "すべて", + "xpack.fleet.epmList.allTabText": "すべての統合", + "xpack.fleet.epmList.allTitle": "カテゴリで参照", + "xpack.fleet.epmList.installedTabText": "インストールされている統合", + "xpack.fleet.epmList.installedTitle": "インストールされている統合", + "xpack.fleet.epmList.noPackagesFoundPlaceholder": "パッケージが見つかりません", + "xpack.fleet.epmList.searchPackagesPlaceholder": "統合を検索", + "xpack.fleet.epmList.updatesAvailableFilterLinkText": "更新が可能です", + "xpack.fleet.featureCatalogueDescription": "Elasticエージェントと統合のFleetを追加して管理します。", + "xpack.fleet.featureCatalogueTitle": "Elasticエージェントの追加", + "xpack.fleet.genericActionsMenuText": "開く", + "xpack.fleet.homeIntegration.tutorialDirectory.dismissNoticeButtonText": "メッセージを消去", + "xpack.fleet.homeIntegration.tutorialDirectory.noticeText": "Elasticエージェントでは、シンプルかつ統合された方法で、ログ、メトリック、他の種類のデータの監視をホストに追加することができます。複数のBeatsと他のエージェントをインストールする必要はありません。このため、インフラストラクチャ全体でのポリシーのデプロイが簡単で高速になりました。詳細については、{blogPostLink}をお読みください。", + "xpack.fleet.homeIntegration.tutorialDirectory.noticeText.blogPostLink": "発表ブログ投稿", + "xpack.fleet.homeIntegration.tutorialDirectory.noticeTitle": "{newPrefix} ElasticエージェントおよびIngest Managerベータ", + "xpack.fleet.homeIntegration.tutorialDirectory.noticeTitle.newPrefix": "新規:", + "xpack.fleet.homeIntegration.tutorialModule.noticeText": "{notePrefix}このモジュールの新しいバージョンは、Ingest Managerベータの{availableAsIntegrationLink}です。エージェントポリシーと新しいElasticエージェントの詳細については、{blogPostLink}をお読みください。", + "xpack.fleet.homeIntegration.tutorialModule.noticeText.blogPostLink": "発表ブログ投稿", + "xpack.fleet.homeIntegration.tutorialModule.noticeText.integrationLink": "統合として利用可能", + "xpack.fleet.homeIntegration.tutorialModule.noticeText.notePrefix": "注:", + "xpack.fleet.initializationErrorMessageTitle": "Ingest Manager を初期化できません", + "xpack.fleet.integrations.installPackage.installingPackageButtonLabel": "{title}アセットをインストールしています", + "xpack.fleet.integrations.installPackage.installPackageButtonLabel": "{title}アセットをインストール", + "xpack.fleet.integrations.packageInstallErrorDescription": "このパッケージのインストール中に問題が発生しました。しばらくたってから再試行してください。", + "xpack.fleet.integrations.packageInstallErrorTitle": "{title}パッケージをインストールできませんでした", + "xpack.fleet.integrations.packageInstallSuccessDescription": "正常き{title}をインストールしました", + "xpack.fleet.integrations.packageInstallSuccessTitle": "{title}をインストールしました", + "xpack.fleet.integrations.packageUninstallErrorDescription": "このパッケージのアンインストール中に問題が発生しました。しばらくたってから再試行してください。", + "xpack.fleet.integrations.packageUninstallErrorTitle": "{title}パッケージをアンインストールできませんでした", + "xpack.fleet.integrations.packageUninstallSuccessDescription": "正常き{title}をアンインストールしました", + "xpack.fleet.integrations.packageUninstallSuccessTitle": "{title}をアンインストールしました", + "xpack.fleet.integrations.settings.confirmInstallModal.cancelButtonLabel": "キャンセル", + "xpack.fleet.integrations.settings.confirmInstallModal.installButtonLabel": "{packageName}をインストール", + "xpack.fleet.integrations.settings.confirmInstallModal.installCalloutTitle": "{numOfAssets}個のアセットがインストールされます", + "xpack.fleet.integrations.settings.confirmInstallModal.installDescription": "Kibanaアセットは現在のスペース(既定)にインストールされ、このスペースを表示する権限があるユーザーのみがアクセスできます。Elasticsearchアセットはグローバルでインストールされ、すべてのKibanaユーザーがアクセスできます。", + "xpack.fleet.integrations.settings.confirmInstallModal.installTitle": "{packageName}をインストール", + "xpack.fleet.integrations.settings.confirmUninstallModal.cancelButtonLabel": "キャンセル", + "xpack.fleet.integrations.settings.confirmUninstallModal.uninstallButtonLabel": "{packageName}をアンインストール", + "xpack.fleet.integrations.settings.confirmUninstallModal.uninstallCallout.description": "この統合によって作成されたKibanaおよびElasticsearchアセットは削除されます。エージェントポリシーとエージェントによって送信されたデータは影響を受けません。", + "xpack.fleet.integrations.settings.confirmUninstallModal.uninstallCallout.title": "{numOfAssets}個のアセットが削除されます", + "xpack.fleet.integrations.settings.confirmUninstallModal.uninstallDescription": "この操作は元に戻すことができません。続行していいですか?", + "xpack.fleet.integrations.settings.confirmUninstallModal.uninstallTitle": "{packageName}をアンインストール", + "xpack.fleet.integrations.settings.packageInstallDescription": "この統合をインストールして、{title}データ向けに設計されたKibanaおよびElasticsearchアセットをセットアップします。", + "xpack.fleet.integrations.settings.packageInstallTitle": "{title}をインストール", + "xpack.fleet.integrations.settings.packageSettingsTitle": "設定", + "xpack.fleet.integrations.settings.packageUninstallDescription": "この統合によってインストールされたKibanaおよびElasticsearchアセットを削除します。", + "xpack.fleet.integrations.settings.packageUninstallNoteDescription.packageUninstallNoteDetail": "{strongNote} {title}をアンインストールできません。この統合を使用しているアクティブなエージェントがあります。アンインストールするには、エージェントポリシーからすべての{title}統合を削除します。", + "xpack.fleet.integrations.settings.packageUninstallNoteDescription.packageUninstallNoteLabel": "注:", + "xpack.fleet.integrations.settings.packageUninstallNoteDescription.packageUninstallUninstallableNoteDetail": "{strongNote} {title}統合は既定でインストールされているため、削除できません。", + "xpack.fleet.integrations.settings.packageUninstallTitle": "{title}をアンインストール", + "xpack.fleet.integrations.settings.packageVersionTitle": "{title}バージョン", + "xpack.fleet.integrations.settings.versionInfo.installedVersion": "インストールされているバージョン", + "xpack.fleet.integrations.settings.versionInfo.latestVersion": "最新バージョン", + "xpack.fleet.integrations.settings.versionInfo.updatesAvailable": "更新が利用可能です", + "xpack.fleet.integrations.uninstallPackage.uninstallingPackageButtonLabel": "{title}をアンインストールしています", + "xpack.fleet.integrations.uninstallPackage.uninstallPackageButtonLabel": "{title}をアンインストール", + "xpack.fleet.integrations.updatePackage.updatePackageButtonLabel": "最新バージョンに更新", + "xpack.fleet.invalidLicenseDescription": "現在のライセンスは期限切れです。登録されたビートエージェントは引き続き動作しますが、Elastic Fleet インターフェースにアクセスするには有効なライセンスが必要です。", + "xpack.fleet.invalidLicenseTitle": "ライセンスの期限切れ", + "xpack.fleet.listTabs.agentTitle": "エージェント", + "xpack.fleet.listTabs.enrollmentTokensTitle": "登録トークン", + "xpack.fleet.metadataForm.addButton": "+ メタデータを追加", + "xpack.fleet.metadataForm.keyLabel": "キー", + "xpack.fleet.metadataForm.submitButtonText": "追加", + "xpack.fleet.metadataForm.valueLabel": "値", + "xpack.fleet.namespaceValidation.invalidCharactersErrorMessage": "名前空間に無効な文字が含まれています", + "xpack.fleet.namespaceValidation.lowercaseErrorMessage": "名前空間は小文字で指定する必要があります", + "xpack.fleet.namespaceValidation.requiredErrorMessage": "名前空間は必須です", + "xpack.fleet.namespaceValidation.tooLongErrorMessage": "名前空間は100バイト以下でなければなりません", + "xpack.fleet.newEnrollmentKey.cancelButtonLabel": "キャンセル", + "xpack.fleet.newEnrollmentKey.flyoutTitle": "登録トークンを作成", + "xpack.fleet.newEnrollmentKey.keyCreatedToasts": "登録トークンが作成されました。", + "xpack.fleet.newEnrollmentKey.nameLabel": "名前", + "xpack.fleet.newEnrollmentKey.policyLabel": "ポリシー", + "xpack.fleet.newEnrollmentKey.submitButton": "登録トークンを作成", + "xpack.fleet.noAccess.accessDeniedDescription": "Elastic Fleet にアクセスする権限がありません。Elastic Fleet を使用するには、このアプリケーションの読み取り権または全権を含むユーザーロールが必要です。", + "xpack.fleet.noAccess.accessDeniedTitle": "アクセスが拒否されました", + "xpack.fleet.overviewAgentActiveTitle": "アクティブ", + "xpack.fleet.overviewAgentErrorTitle": "エラー", + "xpack.fleet.overviewAgentOfflineTitle": "オフライン", + "xpack.fleet.overviewAgentTotalTitle": "合計エージェント数", + "xpack.fleet.overviewDatastreamNamespacesTitle": "名前空間", + "xpack.fleet.overviewDatastreamSizeTitle": "合計サイズ", + "xpack.fleet.overviewDatastreamTotalTitle": "データストリーム", + "xpack.fleet.overviewIntegrationsInstalledTitle": "インストール済み", + "xpack.fleet.overviewIntegrationsTotalTitle": "合計利用可能数", + "xpack.fleet.overviewIntegrationsUpdatesAvailableTitle": "更新が可能です", + "xpack.fleet.overviewPackagePolicyTitle": "使用済みの統合", + "xpack.fleet.overviewPageAgentsPanelTitle": "エージェント", + "xpack.fleet.overviewPageDataStreamsPanelAction": "データストリームを表示", + "xpack.fleet.overviewPageDataStreamsPanelTitle": "データストリーム", + "xpack.fleet.overviewPageDataStreamsPanelTooltip": "エージェントが収集するデータはさまざまなデータストリームに整理されます。", + "xpack.fleet.overviewPageEnrollAgentButton": "エージェントの追加", + "xpack.fleet.overviewPageFleetPanelAction": "エージェントを表示", + "xpack.fleet.overviewPageFleetPanelTooltip": "Fleetを使用して、中央の場所からエージェントを登録し、ポリシーを管理します。", + "xpack.fleet.overviewPageIntegrationsPanelAction": "統合を表示", + "xpack.fleet.overviewPageIntegrationsPanelTitle": "羹合", + "xpack.fleet.overviewPageIntegrationsPanelTooltip": "Elastic Stackの統合を参照し、インストールします。統合をエージェントポリシーに追加し、データの送信を開始します。", + "xpack.fleet.overviewPagePoliciesPanelAction": "ポリシーを表示", + "xpack.fleet.overviewPagePoliciesPanelTitle": "エージェントポリシー", + "xpack.fleet.overviewPagePoliciesPanelTooltip": "エージェントポリシーを使用すると、エージェントが収集するデータを管理できます。", + "xpack.fleet.overviewPageSubtitle": "Elasticエージェントとポリシーを中央の場所で管理します。", + "xpack.fleet.overviewPageTitle": "Fleet", + "xpack.fleet.overviewPolicyTotalTitle": "合計利用可能数", + "xpack.fleet.packagePolicyValidation.invalidArrayErrorMessage": "無効なフォーマット", + "xpack.fleet.packagePolicyValidation.invalidYamlFormatErrorMessage": "YAML形式が無効です", + "xpack.fleet.packagePolicyValidation.nameRequiredErrorMessage": "名前が必要です", + "xpack.fleet.packagePolicyValidation.requiredErrorMessage": "{fieldName}が必要です", + "xpack.fleet.permissionDeniedErrorMessage": "Ingest Managerにアクセスする権限がありません。Ingest Managerきは{roleName}権限が必要です。", + "xpack.fleet.permissionDeniedErrorTitle": "パーミッションが拒否されました", + "xpack.fleet.permissionsRequestErrorMessageDescription": "Ingest Managerアクセス権の確認中に問題が発生しました", + "xpack.fleet.permissionsRequestErrorMessageTitle": "アクセス権を確認できません", + "xpack.fleet.policyDetails.addPackagePolicyButtonText": "統合の追加", + "xpack.fleet.policyDetails.ErrorGettingFullAgentPolicy": "エージェントポリシーの読み込みエラー", + "xpack.fleet.policyDetails.packagePoliciesTable.actionsColumnTitle": "アクション", + "xpack.fleet.policyDetails.packagePoliciesTable.deleteActionTitle": "統合の削除", + "xpack.fleet.policyDetails.packagePoliciesTable.descriptionColumnTitle": "説明", + "xpack.fleet.policyDetails.packagePoliciesTable.editActionTitle": "統合の編集", + "xpack.fleet.policyDetails.packagePoliciesTable.nameColumnTitle": "名前", + "xpack.fleet.policyDetails.packagePoliciesTable.namespaceColumnTitle": "名前空間", + "xpack.fleet.policyDetails.packagePoliciesTable.packageNameColumnTitle": "羹合", + "xpack.fleet.policyDetails.policyDetailsTitle": "ポリシー「{id}」", + "xpack.fleet.policyDetails.policyNotFoundErrorTitle": "ポリシー「{id}」が見つかりません", + "xpack.fleet.policyDetails.subTabs.packagePoliciesTabText": "羹合", + "xpack.fleet.policyDetails.subTabs.settingsTabText": "設定", + "xpack.fleet.policyDetails.summary.integrations": "羹合", + "xpack.fleet.policyDetails.summary.lastUpdated": "最終更新日", + "xpack.fleet.policyDetails.summary.revision": "リビジョン", + "xpack.fleet.policyDetails.summary.usedBy": "使用者", + "xpack.fleet.policyDetails.unexceptedErrorTitle": "エージェントポリシーの読み込み中にエラーが発生しました", + "xpack.fleet.policyDetails.viewAgentListTitle": "すべてのエージェントポリシーを表示", + "xpack.fleet.policyDetails.yamlDownloadButtonLabel": "ダウンロードポリシー", + "xpack.fleet.policyDetails.yamlFlyoutCloseButtonLabel": "閉じる", + "xpack.fleet.policyDetails.yamlflyoutTitleWithName": "「{name}」エージェントポリシー", + "xpack.fleet.policyDetails.yamlflyoutTitleWithoutName": "エージェントポリシー", + "xpack.fleet.policyDetailsPackagePolicies.createFirstButtonText": "統合の追加", + "xpack.fleet.policyDetailsPackagePolicies.createFirstMessage": "このポリシーにはまだ統合がありません。", + "xpack.fleet.policyDetailsPackagePolicies.createFirstTitle": "最初の統合を追加", + "xpack.fleet.policyForm.deletePolicyActionText": "ポリシーを削除", + "xpack.fleet.policyForm.deletePolicyGroupDescription": "既存のデータは削除されません。", + "xpack.fleet.policyForm.deletePolicyGroupTitle": "ポリシーを削除", + "xpack.fleet.policyForm.generalSettingsGroupDescription": "エージェントポリシーの名前と説明を選択してください。", + "xpack.fleet.policyForm.generalSettingsGroupTitle": "一般設定", + "xpack.fleet.policyForm.unableToDeleteDefaultPolicyText": "デフォルトポリシーは削除できません", + "xpack.fleet.securityRequiredErrorMessage": "Ingest Managerを使用するには、KibanaとElasticsearchでセキュリティを有効にする必要があります。", + "xpack.fleet.securityRequiredErrorTitle": "セキュリティが有効ではありません", + "xpack.fleet.settings.additionalYamlConfig": "Elasticsearch出力構成", + "xpack.fleet.settings.autoUpgradeDisabledLabel": "エージェントバイナリバージョンを手動で管理します。サブスクリプションが必要です。", + "xpack.fleet.settings.autoUpgradeEnabledLabel": "エージェントバイナリを自動的に更新し、最新マイナーバージョンを使用します。", + "xpack.fleet.settings.autoUpgradeFieldLabel": "Elasticエージェントバイナリバージョン", + "xpack.fleet.settings.cancelButtonLabel": "キャンセル", + "xpack.fleet.settings.elasticHostError": "無効なURL", + "xpack.fleet.settings.elasticsearchUrlLabel": "Elasticsearch URL", + "xpack.fleet.settings.flyoutTitle": "Ingest Manager設定", + "xpack.fleet.settings.globalOutputDescription": "データを送信する場所を指定します。これらの設定はすべてのElasticエージェントポリシーに適用されます。", + "xpack.fleet.settings.globalOutputTitle": "グローバル出力", + "xpack.fleet.settings.integrationUpgradeDisabledFieldLabel": "統合バージョンを手動で管理します。", + "xpack.fleet.settings.integrationUpgradeEnabledFieldLabel": "自動的に統合を最新バージョンに更新し、最新のアセットを取得します。新機能を使用するには、エージェントポリシーを更新しなければならない場合があります。", + "xpack.fleet.settings.integrationUpgradeFieldLabel": "統合バージョン", + "xpack.fleet.settings.invalidYamlFormatErrorMessage": "無効なYAML形式:{reason}", + "xpack.fleet.settings.kibanaUrlDifferentPathOrProtocolError": "各URLのプロトコルとパスは同じでなければなりません", + "xpack.fleet.settings.kibanaUrlEmptyError": "1つ以上のURLが必要です。", + "xpack.fleet.settings.kibanaUrlError": "無効なURL", + "xpack.fleet.settings.kibanaUrlLabel": "Kibana URL", + "xpack.fleet.settings.saveButtonLabel": "設定を保存", + "xpack.fleet.settings.success.message": "設定が保存されました", + "xpack.fleet.setupPage.apiKeyServiceLink": "APIキーサービス", + "xpack.fleet.setupPage.elasticsearchApiKeyFlagText": "{apiKeyLink}.{apiKeyFlag}を{true}に設定します。", + "xpack.fleet.setupPage.elasticsearchSecurityFlagText": "{esSecurityLink}.{securityFlag}を{true}に設定します。", + "xpack.fleet.setupPage.elasticsearchSecurityLink": "Elasticsearchセキュリティ", + "xpack.fleet.setupPage.enableCentralManagement": "ユーザーを作成し、集中管理を有効にする", + "xpack.fleet.setupPage.enableText": "集中管理には、APIキーを作成し、log-*とmetrics-*に書き込むことができるElasticユーザーが必要です。", + "xpack.fleet.setupPage.enableTitle": "ElasticElasticエージェントの集中管理を有効にする", + "xpack.fleet.setupPage.encryptionKeyFlagText": "{encryptionKeyLink}.{keyFlag}を32文字以上の英数字に設定します。", + "xpack.fleet.setupPage.gettingStartedLink": "はじめに", + "xpack.fleet.setupPage.gettingStartedText": "詳細については、{link}ガイドをお読みください。", + "xpack.fleet.setupPage.kibanaEncryptionLink": "Kibana暗号化鍵", + "xpack.fleet.setupPage.kibanaSecurityLink": "Kibanaセキュリティ", + "xpack.fleet.setupPage.missingRequirementsCalloutDescription": "Elasticエージェントの集中管理を使用するには、次のElasticsearchとKibanaセキュリティ機能を有効にする必要があります。", + "xpack.fleet.setupPage.missingRequirementsCalloutTitle": "不足しているセキュリティ要件", + "xpack.fleet.setupPage.missingRequirementsElasticsearchTitle": "Elasticsearchポリシーでは、次のことができます。", + "xpack.fleet.setupPage.missingRequirementsKibanaTitle": "Kibanaポリシーでは、次のことができます。", + "xpack.fleet.setupPage.tlsFlagText": "{kibanaSecurityLink}.{securityFlag}を{true}に設定します。開発目的では、危険な代替として{tlsFlag}を{true}に設定して、{tlsLink}を無効化できます。", + "xpack.fleet.setupPage.tlsLink": "TLS", + "xpack.fleet.unenrollAgents.cancelButtonLabel": "キャンセル", + "xpack.fleet.unenrollAgents.confirmMultipleButtonLabel": "{count}個のエージェントを登録解除", + "xpack.fleet.unenrollAgents.confirmSingleButtonLabel": "エージェントの登録解除", + "xpack.fleet.unenrollAgents.deleteMultipleDescription": "このアクションにより、複数のエージェントがFleetから削除され、新しいデータを取り込めなくなります。これらのエージェントによってすでに送信されたデータは一切影響を受けません。この操作は元に戻すことができません。", + "xpack.fleet.unenrollAgents.deleteSingleDescription": "このアクションにより、「{hostName}」で実行中の選択したエージェントがFleetから削除されます。エージェントによってすでに送信されたデータは一切削除されません。この操作は元に戻すことができません。", + "xpack.fleet.unenrollAgents.deleteSingleTitle": "エージェントの登録解除", + "xpack.fleet.unenrollAgents.fatalErrorNotificationTitle": "{count, plural, one {エージェント} other {エージェント}}の登録解除エラー", + "xpack.fleet.unenrollAgents.forceDeleteMultipleTitle": "{count}個のエージェントを登録解除", + "xpack.fleet.unenrollAgents.forceUnenrollCheckboxLabel": "{count, plural, one {エージェント} other {エージェント}}がただちに削除されました。エージェントが最後のデータを送信するまで待機しない。", + "xpack.fleet.unenrollAgents.forceUnenrollLegendText": "{count, plural, one {エージェント} other {エージェント}}を強制的に登録解除", + "xpack.fleet.unenrollAgents.successForceMultiNotificationTitle": "エージェントが登録解除されました", + "xpack.fleet.unenrollAgents.successForceSingleNotificationTitle": "エージェントが登録解除されました", + "xpack.fleet.unenrollAgents.successMultiNotificationTitle": "エージェントを登録解除しています", + "xpack.fleet.unenrollAgents.successSingleNotificationTitle": "エージェントを登録解除しています", + "xpack.fleet.upgradeAgents.cancelButtonLabel": "キャンセル", + "xpack.fleet.upgradeAgents.confirmMultipleButtonLabel": "{count}個のエージェントをアップグレード", + "xpack.fleet.upgradeAgents.confirmSingleButtonLabel": "エージェントをアップグレード", + "xpack.fleet.upgradeAgents.deleteMultipleTitle": "{count}個のエージェントをアップグレード", + "xpack.fleet.upgradeAgents.deleteSingleTitle": "エージェントをアップグレード", + "xpack.fleet.upgradeAgents.fatalErrorNotificationTitle": "{count, plural, one {エージェント} other {エージェント}}のアップグレードエラー", + "xpack.fleet.upgradeAgents.successMultiNotificationTitle": "エージェントをアップグレード中...", + "xpack.fleet.upgradeAgents.successSingleNotificationTitle": "エージェントをアップグレード中", + "xpack.fleet.upgradeAgents.upgradeMultipleDescription": "このアクションにより、複数のエージェントがバージョン{version}にアップグレードされます。この操作は元に戻すことができません。続行していいですか?", + "xpack.fleet.upgradeAgents.upgradeSingleDescription": "このアクションにより、「{hostName}」で実行中の選択したエージェントがバージョン{version}にアップグレードされます。この操作は元に戻すことができません。続行していいですか?", "xpack.globalSearch.find.invalidLicenseError": "GlobalSearch APIは、ライセンス状態が無効であるため、無効になっています。{errorMessage}", "xpack.globalSearchBar.searchBar.mobileSearchButtonAriaLabel": "サイト検索", "xpack.globalSearchBar.searchBar.noResults": "アプリケーション、ダッシュボード、ビジュアライゼーションなどを検索してみてください。", @@ -8505,7 +9075,6 @@ "xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeIndexExplanationText": "インデックスを読み取り専用にし、メモリー消費量を最小化します。", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeText": "凍結", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel": "レプリカを設定", - "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.allocationFieldLabel": "データティアオプション", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.helpText": "ノード属性に基づいてデータを移動します。", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.input": "カスタム", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.helpText": "コールドティアのノードにデータを移動します。", @@ -8569,7 +9138,6 @@ "xpack.indexLifecycleMgmt.editPolicy.nameLabel": "名前", "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.customOption.description": "ノード属性を使用して、シャード割り当てを制御します。{learnMoreLink}。", "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption": "割り当て構成を修正しない", - "xpack.indexLifecycleMgmt.editPolicy.nodeAllocationLabel": "ノード属性を選択", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesLoadingFailedTitle": "ノード属性を読み込めません", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingLabel": "カスタムノード属性が構成されていません", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesReloadButton": "再試行", @@ -8687,7 +9255,6 @@ "xpack.indexLifecycleMgmt.indexMgmtFilter.managedLabel": "管理中", "xpack.indexLifecycleMgmt.indexMgmtFilter.unmanagedLabel": "管理対象外", "xpack.indexLifecycleMgmt.indexMgmtFilter.warmLabel": "ウォーム", - "xpack.indexLifecycleMgmt.indexPriorityLabel": "インデックスの優先順位", "xpack.indexLifecycleMgmt.learnMore": "その他のリソース", "xpack.indexLifecycleMgmt.licenseCheckErrorMessage": "ライセンス確認失敗", "xpack.indexLifecycleMgmt.nodeAttrDetails.hostField": "ホスト", @@ -9620,578 +10187,6 @@ "xpack.infra.waffle.unableToSelectMetricErrorTitle": "メトリックのオプションまたは値を選択できません", "xpack.infra.waffleTime.autoRefreshButtonLabel": "自動更新", "xpack.infra.waffleTime.stopRefreshingButtonLabel": "更新中止", - "xpack.ingestManager.agentBulkActions.agentsSelected": "{count, plural, one {#個のエージェント} other {#個のエージェント}}が選択されました", - "xpack.ingestManager.agentBulkActions.clearSelection": "選択した項目をクリア", - "xpack.ingestManager.agentBulkActions.reassignPolicy": "新しいポリシーに割り当てる", - "xpack.ingestManager.agentBulkActions.selectAll": "すべてのページのすべての項目を選択", - "xpack.ingestManager.agentBulkActions.totalAgents": "{count, plural, one {#個のエージェント} other {#個のエージェント}}を表示しています", - "xpack.ingestManager.agentBulkActions.totalAgentsWithLimit": "{count}/{total}個のエージェントを表示しています", - "xpack.ingestManager.agentBulkActions.unenrollAgents": "エージェントの登録を解除", - "xpack.ingestManager.agentBulkActions.upgradeAgents": "エージェントをアップグレード", - "xpack.ingestManager.agentDetails.actionsButton": "アクション", - "xpack.ingestManager.agentDetails.agentDetailsTitle": "エージェント'{id}'", - "xpack.ingestManager.agentDetails.agentNotFoundErrorDescription": "エージェントID {agentId}が見つかりません", - "xpack.ingestManager.agentDetails.agentNotFoundErrorTitle": "エージェントが見つかりません", - "xpack.ingestManager.agentDetails.agentPolicyLabel": "エージェントポリシー", - "xpack.ingestManager.agentDetails.agentVersionLabel": "エージェントバージョン", - "xpack.ingestManager.agentDetails.hostIdLabel": "エージェントID", - "xpack.ingestManager.agentDetails.hostNameLabel": "ホスト名", - "xpack.ingestManager.agentDetails.localMetadataSectionSubtitle": "メタデータを読み込み中", - "xpack.ingestManager.agentDetails.metadataSectionTitle": "メタデータ", - "xpack.ingestManager.agentDetails.platformLabel": "プラットフォーム", - "xpack.ingestManager.agentDetails.policyLabel": "ポリシー", - "xpack.ingestManager.agentDetails.releaseLabel": "エージェントリリース", - "xpack.ingestManager.agentDetails.statusLabel": "ステータス", - "xpack.ingestManager.agentDetails.subTabs.activityLogTab": "アクティビティログ", - "xpack.ingestManager.agentDetails.subTabs.detailsTab": "エージェントの詳細", - "xpack.ingestManager.agentDetails.unexceptedErrorTitle": "エージェントの読み込み中にエラーが発生しました", - "xpack.ingestManager.agentDetails.upgradeAvailableTooltip": "アップグレードが利用可能です", - "xpack.ingestManager.agentDetails.userProvidedMetadataSectionSubtitle": "ユーザー提供メタデータ", - "xpack.ingestManager.agentDetails.versionLabel": "エージェントバージョン", - "xpack.ingestManager.agentDetails.viewAgentListTitle": "すべてのエージェントを表示", - "xpack.ingestManager.agentEnrollment.agentDescription": "Elasticエージェントをホストに追加し、データを収集して、Elastic Stackに送信します。", - "xpack.ingestManager.agentEnrollment.agentsNotInitializedText": "エージェントを登録する前に、{link}。", - "xpack.ingestManager.agentEnrollment.cancelButtonLabel": "キャンセル", - "xpack.ingestManager.agentEnrollment.continueButtonLabel": "続行", - "xpack.ingestManager.agentEnrollment.copyPolicyButton": "クリップボードにコピー", - "xpack.ingestManager.agentEnrollment.copyRunInstructionsButton": "クリップボードにコピー", - "xpack.ingestManager.agentEnrollment.downloadDescription": "Elasticエージェントダウンロードページでは、エージェントバイナリと検証署名をダウンロードできます。", - "xpack.ingestManager.agentEnrollment.downloadLink": "ダウンロードページに移動", - "xpack.ingestManager.agentEnrollment.downloadPolicyButton": "ダウンロードポリシー", - "xpack.ingestManager.agentEnrollment.enrollFleetTabLabel": "Fleetで登録", - "xpack.ingestManager.agentEnrollment.enrollStandaloneTabLabel": "スタンドアロンで実行", - "xpack.ingestManager.agentEnrollment.flyoutTitle": "エージェントの追加", - "xpack.ingestManager.agentEnrollment.goToDataStreamsLink": "データストリーム", - "xpack.ingestManager.agentEnrollment.managedDescription": "ElasticエージェントをFleetに登録して、自動的に更新をデプロイしたり、一元的にエージェントを管理したりします。", - "xpack.ingestManager.agentEnrollment.setUpAgentsLink": "Elasticエージェントの集中管理を設定", - "xpack.ingestManager.agentEnrollment.standaloneDescription": "Elasticエージェントをスタンドアロンで実行して、エージェントがインストールされているホストで、手動でエージェントを構成および更新します。", - "xpack.ingestManager.agentEnrollment.stepCheckForDataDescription": "エージェントがデータの送信を開始します。{link}に移動して、データを表示してください。", - "xpack.ingestManager.agentEnrollment.stepCheckForDataTitle": "データを確認", - "xpack.ingestManager.agentEnrollment.stepChooseAgentPolicyTitle": "エージェントポリシーを選択", - "xpack.ingestManager.agentEnrollment.stepConfigureAgentDescription": "Elasticエージェントがインストールされているホストで、このポリシーを{fileName}にコピーします。Elasticsearch資格情報を使用するには、{fileName}ぎ{outputSection}セクションで、{ESUsernameVariable}と{ESPasswordVariable}を変更します。", - "xpack.ingestManager.agentEnrollment.stepConfigureAgentTitle": "エージェントの構成", - "xpack.ingestManager.agentEnrollment.stepDownloadAgentTitle": "Elasticエージェントをホストにダウンロード", - "xpack.ingestManager.agentEnrollment.stepEnrollAndRunAgentTitle": "Elasticエージェントを登録して実行", - "xpack.ingestManager.agentEnrollment.stepRunAgentDescription": "エージェントのディレクトリから、このコマンドを実行し、Elasticエージェントを、インストール、登録、起動します。このコマンドを再利用すると、複数のホストでエージェントを設定できます。管理者権限が必要です。", - "xpack.ingestManager.agentEnrollment.stepRunAgentTitle": "エージェントの起動", - "xpack.ingestManager.agentEventsList.collapseDetailsAriaLabel": "詳細を非表示", - "xpack.ingestManager.agentEventsList.expandDetailsAriaLabel": "詳細を表示", - "xpack.ingestManager.agentEventsList.messageColumnTitle": "メッセージ", - "xpack.ingestManager.agentEventsList.messageDetailsTitle": "メッセージ", - "xpack.ingestManager.agentEventsList.payloadDetailsTitle": "ペイロード", - "xpack.ingestManager.agentEventsList.refreshButton": "更新", - "xpack.ingestManager.agentEventsList.searchPlaceholderText": "アクティビティログを検索", - "xpack.ingestManager.agentEventsList.subtypeColumnTitle": "サブタイプ", - "xpack.ingestManager.agentEventsList.timestampColumnTitle": "タイムスタンプ", - "xpack.ingestManager.agentEventsList.typeColumnTitle": "タイプ", - "xpack.ingestManager.agentEventSubtype.acknowledgedLabel": "認識", - "xpack.ingestManager.agentEventSubtype.dataDumpLabel": "データダンプ", - "xpack.ingestManager.agentEventSubtype.degradedLabel": "劣化", - "xpack.ingestManager.agentEventSubtype.failedLabel": "失敗", - "xpack.ingestManager.agentEventSubtype.inProgressLabel": "進行中", - "xpack.ingestManager.agentEventSubtype.policyLabel": "ポリシー", - "xpack.ingestManager.agentEventSubtype.runningLabel": "実行中", - "xpack.ingestManager.agentEventSubtype.startingLabel": "開始中", - "xpack.ingestManager.agentEventSubtype.stoppedLabel": "停止", - "xpack.ingestManager.agentEventSubtype.stoppingLabel": "停止中", - "xpack.ingestManager.agentEventSubtype.unknownLabel": "不明", - "xpack.ingestManager.agentEventSubtype.updatingLabel": "更新中", - "xpack.ingestManager.agentEventType.actionLabel": "アクション", - "xpack.ingestManager.agentEventType.actionResultLabel": "アクション結果", - "xpack.ingestManager.agentEventType.errorLabel": "エラー", - "xpack.ingestManager.agentEventType.stateLabel": "ステータス", - "xpack.ingestManager.agentHealth.checkInTooltipText": "前回のチェックイン {lastCheckIn}", - "xpack.ingestManager.agentHealth.degradedStatusText": "劣化", - "xpack.ingestManager.agentHealth.enrollingStatusText": "登録中", - "xpack.ingestManager.agentHealth.errorStatusText": "エラー", - "xpack.ingestManager.agentHealth.inactiveStatusText": "非アクティブ", - "xpack.ingestManager.agentHealth.noCheckInTooltipText": "チェックインしない", - "xpack.ingestManager.agentHealth.offlineStatusText": "オフライン", - "xpack.ingestManager.agentHealth.onlineStatusText": "オンライン", - "xpack.ingestManager.agentHealth.unenrollingStatusText": "登録解除中", - "xpack.ingestManager.agentHealth.updatingStatusText": "更新中", - "xpack.ingestManager.agentHealth.warningStatusText": "エラー", - "xpack.ingestManager.agentList.actionsColumnTitle": "アクション", - "xpack.ingestManager.agentList.addButton": "エージェントの追加", - "xpack.ingestManager.agentList.agentUpgradeLabel": "アップグレードが利用可能です", - "xpack.ingestManager.agentList.clearFiltersLinkText": "フィルターを消去", - "xpack.ingestManager.agentList.enrollButton": "エージェントの追加", - "xpack.ingestManager.agentList.forceUnenrollOneButton": "強制的に登録解除する", - "xpack.ingestManager.agentList.hostColumnTitle": "ホスト", - "xpack.ingestManager.agentList.lastCheckinTitle": "前回のアクティビティ", - "xpack.ingestManager.agentList.loadingAgentsMessage": "エージェントを読み込み中...", - "xpack.ingestManager.agentList.noAgentsPrompt": "エージェントが登録されていません", - "xpack.ingestManager.agentList.noFilteredAgentsPrompt": "エージェントが見つかりません。{clearFiltersLink}", - "xpack.ingestManager.agentList.outOfDateLabel": "最新ではありません", - "xpack.ingestManager.agentList.policyColumnTitle": "エージェントポリシー", - "xpack.ingestManager.agentList.policyFilterText": "エージェントポリシー", - "xpack.ingestManager.agentList.reassignActionText": "新しいポリシーに割り当てる", - "xpack.ingestManager.agentList.revisionNumber": "rev. {revNumber}", - "xpack.ingestManager.agentList.showInactiveSwitchLabel": "非アクティブ", - "xpack.ingestManager.agentList.showUpgradeableFilterLabel": "アップグレードが利用可能です", - "xpack.ingestManager.agentList.statusColumnTitle": "ステータス", - "xpack.ingestManager.agentList.statusErrorFilterText": "エラー", - "xpack.ingestManager.agentList.statusFilterText": "ステータス", - "xpack.ingestManager.agentList.statusOfflineFilterText": "オフライン", - "xpack.ingestManager.agentList.statusOnlineFilterText": "オンライン", - "xpack.ingestManager.agentList.statusUpdatingFilterText": "更新中", - "xpack.ingestManager.agentList.unenrollOneButton": "エージェントの登録解除", - "xpack.ingestManager.agentList.upgradeOneButton": "エージェントをアップグレード", - "xpack.ingestManager.agentList.versionTitle": "バージョン", - "xpack.ingestManager.agentList.viewActionText": "エージェントを表示", - "xpack.ingestManager.agentListStatus.errorLabel": "エラー", - "xpack.ingestManager.agentListStatus.offlineLabel": "オフライン", - "xpack.ingestManager.agentListStatus.onlineLabel": "オンライン", - "xpack.ingestManager.agentListStatus.totalLabel": "エージェント", - "xpack.ingestManager.agentPolicy.confirmModalCalloutDescription": "選択されたエージェントポリシー{policyName}が一部のエージェントですでに使用されていることをFleetが検出しました。このアクションの結果として、Fleetはこのポリシーで使用されているすべてのエージェントに更新をデプロイします。", - "xpack.ingestManager.agentPolicy.confirmModalCancelButtonLabel": "キャンセル", - "xpack.ingestManager.agentPolicy.confirmModalConfirmButtonLabel": "変更を保存してデプロイ", - "xpack.ingestManager.agentPolicy.confirmModalDescription": "このアクションは元に戻せません。続行していいですか?", - "xpack.ingestManager.agentPolicy.confirmModalTitle": "変更を保存してデプロイ", - "xpack.ingestManager.agentPolicy.linkedAgentCountText": "{count, plural, one {#件のエージェント} other {#件のエージェント}}", - "xpack.ingestManager.agentPolicyActionMenu.buttonText": "アクション", - "xpack.ingestManager.agentPolicyActionMenu.copyPolicyActionText": "ポリシーをコピー", - "xpack.ingestManager.agentPolicyActionMenu.enrollAgentActionText": "エージェントの追加", - "xpack.ingestManager.agentPolicyActionMenu.viewPolicyText": "ポリシーを表示", - "xpack.ingestManager.agentPolicyForm.advancedOptionsToggleLabel": "高度なオプション", - "xpack.ingestManager.agentPolicyForm.descriptionFieldLabel": "説明", - "xpack.ingestManager.agentPolicyForm.descriptionFieldPlaceholder": "どのようにこのポリシーを使用しますか?", - "xpack.ingestManager.agentPolicyForm.monitoringDescription": "パフォーマンスのデバッグと追跡のために、エージェントに関するデータを収集します。", - "xpack.ingestManager.agentPolicyForm.monitoringLabel": "アラート監視", - "xpack.ingestManager.agentPolicyForm.monitoringLogsFieldLabel": "エージェントログを収集", - "xpack.ingestManager.agentPolicyForm.monitoringLogsTooltipText": "このポリシーを使用するElasticエージェントからログを収集します。", - "xpack.ingestManager.agentPolicyForm.monitoringMetricsFieldLabel": "エージェントメトリックを収集", - "xpack.ingestManager.agentPolicyForm.monitoringMetricsTooltipText": "このポリシーを使用するElasticエージェントからメトリックを収集します。", - "xpack.ingestManager.agentPolicyForm.nameFieldLabel": "名前", - "xpack.ingestManager.agentPolicyForm.nameFieldPlaceholder": "名前を選択", - "xpack.ingestManager.agentPolicyForm.nameRequiredErrorMessage": "エージェントポリシー名が必要です。", - "xpack.ingestManager.agentPolicyForm.namespaceFieldDescription": "このポリシーを使用する統合にデフォルトの名前空間を適用します。統合はその独自の名前空間を指定できます。", - "xpack.ingestManager.agentPolicyForm.namespaceFieldLabel": "デフォルト名前空間", - "xpack.ingestManager.agentPolicyForm.systemMonitoringFieldLabel": "システム監視", - "xpack.ingestManager.agentPolicyForm.systemMonitoringText": "システムメトリックを収集", - "xpack.ingestManager.agentPolicyForm.systemMonitoringTooltipText": "このオプションを有効にすると、システムメトリックと情報を収集する統合でポリシーをブートストラップできます。", - "xpack.ingestManager.agentPolicyList.actionsColumnTitle": "アクション", - "xpack.ingestManager.agentPolicyList.addButton": "エージェントポリシーを作成", - "xpack.ingestManager.agentPolicyList.agentsColumnTitle": "エージェント", - "xpack.ingestManager.agentPolicyList.clearFiltersLinkText": "フィルターを消去", - "xpack.ingestManager.agentPolicyList.descriptionColumnTitle": "説明", - "xpack.ingestManager.agentPolicyList.loadingAgentPoliciesMessage": "エージェントポリシーの読み込み中...", - "xpack.ingestManager.agentPolicyList.nameColumnTitle": "名前", - "xpack.ingestManager.agentPolicyList.noAgentPoliciesPrompt": "エージェントポリシーがありません", - "xpack.ingestManager.agentPolicyList.noFilteredAgentPoliciesPrompt": "エージェントポリシーが見つかりません。{clearFiltersLink}", - "xpack.ingestManager.agentPolicyList.packagePoliciesCountColumnTitle": "羹合", - "xpack.ingestManager.agentPolicyList.pageSubtitle": "エージェントポリシーを使用すると、エージェントとエージェントが収集するデータを管理できます。", - "xpack.ingestManager.agentPolicyList.pageTitle": "エージェントポリシー", - "xpack.ingestManager.agentPolicyList.reloadAgentPoliciesButtonText": "再読み込み", - "xpack.ingestManager.agentPolicyList.revisionNumber": "rev. {revNumber}", - "xpack.ingestManager.agentPolicyList.updatedOnColumnTitle": "最終更新日", - "xpack.ingestManager.agentReassignPolicy.cancelButtonLabel": "キャンセル", - "xpack.ingestManager.agentReassignPolicy.continueButtonLabel": "ポリシーの割り当て", - "xpack.ingestManager.agentReassignPolicy.flyoutDescription": "選択した{count, plural, one {エージェント} other {エージェント}}を割り当てる新しいエージェントポリシーを選択します。", - "xpack.ingestManager.agentReassignPolicy.flyoutTitle": "新しいエージェントポリシーを割り当てる", - "xpack.ingestManager.agentReassignPolicy.policyDescription": "選択したエージェントポリシーは、{count, plural, one {{countValue}個の統合} other {{countValue}個の統合}}のデータを収集します。", - "xpack.ingestManager.agentReassignPolicy.selectPolicyLabel": "エージェントポリシー", - "xpack.ingestManager.agentReassignPolicy.successSingleNotificationTitle": "エージェントポリシーが再割り当てされました", - "xpack.ingestManager.agents.pageSubtitle": "ポリシーの更新を管理し、任意のサイズのエージェントのグループにデプロイします。", - "xpack.ingestManager.agents.pageTitle": "エージェント", - "xpack.ingestManager.alphaMessageDescription": "Ingest Managerは本番環境用ではありません。", - "xpack.ingestManager.alphaMessageLinkText": "詳細を参照してください。", - "xpack.ingestManager.alphaMessageTitle": "ベータリリース", - "xpack.ingestManager.alphaMessaging.docsLink": "ドキュメンテーション", - "xpack.ingestManager.alphaMessaging.feedbackText": "{docsLink}をご覧ください。質問やフィードバックについては、{forumLink}にアクセスしてください。", - "xpack.ingestManager.alphaMessaging.flyoutTitle": "このリリースについて", - "xpack.ingestManager.alphaMessaging.forumLink": "ディスカッションフォーラム", - "xpack.ingestManager.alphaMessaging.introText": "Ingest Managerは開発中であり、本番環境用ではありません。このベータリリースは、ユーザーがIngest Managerと新しいElasticエージェントをテストしてフィードバックを提供することを目的としています。このプラグインには、サポートSLAが適用されません。", - "xpack.ingestManager.alphaMessging.closeFlyoutLabel": "閉じる", - "xpack.ingestManager.appNavigation.agentsLinkText": "エージェント", - "xpack.ingestManager.appNavigation.dataStreamsLinkText": "データストリーム", - "xpack.ingestManager.appNavigation.epmLinkText": "羹合", - "xpack.ingestManager.appNavigation.overviewLinkText": "概要", - "xpack.ingestManager.appNavigation.policiesLinkText": "ポリシー", - "xpack.ingestManager.appNavigation.sendFeedbackButton": "フィードバックを送信", - "xpack.ingestManager.appNavigation.settingsButton": "設定", - "xpack.ingestManager.appTitle": "Fleet", - "xpack.ingestManager.betaBadge.labelText": "ベータ", - "xpack.ingestManager.betaBadge.tooltipText": "このプラグインは本番環境用ではありません。バグについてはディスカッションフォーラムで報告してください。", - "xpack.ingestManager.breadcrumbs.addPackagePolicyPageTitle": "統合の追加", - "xpack.ingestManager.breadcrumbs.agentsPageTitle": "エージェント", - "xpack.ingestManager.breadcrumbs.allIntegrationsPageTitle": "すべて", - "xpack.ingestManager.breadcrumbs.appTitle": "Fleet", - "xpack.ingestManager.breadcrumbs.datastreamsPageTitle": "データストリーム", - "xpack.ingestManager.breadcrumbs.editPackagePolicyPageTitle": "統合の編集", - "xpack.ingestManager.breadcrumbs.enrollmentTokensPageTitle": "登録トークン", - "xpack.ingestManager.breadcrumbs.installedIntegrationsPageTitle": "インストール済み", - "xpack.ingestManager.breadcrumbs.integrationsPageTitle": "羹合", - "xpack.ingestManager.breadcrumbs.overviewPageTitle": "概要", - "xpack.ingestManager.breadcrumbs.policiesPageTitle": "ポリシー", - "xpack.ingestManager.copyAgentPolicy.confirmModal.cancelButtonLabel": "キャンセル", - "xpack.ingestManager.copyAgentPolicy.confirmModal.confirmButtonLabel": "ポリシーをコピー", - "xpack.ingestManager.copyAgentPolicy.confirmModal.copyPolicyPrompt": "新しいエージェントポリシーの名前と説明を選択してください。", - "xpack.ingestManager.copyAgentPolicy.confirmModal.copyPolicyTitle": "「{name}」エージェントポリシーをコピー", - "xpack.ingestManager.copyAgentPolicy.confirmModal.defaultNewPolicyName": "{name}(コピー)", - "xpack.ingestManager.copyAgentPolicy.confirmModal.newDescriptionLabel": "説明", - "xpack.ingestManager.copyAgentPolicy.confirmModal.newNameLabel": "新しいポリシー名", - "xpack.ingestManager.copyAgentPolicy.failureNotificationTitle": "エージェントポリシー「{id}」のコピーエラー", - "xpack.ingestManager.copyAgentPolicy.fatalErrorNotificationTitle": "エージェントポリシーのコピーエラー", - "xpack.ingestManager.copyAgentPolicy.successNotificationTitle": "エージェントポリシーがコピーされました", - "xpack.ingestManager.createAgentPolicy.cancelButtonLabel": "キャンセル", - "xpack.ingestManager.createAgentPolicy.errorNotificationTitle": "エージェントポリシーを作成できません", - "xpack.ingestManager.createAgentPolicy.flyoutTitle": "エージェントポリシーを作成", - "xpack.ingestManager.createAgentPolicy.flyoutTitleDescription": "エージェントポリシーは、エージェントのグループ全体にわたる設定を管理する目的で使用されます。エージェントポリシーに統合を追加すると、エージェントで収集するデータを指定できます。エージェントポリシーの編集時には、フリートを使用して、指定したエージェントのグループに更新をデプロイできます。", - "xpack.ingestManager.createAgentPolicy.submitButtonLabel": "エージェントポリシーを作成", - "xpack.ingestManager.createAgentPolicy.successNotificationTitle": "エージェントポリシー「{name}」が作成されました", - "xpack.ingestManager.createPackagePolicy.addedNotificationMessage": "Fleetは'{agentPolicyName}'ポリシーで使用されているすべてのエージェントに更新をデプロイします。", - "xpack.ingestManager.createPackagePolicy.addedNotificationTitle": "「{packagePolicyName}」統合が追加されました。", - "xpack.ingestManager.createPackagePolicy.agentPolicyNameLabel": "エージェントポリシー", - "xpack.ingestManager.createPackagePolicy.cancelButton": "キャンセル", - "xpack.ingestManager.createPackagePolicy.cancelLinkText": "キャンセル", - "xpack.ingestManager.createPackagePolicy.errorOnSaveText": "統合ポリシーにはエラーがあります。保存前に修正してください。", - "xpack.ingestManager.createPackagePolicy.pageDescriptionfromPackage": "次の手順に従い、この統合をエージェントポリシーに追加します。", - "xpack.ingestManager.createPackagePolicy.pageDescriptionfromPolicy": "選択したエージェントポリシーの統合を構成します。", - "xpack.ingestManager.createPackagePolicy.pageTitle": "統合の追加", - "xpack.ingestManager.createPackagePolicy.pageTitleWithPackageName": "{packageName}統合の追加", - "xpack.ingestManager.createPackagePolicy.saveButton": "統合の保存", - "xpack.ingestManager.createPackagePolicy.stepConfigure.advancedOptionsToggleLinkText": "高度なオプション", - "xpack.ingestManager.createPackagePolicy.stepConfigure.errorCountText": "{count, plural, one {件のエラー} other {件のエラー}}", - "xpack.ingestManager.createPackagePolicy.stepConfigure.hideStreamsAriaLabel": "{type}入力を非表示", - "xpack.ingestManager.createPackagePolicy.stepConfigure.inputSettingsDescription": "次の設定は以下のすべての入力に適用されます。", - "xpack.ingestManager.createPackagePolicy.stepConfigure.inputSettingsTitle": "設定", - "xpack.ingestManager.createPackagePolicy.stepConfigure.inputVarFieldOptionalLabel": "オプション", - "xpack.ingestManager.createPackagePolicy.stepConfigure.integrationSettingsSectionDescription": "この統合の使用方法を識別できるように、名前と説明を選択してください。", - "xpack.ingestManager.createPackagePolicy.stepConfigure.integrationSettingsSectionTitle": "統合設定", - "xpack.ingestManager.createPackagePolicy.stepConfigure.noPolicyOptionsMessage": "構成するものがありません", - "xpack.ingestManager.createPackagePolicy.stepConfigure.packagePolicyDescriptionInputLabel": "説明", - "xpack.ingestManager.createPackagePolicy.stepConfigure.packagePolicyNameInputLabel": "統合名", - "xpack.ingestManager.createPackagePolicy.stepConfigure.packagePolicyNamespaceInputLabel": "名前空間", - "xpack.ingestManager.createPackagePolicy.stepConfigure.showStreamsAriaLabel": "{type}入力を表示", - "xpack.ingestManager.createPackagePolicy.stepConfigure.toggleAdvancedOptionsButtonText": "高度なオプション", - "xpack.ingestManager.createPackagePolicy.stepConfigurePackagePolicyTitle": "統合の構成", - "xpack.ingestManager.createPackagePolicy.stepSelectAgentPolicyTitle": "エージェントポリシーを選択", - "xpack.ingestManager.createPackagePolicy.stepSelectPackage.errorLoadingPackagesTitle": "統合の読み込みエラー", - "xpack.ingestManager.createPackagePolicy.stepSelectPackage.errorLoadingPolicyTitle": "エージェントポリシー情報の読み込みエラー", - "xpack.ingestManager.createPackagePolicy.stepSelectPackage.errorLoadingSelectedPackageTitle": "選択した統合の読み込みエラー", - "xpack.ingestManager.createPackagePolicy.stepSelectPackage.filterPackagesInputPlaceholder": "統合を検索", - "xpack.ingestManager.createPackagePolicy.stepSelectPackageTitle": "統合を選択", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.addButton": "エージェントポリシーを作成", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.agentPolicyAgentsCountText": "{count, plural, one {#個のエージェント} other {#個のエージェント}}が登録されました", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.agentPolicyAgentsDescriptionText": "選択したエージェントポリシーで{count, plural, one {#個のエージェント} other {#個のエージェント}}が登録されました。", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.agentPolicyLabel": "エージェントポリシー", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.agentPolicyPlaceholderText": "この統合を追加するエージェントポリシーを選択", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.errorLoadingAgentPoliciesTitle": "エージェントポリシーの読み込みエラー", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.errorLoadingPackageTitle": "パッケージ情報の読み込みエラー", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.errorLoadingSelectedAgentPolicyTitle": "選択したエージェントポリシーの読み込みエラー", - "xpack.ingestManager.dataStreamList.actionsColumnTitle": "アクション", - "xpack.ingestManager.dataStreamList.datasetColumnTitle": "データセット", - "xpack.ingestManager.dataStreamList.integrationColumnTitle": "羹合", - "xpack.ingestManager.dataStreamList.lastActivityColumnTitle": "前回のアクティビティ", - "xpack.ingestManager.dataStreamList.loadingDataStreamsMessage": "データストリームを読み込んでいます...", - "xpack.ingestManager.dataStreamList.namespaceColumnTitle": "名前空間", - "xpack.ingestManager.dataStreamList.noDataStreamsPrompt": "データストリームがありません", - "xpack.ingestManager.dataStreamList.noFilteredDataStreamsMessage": "一致するデータストリームが見つかりません", - "xpack.ingestManager.dataStreamList.pageSubtitle": "エージェントが作成したデータを管理します。", - "xpack.ingestManager.dataStreamList.pageTitle": "データストリーム", - "xpack.ingestManager.dataStreamList.reloadDataStreamsButtonText": "再読み込み", - "xpack.ingestManager.dataStreamList.searchPlaceholderTitle": "データストリームをフィルター", - "xpack.ingestManager.dataStreamList.sizeColumnTitle": "サイズ", - "xpack.ingestManager.dataStreamList.typeColumnTitle": "タイプ", - "xpack.ingestManager.dataStreamList.viewDashboardActionText": "ダッシュボードを表示", - "xpack.ingestManager.dataStreamList.viewDashboardsActionText": "ダッシュボードを表示", - "xpack.ingestManager.dataStreamList.viewDashboardsPanelTitle": "ダッシュボードを表示", - "xpack.ingestManager.defaultSearchPlaceholderText": "検索", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.affectedAgentsMessage": "{agentsCount, plural, one {#個のエージェントは} other {#個のエージェントは}}このエージェントポリシーに割り当てられました。このポリシーを削除する前に、これらのエージェントの割り当てを解除します。", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.affectedAgentsTitle": "使用中のポリシー", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.cancelButtonLabel": "キャンセル", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.confirmButtonLabel": "ポリシーを削除", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.deletePolicyTitle": "このエージェントポリシーを削除しますか?", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.irreversibleMessage": "この操作は元に戻すことができません。", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.loadingAgentsCountMessage": "影響があるエージェントの数を確認中...", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.loadingButtonLabel": "読み螟み中...", - "xpack.ingestManager.deleteAgentPolicy.failureSingleNotificationTitle": "エージェントポリシー「{id}」の削除エラー", - "xpack.ingestManager.deleteAgentPolicy.fatalErrorNotificationTitle": "エージェントポリシーの削除エラー", - "xpack.ingestManager.deleteAgentPolicy.successSingleNotificationTitle": "エージェントポリシー「{id}」が削除されました", - "xpack.ingestManager.deletePackagePolicy.confirmModal.affectedAgentsMessage": "{agentPolicyName}が一部のエージェントですでに使用されていることをFleetが検出しました。", - "xpack.ingestManager.deletePackagePolicy.confirmModal.affectedAgentsTitle": "このアクションは {agentsCount} {agentsCount, plural, one {# エージェント} other {# エージェント}}に影響します", - "xpack.ingestManager.deletePackagePolicy.confirmModal.cancelButtonLabel": "キャンセル", - "xpack.ingestManager.deletePackagePolicy.confirmModal.deleteMultipleTitle": "{count, plural, one {個の統合} other {個の統合}}を削除しますか?", - "xpack.ingestManager.deletePackagePolicy.confirmModal.generalMessage": "このアクションは元に戻せません。続行していいですか?", - "xpack.ingestManager.deletePackagePolicy.confirmModal.loadingAgentsCountMessage": "影響があるエージェントを確認中...", - "xpack.ingestManager.deletePackagePolicy.confirmModal.loadingButtonLabel": "読み螟み中...", - "xpack.ingestManager.deletePackagePolicy.failureMultipleNotificationTitle": "{count}個の統合の削除エラー", - "xpack.ingestManager.deletePackagePolicy.failureSingleNotificationTitle": "統合「{id}」の削除エラー", - "xpack.ingestManager.deletePackagePolicy.fatalErrorNotificationTitle": "統合の削除エラー", - "xpack.ingestManager.deletePackagePolicy.successMultipleNotificationTitle": "{count}個の統合を削除しました", - "xpack.ingestManager.deletePackagePolicy.successSingleNotificationTitle": "統合「{id}」を削除しました", - "xpack.ingestManager.disabledSecurityDescription": "Elastic Fleet を使用するには、Kibana と Elasticsearch でセキュリティを有効にする必要があります。", - "xpack.ingestManager.disabledSecurityTitle": "セキュリティが有効ではありません", - "xpack.ingestManager.editAgentPolicy.cancelButtonText": "キャンセル", - "xpack.ingestManager.editAgentPolicy.errorNotificationTitle": "エージェントポリシーを更新できません", - "xpack.ingestManager.editAgentPolicy.saveButtonText": "変更を保存", - "xpack.ingestManager.editAgentPolicy.savingButtonText": "保存中…", - "xpack.ingestManager.editAgentPolicy.successNotificationTitle": "正常に「{name}」設定を更新しました", - "xpack.ingestManager.editAgentPolicy.unsavedChangesText": "保存されていない変更があります", - "xpack.ingestManager.editPackagePolicy.cancelButton": "キャンセル", - "xpack.ingestManager.editPackagePolicy.errorLoadingDataMessage": "この統合情報の読み込みエラーが発生しました", - "xpack.ingestManager.editPackagePolicy.errorLoadingDataTitle": "データの読み込み中にエラーが発生", - "xpack.ingestManager.editPackagePolicy.failedConflictNotificationMessage": "データが最新ではありません。最新のポリシーを取得するには、ページを更新してください。", - "xpack.ingestManager.editPackagePolicy.failedNotificationTitle": "「{packagePolicyName}」の更新エラー", - "xpack.ingestManager.editPackagePolicy.pageDescription": "統合設定を修正し、選択したエージェントポリシーに変更をデプロイします。", - "xpack.ingestManager.editPackagePolicy.pageTitle": "統合の編集", - "xpack.ingestManager.editPackagePolicy.pageTitleWithPackageName": "{packageName}統合の編集", - "xpack.ingestManager.editPackagePolicy.saveButton": "統合の保存", - "xpack.ingestManager.editPackagePolicy.updatedNotificationMessage": "Fleetは'{agentPolicyName}'ポリシーで使用されているすべてのエージェントに更新をデプロイします", - "xpack.ingestManager.editPackagePolicy.updatedNotificationTitle": "正常に「{packagePolicyName}」を更新しました", - "xpack.ingestManager.enrollemntAPIKeyList.emptyMessage": "登録トークンが見つかりません。", - "xpack.ingestManager.enrollemntAPIKeyList.loadingTokensMessage": "登録トークンを読み込んでいます...", - "xpack.ingestManager.enrollmentInstructions.descriptionText": "エージェントのディレクトリから、該当するコマンドを実行し、Elasticエージェントをインストール、登録、起動します。これらのコマンドを再利用すると、複数のホストでエージェントを設定できます。管理者権限が必要です。", - "xpack.ingestManager.enrollmentInstructions.linuxMacOSTitle": "Linux、MacOS", - "xpack.ingestManager.enrollmentInstructions.moreInstructionsLink": "Elasticエージェントドキュメント", - "xpack.ingestManager.enrollmentInstructions.moreInstructionsText": "手順とオプションの詳細については、{link}を参照してください。", - "xpack.ingestManager.enrollmentInstructions.windowsTitle": "Windows", - "xpack.ingestManager.enrollmentStepAgentPolicy.enrollmentTokenSelectLabel": "登録トークン", - "xpack.ingestManager.enrollmentStepAgentPolicy.policySelectAriaLabel": "エージェントポリシー", - "xpack.ingestManager.enrollmentStepAgentPolicy.policySelectLabel": "エージェントポリシー", - "xpack.ingestManager.enrollmentStepAgentPolicy.showAuthenticationSettingsButton": "認証設定", - "xpack.ingestManager.enrollmentTokenDeleteModal.cancelButton": "キャンセル", - "xpack.ingestManager.enrollmentTokenDeleteModal.deleteButton": "登録トークンを取り消し", - "xpack.ingestManager.enrollmentTokenDeleteModal.description": "{keyName}を取り消してよろしいですか?このトークンを使用するエージェントは、ポリシーにアクセスしたり、データを送信したりできなくなります。 ", - "xpack.ingestManager.enrollmentTokenDeleteModal.title": "登録トークンを取り消し", - "xpack.ingestManager.enrollmentTokensList.actionsTitle": "アクション", - "xpack.ingestManager.enrollmentTokensList.activeTitle": "アクティブ", - "xpack.ingestManager.enrollmentTokensList.createdAtTitle": "作成日時", - "xpack.ingestManager.enrollmentTokensList.hideTokenButtonLabel": "トークンを非表示", - "xpack.ingestManager.enrollmentTokensList.nameTitle": "名前", - "xpack.ingestManager.enrollmentTokensList.newKeyButton": "登録トークンを作成", - "xpack.ingestManager.enrollmentTokensList.pageDescription": "登録トークンを作成して取り消します。登録トークンを使用すると、1つ以上のエージェントをFleetに登録し、データを送信できます。", - "xpack.ingestManager.enrollmentTokensList.policyTitle": "エージェントポリシー", - "xpack.ingestManager.enrollmentTokensList.revokeTokenButtonLabel": "トークンを取り消す", - "xpack.ingestManager.enrollmentTokensList.secretTitle": "シークレット", - "xpack.ingestManager.enrollmentTokensList.showTokenButtonLabel": "トークンを表示", - "xpack.ingestManager.epm.addPackagePolicyButtonText": "{packageName}の追加", - "xpack.ingestManager.epm.assetGroupTitle": "{assetType}アセット", - "xpack.ingestManager.epm.browseAllButtonText": "すべての統合を参照", - "xpack.ingestManager.epm.illustrationAltText": "統合の例", - "xpack.ingestManager.epm.loadingIntegrationErrorTitle": "統合詳細の読み込みエラー", - "xpack.ingestManager.epm.packageDetailsNav.overviewLinkText": "概要", - "xpack.ingestManager.epm.packageDetailsNav.packagePoliciesLinkText": "使用", - "xpack.ingestManager.epm.packageDetailsNav.settingsLinkText": "設定", - "xpack.ingestManager.epm.pageSubtitle": "一般的なアプリやサービスの統合を参照する", - "xpack.ingestManager.epm.pageTitle": "羹合", - "xpack.ingestManager.epm.releaseBadge.betaDescription": "この統合は本番環境用ではありません。", - "xpack.ingestManager.epm.releaseBadge.betaLabel": "ベータ", - "xpack.ingestManager.epm.releaseBadge.experimentalDescription": "この統合は、急に変更されたり、将来のリリースで削除されたりする可能性があります。", - "xpack.ingestManager.epm.releaseBadge.experimentalLabel": "実験的", - "xpack.ingestManager.epm.screenshotsTitle": "スクリーンショット", - "xpack.ingestManager.epm.updateAvailableTooltip": "更新が利用可能です", - "xpack.ingestManager.epm.versionLabel": "バージョン", - "xpack.ingestManager.epmList.allFilterLinkText": "すべて", - "xpack.ingestManager.epmList.allPackagesFilterLinkText": "すべて", - "xpack.ingestManager.epmList.allTabText": "すべての統合", - "xpack.ingestManager.epmList.allTitle": "カテゴリで参照", - "xpack.ingestManager.epmList.installedTabText": "インストールされている統合", - "xpack.ingestManager.epmList.installedTitle": "インストールされている統合", - "xpack.ingestManager.epmList.noPackagesFoundPlaceholder": "パッケージが見つかりません", - "xpack.ingestManager.epmList.searchPackagesPlaceholder": "統合を検索", - "xpack.ingestManager.epmList.updatesAvailableFilterLinkText": "更新が可能です", - "xpack.ingestManager.featureCatalogueDescription": "Elasticエージェントと統合のFleetを追加して管理します。", - "xpack.ingestManager.featureCatalogueTitle": "Elasticエージェントの追加", - "xpack.ingestManager.genericActionsMenuText": "開く", - "xpack.ingestManager.homeIntegration.tutorialDirectory.dismissNoticeButtonText": "メッセージを消去", - "xpack.ingestManager.homeIntegration.tutorialDirectory.noticeText": "Elasticエージェントでは、シンプルかつ統合された方法で、ログ、メトリック、他の種類のデータの監視をホストに追加することができます。複数のBeatsと他のエージェントをインストールする必要はありません。このため、インフラストラクチャ全体でのポリシーのデプロイが簡単で高速になりました。詳細については、{blogPostLink}をお読みください。", - "xpack.ingestManager.homeIntegration.tutorialDirectory.noticeText.blogPostLink": "発表ブログ投稿", - "xpack.ingestManager.homeIntegration.tutorialDirectory.noticeTitle": "{newPrefix} ElasticエージェントおよびIngest Managerベータ", - "xpack.ingestManager.homeIntegration.tutorialDirectory.noticeTitle.newPrefix": "新規:", - "xpack.ingestManager.homeIntegration.tutorialModule.noticeText": "{notePrefix}このモジュールの新しいバージョンは、Ingest Managerベータの{availableAsIntegrationLink}です。エージェントポリシーと新しいElasticエージェントの詳細については、{blogPostLink}をお読みください。", - "xpack.ingestManager.homeIntegration.tutorialModule.noticeText.blogPostLink": "発表ブログ投稿", - "xpack.ingestManager.homeIntegration.tutorialModule.noticeText.integrationLink": "統合として利用可能", - "xpack.ingestManager.homeIntegration.tutorialModule.noticeText.notePrefix": "注:", - "xpack.ingestManager.initializationErrorMessageTitle": "Ingest Manager を初期化できません", - "xpack.ingestManager.integrations.installPackage.installingPackageButtonLabel": "{title}アセットをインストールしています", - "xpack.ingestManager.integrations.installPackage.installPackageButtonLabel": "{title}アセットをインストール", - "xpack.ingestManager.integrations.packageInstallErrorDescription": "このパッケージのインストール中に問題が発生しました。しばらくたってから再試行してください。", - "xpack.ingestManager.integrations.packageInstallErrorTitle": "{title}パッケージをインストールできませんでした", - "xpack.ingestManager.integrations.packageInstallSuccessDescription": "正常き{title}をインストールしました", - "xpack.ingestManager.integrations.packageInstallSuccessTitle": "{title}をインストールしました", - "xpack.ingestManager.integrations.packageUninstallErrorDescription": "このパッケージのアンインストール中に問題が発生しました。しばらくたってから再試行してください。", - "xpack.ingestManager.integrations.packageUninstallErrorTitle": "{title}パッケージをアンインストールできませんでした", - "xpack.ingestManager.integrations.packageUninstallSuccessDescription": "正常き{title}をアンインストールしました", - "xpack.ingestManager.integrations.packageUninstallSuccessTitle": "{title}をアンインストールしました", - "xpack.ingestManager.integrations.settings.confirmInstallModal.cancelButtonLabel": "キャンセル", - "xpack.ingestManager.integrations.settings.confirmInstallModal.installButtonLabel": "{packageName}をインストール", - "xpack.ingestManager.integrations.settings.confirmInstallModal.installCalloutTitle": "{numOfAssets}個のアセットがインストールされます", - "xpack.ingestManager.integrations.settings.confirmInstallModal.installDescription": "Kibanaアセットは現在のスペース(既定)にインストールされ、このスペースを表示する権限があるユーザーのみがアクセスできます。Elasticsearchアセットはグローバルでインストールされ、すべてのKibanaユーザーがアクセスできます。", - "xpack.ingestManager.integrations.settings.confirmInstallModal.installTitle": "{packageName}をインストール", - "xpack.ingestManager.integrations.settings.confirmUninstallModal.cancelButtonLabel": "キャンセル", - "xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallButtonLabel": "{packageName}をアンインストール", - "xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallCallout.description": "この統合によって作成されたKibanaおよびElasticsearchアセットは削除されます。エージェントポリシーとエージェントによって送信されたデータは影響を受けません。", - "xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallCallout.title": "{numOfAssets}個のアセットが削除されます", - "xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallDescription": "この操作は元に戻すことができません。続行していいですか?", - "xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallTitle": "{packageName}をアンインストール", - "xpack.ingestManager.integrations.settings.packageInstallDescription": "この統合をインストールして、{title}データ向けに設計されたKibanaおよびElasticsearchアセットをセットアップします。", - "xpack.ingestManager.integrations.settings.packageInstallTitle": "{title}をインストール", - "xpack.ingestManager.integrations.settings.packageSettingsTitle": "設定", - "xpack.ingestManager.integrations.settings.packageUninstallDescription": "この統合によってインストールされたKibanaおよびElasticsearchアセットを削除します。", - "xpack.ingestManager.integrations.settings.packageUninstallNoteDescription.packageUninstallNoteDetail": "{strongNote} {title}をアンインストールできません。この統合を使用しているアクティブなエージェントがあります。アンインストールするには、エージェントポリシーからすべての{title}統合を削除します。", - "xpack.ingestManager.integrations.settings.packageUninstallNoteDescription.packageUninstallNoteLabel": "注:", - "xpack.ingestManager.integrations.settings.packageUninstallNoteDescription.packageUninstallUninstallableNoteDetail": "{strongNote} {title}統合は既定でインストールされているため、削除できません。", - "xpack.ingestManager.integrations.settings.packageUninstallTitle": "{title}をアンインストール", - "xpack.ingestManager.integrations.settings.packageVersionTitle": "{title}バージョン", - "xpack.ingestManager.integrations.settings.versionInfo.installedVersion": "インストールされているバージョン", - "xpack.ingestManager.integrations.settings.versionInfo.latestVersion": "最新バージョン", - "xpack.ingestManager.integrations.settings.versionInfo.updatesAvailable": "更新が利用可能です", - "xpack.ingestManager.integrations.uninstallPackage.uninstallingPackageButtonLabel": "{title}をアンインストールしています", - "xpack.ingestManager.integrations.uninstallPackage.uninstallPackageButtonLabel": "{title}をアンインストール", - "xpack.ingestManager.integrations.updatePackage.updatePackageButtonLabel": "最新バージョンに更新", - "xpack.ingestManager.invalidLicenseDescription": "現在のライセンスは期限切れです。登録されたビートエージェントは引き続き動作しますが、Elastic Fleet インターフェースにアクセスするには有効なライセンスが必要です。", - "xpack.ingestManager.invalidLicenseTitle": "ライセンスの期限切れ", - "xpack.ingestManager.listTabs.agentTitle": "エージェント", - "xpack.ingestManager.listTabs.enrollmentTokensTitle": "登録トークン", - "xpack.ingestManager.metadataForm.addButton": "+ メタデータを追加", - "xpack.ingestManager.metadataForm.keyLabel": "キー", - "xpack.ingestManager.metadataForm.submitButtonText": "追加", - "xpack.ingestManager.metadataForm.valueLabel": "値", - "xpack.ingestManager.namespaceValidation.invalidCharactersErrorMessage": "名前空間に無効な文字が含まれています", - "xpack.ingestManager.namespaceValidation.lowercaseErrorMessage": "名前空間は小文字で指定する必要があります", - "xpack.ingestManager.namespaceValidation.requiredErrorMessage": "名前空間は必須です", - "xpack.ingestManager.namespaceValidation.tooLongErrorMessage": "名前空間は100バイト以下でなければなりません", - "xpack.ingestManager.newEnrollmentKey.cancelButtonLabel": "キャンセル", - "xpack.ingestManager.newEnrollmentKey.flyoutTitle": "登録トークンを作成", - "xpack.ingestManager.newEnrollmentKey.keyCreatedToasts": "登録トークンが作成されました。", - "xpack.ingestManager.newEnrollmentKey.nameLabel": "名前", - "xpack.ingestManager.newEnrollmentKey.policyLabel": "ポリシー", - "xpack.ingestManager.newEnrollmentKey.submitButton": "登録トークンを作成", - "xpack.ingestManager.noAccess.accessDeniedDescription": "Elastic Fleet にアクセスする権限がありません。Elastic Fleet を使用するには、このアプリケーションの読み取り権または全権を含むユーザーロールが必要です。", - "xpack.ingestManager.noAccess.accessDeniedTitle": "アクセスが拒否されました", - "xpack.ingestManager.overviewAgentActiveTitle": "アクティブ", - "xpack.ingestManager.overviewAgentErrorTitle": "エラー", - "xpack.ingestManager.overviewAgentOfflineTitle": "オフライン", - "xpack.ingestManager.overviewAgentTotalTitle": "合計エージェント数", - "xpack.ingestManager.overviewDatastreamNamespacesTitle": "名前空間", - "xpack.ingestManager.overviewDatastreamSizeTitle": "合計サイズ", - "xpack.ingestManager.overviewDatastreamTotalTitle": "データストリーム", - "xpack.ingestManager.overviewIntegrationsInstalledTitle": "インストール済み", - "xpack.ingestManager.overviewIntegrationsTotalTitle": "合計利用可能数", - "xpack.ingestManager.overviewIntegrationsUpdatesAvailableTitle": "更新が可能です", - "xpack.ingestManager.overviewPackagePolicyTitle": "使用済みの統合", - "xpack.ingestManager.overviewPageAgentsPanelTitle": "エージェント", - "xpack.ingestManager.overviewPageDataStreamsPanelAction": "データストリームを表示", - "xpack.ingestManager.overviewPageDataStreamsPanelTitle": "データストリーム", - "xpack.ingestManager.overviewPageDataStreamsPanelTooltip": "エージェントが収集するデータはさまざまなデータストリームに整理されます。", - "xpack.ingestManager.overviewPageEnrollAgentButton": "エージェントの追加", - "xpack.ingestManager.overviewPageFleetPanelAction": "エージェントを表示", - "xpack.ingestManager.overviewPageFleetPanelTooltip": "Fleetを使用して、中央の場所からエージェントを登録し、ポリシーを管理します。", - "xpack.ingestManager.overviewPageIntegrationsPanelAction": "統合を表示", - "xpack.ingestManager.overviewPageIntegrationsPanelTitle": "羹合", - "xpack.ingestManager.overviewPageIntegrationsPanelTooltip": "Elastic Stackの統合を参照し、インストールします。統合をエージェントポリシーに追加し、データの送信を開始します。", - "xpack.ingestManager.overviewPagePoliciesPanelAction": "ポリシーを表示", - "xpack.ingestManager.overviewPagePoliciesPanelTitle": "エージェントポリシー", - "xpack.ingestManager.overviewPagePoliciesPanelTooltip": "エージェントポリシーを使用すると、エージェントが収集するデータを管理できます。", - "xpack.ingestManager.overviewPageSubtitle": "Elasticエージェントとポリシーを中央の場所で管理します。", - "xpack.ingestManager.overviewPageTitle": "Fleet", - "xpack.ingestManager.overviewPolicyTotalTitle": "合計利用可能数", - "xpack.ingestManager.packagePolicyValidation.invalidArrayErrorMessage": "無効なフォーマット", - "xpack.ingestManager.packagePolicyValidation.invalidYamlFormatErrorMessage": "YAML形式が無効です", - "xpack.ingestManager.packagePolicyValidation.nameRequiredErrorMessage": "名前が必要です", - "xpack.ingestManager.packagePolicyValidation.requiredErrorMessage": "{fieldName}が必要です", - "xpack.ingestManager.permissionDeniedErrorMessage": "Ingest Managerにアクセスする権限がありません。Ingest Managerきは{roleName}権限が必要です。", - "xpack.ingestManager.permissionDeniedErrorTitle": "パーミッションが拒否されました", - "xpack.ingestManager.permissionsRequestErrorMessageDescription": "Ingest Managerアクセス権の確認中に問題が発生しました", - "xpack.ingestManager.permissionsRequestErrorMessageTitle": "アクセス権を確認できません", - "xpack.ingestManager.policyDetails.addPackagePolicyButtonText": "統合の追加", - "xpack.ingestManager.policyDetails.ErrorGettingFullAgentPolicy": "エージェントポリシーの読み込みエラー", - "xpack.ingestManager.policyDetails.packagePoliciesTable.actionsColumnTitle": "アクション", - "xpack.ingestManager.policyDetails.packagePoliciesTable.deleteActionTitle": "統合の削除", - "xpack.ingestManager.policyDetails.packagePoliciesTable.descriptionColumnTitle": "説明", - "xpack.ingestManager.policyDetails.packagePoliciesTable.editActionTitle": "統合の編集", - "xpack.ingestManager.policyDetails.packagePoliciesTable.nameColumnTitle": "名前", - "xpack.ingestManager.policyDetails.packagePoliciesTable.namespaceColumnTitle": "名前空間", - "xpack.ingestManager.policyDetails.packagePoliciesTable.packageNameColumnTitle": "羹合", - "xpack.ingestManager.policyDetails.policyDetailsTitle": "ポリシー「{id}」", - "xpack.ingestManager.policyDetails.policyNotFoundErrorTitle": "ポリシー「{id}」が見つかりません", - "xpack.ingestManager.policyDetails.subTabs.packagePoliciesTabText": "羹合", - "xpack.ingestManager.policyDetails.subTabs.settingsTabText": "設定", - "xpack.ingestManager.policyDetails.summary.integrations": "羹合", - "xpack.ingestManager.policyDetails.summary.lastUpdated": "最終更新日", - "xpack.ingestManager.policyDetails.summary.revision": "リビジョン", - "xpack.ingestManager.policyDetails.summary.usedBy": "使用者", - "xpack.ingestManager.policyDetails.unexceptedErrorTitle": "エージェントポリシーの読み込み中にエラーが発生しました", - "xpack.ingestManager.policyDetails.viewAgentListTitle": "すべてのエージェントポリシーを表示", - "xpack.ingestManager.policyDetails.yamlDownloadButtonLabel": "ダウンロードポリシー", - "xpack.ingestManager.policyDetails.yamlFlyoutCloseButtonLabel": "閉じる", - "xpack.ingestManager.policyDetails.yamlflyoutTitleWithName": "「{name}」エージェントポリシー", - "xpack.ingestManager.policyDetails.yamlflyoutTitleWithoutName": "エージェントポリシー", - "xpack.ingestManager.policyDetailsPackagePolicies.createFirstButtonText": "統合の追加", - "xpack.ingestManager.policyDetailsPackagePolicies.createFirstMessage": "このポリシーにはまだ統合がありません。", - "xpack.ingestManager.policyDetailsPackagePolicies.createFirstTitle": "最初の統合を追加", - "xpack.ingestManager.policyForm.deletePolicyActionText": "ポリシーを削除", - "xpack.ingestManager.policyForm.deletePolicyGroupDescription": "既存のデータは削除されません。", - "xpack.ingestManager.policyForm.deletePolicyGroupTitle": "ポリシーを削除", - "xpack.ingestManager.policyForm.generalSettingsGroupDescription": "エージェントポリシーの名前と説明を選択してください。", - "xpack.ingestManager.policyForm.generalSettingsGroupTitle": "一般設定", - "xpack.ingestManager.policyForm.unableToDeleteDefaultPolicyText": "デフォルトポリシーは削除できません", - "xpack.ingestManager.securityRequiredErrorMessage": "Ingest Managerを使用するには、KibanaとElasticsearchでセキュリティを有効にする必要があります。", - "xpack.ingestManager.securityRequiredErrorTitle": "セキュリティが有効ではありません", - "xpack.ingestManager.settings.additionalYamlConfig": "Elasticsearch出力構成", - "xpack.ingestManager.settings.autoUpgradeDisabledLabel": "エージェントバイナリバージョンを手動で管理します。サブスクリプションが必要です。", - "xpack.ingestManager.settings.autoUpgradeEnabledLabel": "エージェントバイナリを自動的に更新し、最新マイナーバージョンを使用します。", - "xpack.ingestManager.settings.autoUpgradeFieldLabel": "Elasticエージェントバイナリバージョン", - "xpack.ingestManager.settings.cancelButtonLabel": "キャンセル", - "xpack.ingestManager.settings.elasticHostError": "無効なURL", - "xpack.ingestManager.settings.elasticsearchUrlLabel": "Elasticsearch URL", - "xpack.ingestManager.settings.flyoutTitle": "Ingest Manager設定", - "xpack.ingestManager.settings.globalOutputDescription": "データを送信する場所を指定します。これらの設定はすべてのElasticエージェントポリシーに適用されます。", - "xpack.ingestManager.settings.globalOutputTitle": "グローバル出力", - "xpack.ingestManager.settings.integrationUpgradeDisabledFieldLabel": "統合バージョンを手動で管理します。", - "xpack.ingestManager.settings.integrationUpgradeEnabledFieldLabel": "自動的に統合を最新バージョンに更新し、最新のアセットを取得します。新機能を使用するには、エージェントポリシーを更新しなければならない場合があります。", - "xpack.ingestManager.settings.integrationUpgradeFieldLabel": "統合バージョン", - "xpack.ingestManager.settings.invalidYamlFormatErrorMessage": "無効なYAML形式:{reason}", - "xpack.ingestManager.settings.kibanaUrlDifferentPathOrProtocolError": "各URLのプロトコルとパスは同じでなければなりません", - "xpack.ingestManager.settings.kibanaUrlEmptyError": "1つ以上のURLが必要です。", - "xpack.ingestManager.settings.kibanaUrlError": "無効なURL", - "xpack.ingestManager.settings.kibanaUrlLabel": "Kibana URL", - "xpack.ingestManager.settings.saveButtonLabel": "設定を保存", - "xpack.ingestManager.settings.success.message": "設定が保存されました", - "xpack.ingestManager.setupPage.apiKeyServiceLink": "APIキーサービス", - "xpack.ingestManager.setupPage.elasticsearchApiKeyFlagText": "{apiKeyLink}.{apiKeyFlag}を{true}に設定します。", - "xpack.ingestManager.setupPage.elasticsearchSecurityFlagText": "{esSecurityLink}.{securityFlag}を{true}に設定します。", - "xpack.ingestManager.setupPage.elasticsearchSecurityLink": "Elasticsearchセキュリティ", - "xpack.ingestManager.setupPage.enableCentralManagement": "ユーザーを作成し、集中管理を有効にする", - "xpack.ingestManager.setupPage.enableText": "集中管理には、APIキーを作成し、log-*とmetrics-*に書き込むことができるElasticユーザーが必要です。", - "xpack.ingestManager.setupPage.enableTitle": "ElasticElasticエージェントの集中管理を有効にする", - "xpack.ingestManager.setupPage.encryptionKeyFlagText": "{encryptionKeyLink}.{keyFlag}を32文字以上の英数字に設定します。", - "xpack.ingestManager.setupPage.gettingStartedLink": "はじめに", - "xpack.ingestManager.setupPage.gettingStartedText": "詳細については、{link}ガイドをお読みください。", - "xpack.ingestManager.setupPage.kibanaEncryptionLink": "Kibana暗号化鍵", - "xpack.ingestManager.setupPage.kibanaSecurityLink": "Kibanaセキュリティ", - "xpack.ingestManager.setupPage.missingRequirementsCalloutDescription": "Elasticエージェントの集中管理を使用するには、次のElasticsearchとKibanaセキュリティ機能を有効にする必要があります。", - "xpack.ingestManager.setupPage.missingRequirementsCalloutTitle": "不足しているセキュリティ要件", - "xpack.ingestManager.setupPage.missingRequirementsElasticsearchTitle": "Elasticsearchポリシーでは、次のことができます。", - "xpack.ingestManager.setupPage.missingRequirementsKibanaTitle": "Kibanaポリシーでは、次のことができます。", - "xpack.ingestManager.setupPage.tlsFlagText": "{kibanaSecurityLink}.{securityFlag}を{true}に設定します。開発目的では、危険な代替として{tlsFlag}を{true}に設定して、{tlsLink}を無効化できます。", - "xpack.ingestManager.setupPage.tlsLink": "TLS", - "xpack.ingestManager.unenrollAgents.cancelButtonLabel": "キャンセル", - "xpack.ingestManager.unenrollAgents.confirmMultipleButtonLabel": "{count}個のエージェントを登録解除", - "xpack.ingestManager.unenrollAgents.confirmSingleButtonLabel": "エージェントの登録解除", - "xpack.ingestManager.unenrollAgents.deleteMultipleDescription": "このアクションにより、複数のエージェントがFleetから削除され、新しいデータを取り込めなくなります。これらのエージェントによってすでに送信されたデータは一切影響を受けません。この操作は元に戻すことができません。", - "xpack.ingestManager.unenrollAgents.deleteSingleDescription": "このアクションにより、「{hostName}」で実行中の選択したエージェントがFleetから削除されます。エージェントによってすでに送信されたデータは一切削除されません。この操作は元に戻すことができません。", - "xpack.ingestManager.unenrollAgents.deleteSingleTitle": "エージェントの登録解除", - "xpack.ingestManager.unenrollAgents.fatalErrorNotificationTitle": "{count, plural, one {エージェント} other {エージェント}}の登録解除エラー", - "xpack.ingestManager.unenrollAgents.forceDeleteMultipleTitle": "{count}個のエージェントを登録解除", - "xpack.ingestManager.unenrollAgents.forceUnenrollCheckboxLabel": "{count, plural, one {エージェント} other {エージェント}}がただちに削除されました。エージェントが最後のデータを送信するまで待機しない。", - "xpack.ingestManager.unenrollAgents.forceUnenrollLegendText": "{count, plural, one {エージェント} other {エージェント}}を強制的に登録解除", - "xpack.ingestManager.unenrollAgents.successForceMultiNotificationTitle": "エージェントが登録解除されました", - "xpack.ingestManager.unenrollAgents.successForceSingleNotificationTitle": "エージェントが登録解除されました", - "xpack.ingestManager.unenrollAgents.successMultiNotificationTitle": "エージェントを登録解除しています", - "xpack.ingestManager.unenrollAgents.successSingleNotificationTitle": "エージェントを登録解除しています", - "xpack.ingestManager.upgradeAgents.cancelButtonLabel": "キャンセル", - "xpack.ingestManager.upgradeAgents.confirmMultipleButtonLabel": "{count}個のエージェントをアップグレード", - "xpack.ingestManager.upgradeAgents.confirmSingleButtonLabel": "エージェントをアップグレード", - "xpack.ingestManager.upgradeAgents.deleteMultipleTitle": "{count}個のエージェントをアップグレード", - "xpack.ingestManager.upgradeAgents.deleteSingleTitle": "エージェントをアップグレード", - "xpack.ingestManager.upgradeAgents.fatalErrorNotificationTitle": "{count, plural, one {エージェント} other {エージェント}}のアップグレードエラー", - "xpack.ingestManager.upgradeAgents.successMultiNotificationTitle": "エージェントをアップグレード中...", - "xpack.ingestManager.upgradeAgents.successSingleNotificationTitle": "エージェントをアップグレード中", - "xpack.ingestManager.upgradeAgents.upgradeMultipleDescription": "このアクションにより、複数のエージェントがバージョン{version}にアップグレードされます。この操作は元に戻すことができません。続行していいですか?", - "xpack.ingestManager.upgradeAgents.upgradeSingleDescription": "このアクションにより、「{hostName}」で実行中の選択したエージェントがバージョン{version}にアップグレードされます。この操作は元に戻すことができません。続行していいですか?", "xpack.ingestPipelines.addProcesorFormOnFailureFlyout.cancelButtonLabel": "キャンセル", "xpack.ingestPipelines.addProcessorFormOnFailureFlyout.addButtonLabel": "追加", "xpack.ingestPipelines.app.checkingPrivilegesDescription": "権限を確認中…", @@ -20200,7 +20195,6 @@ "xpack.triggersActionsUI.geoThreshold.whenEntityLabel": "エンティティ", "xpack.triggersActionsUI.home.alertsTabTitle": "アラート", "xpack.triggersActionsUI.home.appTitle": "アラートとアクション", - "xpack.triggersActionsUI.home.betaBadgeTooltipContent": "{pluginName} はベータ段階で、変更される可能性があります。デザインとコードはオフィシャル GA 機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャル GA 機能の SLA が適用されません。", "xpack.triggersActionsUI.home.breadcrumbTitle": "アラートとアクション", "xpack.triggersActionsUI.home.connectorsTabTitle": "コネクター", "xpack.triggersActionsUI.home.sectionDescription": "アラートを使用して条件を検出し、コネクターを使用してアクションを実行します。", @@ -20251,18 +20245,14 @@ "xpack.triggersActionsUI.sections.addAlert.error.requiredTimeFieldText": "時間フィールドが必要です。", "xpack.triggersActionsUI.sections.addAlert.error.requiredTimeWindowSizeText": "時間ウィンドウサイズが必要です。", "xpack.triggersActionsUI.sections.addAlert.error.requiredtTermFieldText": "用語フィールドが必要です。", - "xpack.triggersActionsUI.sections.addConnectorForm.betaBadgeTooltipContent": "{pluginName} はベータ段階で、変更される可能性があります。デザインとコードはオフィシャル GA 機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャル GA 機能の SLA が適用されません。", "xpack.triggersActionsUI.sections.addConnectorForm.flyoutTitle": "{actionTypeName} コネクタ", "xpack.triggersActionsUI.sections.addConnectorForm.selectConnectorFlyoutTitle": "コネクターを選択", "xpack.triggersActionsUI.sections.addConnectorForm.updateErrorNotificationText": "コネクターを作成できません。", "xpack.triggersActionsUI.sections.addConnectorForm.updateSuccessNotificationText": "「{connectorName}」を作成しました", - "xpack.triggersActionsUI.sections.addFlyout.betaBadgeTooltipContent": "{pluginName} はベータ段階で、変更される可能性があります。デザインとコードはオフィシャル GA 機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャル GA 機能の SLA が適用されません。", - "xpack.triggersActionsUI.sections.addModalConnectorForm.betaBadgeTooltipContent": "{pluginName} はベータ段階で、変更される可能性があります。デザインとコードはオフィシャル GA 機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャル GA 機能の SLA が適用されません。", "xpack.triggersActionsUI.sections.addModalConnectorForm.cancelButtonLabel": "キャンセル", "xpack.triggersActionsUI.sections.addModalConnectorForm.flyoutTitle": "{actionTypeName} コネクター", "xpack.triggersActionsUI.sections.addModalConnectorForm.saveButtonLabel": "保存", "xpack.triggersActionsUI.sections.addModalConnectorForm.updateSuccessNotificationText": "「{connectorName}」を作成しました", - "xpack.triggersActionsUI.sections.alertAdd.betaBadgeTooltipContent": "{pluginName} はベータ段階で、変更される可能性があります。デザインとコードはオフィシャル GA 機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャル GA 機能の SLA が適用されません。", "xpack.triggersActionsUI.sections.alertAdd.conditionPrompt": "条件を定義してください", "xpack.triggersActionsUI.sections.alertAdd.errorLoadingAlertVisualizationTitle": "アラートビジュアライゼーションを読み込めません", "xpack.triggersActionsUI.sections.alertAdd.flyoutTitle": "アラートの作成", @@ -20292,7 +20282,6 @@ "xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.columns.status": "ステータス", "xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.active": "アクティブ", "xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.inactive": "OK", - "xpack.triggersActionsUI.sections.alertDetails.betaBadgeTooltipContent": "{pluginName} はベータ段階で、変更される可能性があります。デザインとコードはオフィシャル GA 機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャル GA 機能の SLA が適用されません。", "xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.disableTitle": "無効にする", "xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.muteTitle": "ミュート", "xpack.triggersActionsUI.sections.alertDetails.dismissButtonTitle": "閉じる", @@ -20300,7 +20289,6 @@ "xpack.triggersActionsUI.sections.alertDetails.unableToLoadAlertInstanceSummaryMessage": "アラートインスタンス概要を読み込めません:{message}", "xpack.triggersActionsUI.sections.alertDetails.unableToLoadAlertMessage": "アラートを読み込めません: {message}", "xpack.triggersActionsUI.sections.alertDetails.viewAlertInAppButtonLabel": "アプリで表示", - "xpack.triggersActionsUI.sections.alertEdit.betaBadgeTooltipContent": "{pluginName} はベータ段階で、変更される可能性があります。デザインとコードはオフィシャル GA 機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャル GA 機能の SLA が適用されません。", "xpack.triggersActionsUI.sections.alertEdit.cancelButtonLabel": "キャンセル", "xpack.triggersActionsUI.sections.alertEdit.disabledActionsWarningTitle": "このアラートには無効なアクションがあります", "xpack.triggersActionsUI.sections.alertEdit.flyoutTitle": "アラートを編集", @@ -20413,7 +20401,6 @@ "xpack.triggersActionsUI.sections.builtinActionTypes.emailAction.subjectTextFieldLabel": "件名", "xpack.triggersActionsUI.sections.builtinActionTypes.emailAction.userTextFieldLabel": "ユーザー名", "xpack.triggersActionsUI.sections.editConnectorForm.actionTypeDescription": "{actionDescription}", - "xpack.triggersActionsUI.sections.editConnectorForm.betaBadgeTooltipContent": "{pluginName} はベータ段階で、変更される可能性があります。デザインとコードはオフィシャル GA 機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャル GA 機能の SLA が適用されません。", "xpack.triggersActionsUI.sections.editConnectorForm.cancelButtonLabel": "キャンセル", "xpack.triggersActionsUI.sections.editConnectorForm.descriptionText": "このコネクターは読み取り専用です。", "xpack.triggersActionsUI.sections.editConnectorForm.flyoutPreconfiguredTitle": "コネクターを編集", @@ -20423,7 +20410,6 @@ "xpack.triggersActionsUI.sections.editConnectorForm.tabText": "構成", "xpack.triggersActionsUI.sections.editConnectorForm.updateErrorNotificationText": "コネクターを更新できません。", "xpack.triggersActionsUI.sections.editConnectorForm.updateSuccessNotificationText": "「{connectorName}」を更新しました", - "xpack.triggersActionsUI.sections.preconfiguredConnectorForm.betaBadgeTooltipContent": "{pluginName}はベータ段階で、変更される可能性があります。デザインとコードはオフィシャルGA機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャルGA機能のSLAが適用されません。", "xpack.triggersActionsUI.sections.preconfiguredConnectorForm.flyoutTitle": "{connectorName}", "xpack.triggersActionsUI.sections.preconfiguredConnectorForm.tooltipContent": "このコネクターはあらかじめ構成されているため、編集できません。", "xpack.triggersActionsUI.sections.testConnectorForm.awaitingExecutionDescription": "アクションを実行すると、結果がここに表示されます。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 299a761fa3c4..b44fa6a0e3d9 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -5040,10 +5040,8 @@ "xpack.apm.rum.filters.url.noResults": "没有可用结果", "xpack.apm.rum.jsErrors.errorMessage": "错误消息", "xpack.apm.rum.jsErrors.errorRate": "错误率", - "xpack.apm.rum.jsErrors.errorRateValue": "{errorRate}%", "xpack.apm.rum.jsErrors.impactedPageLoads": "受影响的页面加载", "xpack.apm.rum.jsErrors.totalErrors": "错误总数", - "xpack.apm.rum.userExperienceMetrics": "用户体验指标", "xpack.apm.rum.uxMetrics.longestLongTasks": "长期任务最长持续时间", "xpack.apm.rum.uxMetrics.noOfLongTasks": "长期任务数目", "xpack.apm.rum.uxMetrics.sumLongTasks": "长期任务总持续时间", @@ -7216,6 +7214,580 @@ "xpack.fileUpload.jsonUploadAndParse.writingToIndex": "正在写入索引", "xpack.fileUpload.noIndexSuppliedErrorMessage": "未提供任何索引。", "xpack.fileUpload.patternReader.featuresOmitted": "不具有几何形状的一些特征已省略", + "xpack.fleet.agentBulkActions.agentsSelected": "已选择 {count, plural, one {# 个代理} other {# 个代理}}", + "xpack.fleet.agentBulkActions.clearSelection": "清除所选内容", + "xpack.fleet.agentBulkActions.reassignPolicy": "分配到新策略", + "xpack.fleet.agentBulkActions.selectAll": "选择所有页面上的所有内容", + "xpack.fleet.agentBulkActions.totalAgents": "正在显示 {count, plural, one {# 个代理} other {# 个代理}}", + "xpack.fleet.agentBulkActions.totalAgentsWithLimit": "正在显示 {count} 个代理(共 {total} 个)", + "xpack.fleet.agentBulkActions.unenrollAgents": "取消注册代理", + "xpack.fleet.agentBulkActions.upgradeAgents": "升级代理", + "xpack.fleet.agentDetails.actionsButton": "操作", + "xpack.fleet.agentDetails.agentDetailsTitle": "代理“{id}”", + "xpack.fleet.agentDetails.agentNotFoundErrorDescription": "找不到代理 ID {agentId}", + "xpack.fleet.agentDetails.agentNotFoundErrorTitle": "未找到代理", + "xpack.fleet.agentDetails.agentPolicyLabel": "代理策略", + "xpack.fleet.agentDetails.agentVersionLabel": "代理版本", + "xpack.fleet.agentDetails.hostIdLabel": "代理 ID", + "xpack.fleet.agentDetails.hostNameLabel": "主机名", + "xpack.fleet.agentDetails.localMetadataSectionSubtitle": "本地元数据", + "xpack.fleet.agentDetails.metadataSectionTitle": "元数据", + "xpack.fleet.agentDetails.platformLabel": "平台", + "xpack.fleet.agentDetails.policyLabel": "策略", + "xpack.fleet.agentDetails.releaseLabel": "代理发行版", + "xpack.fleet.agentDetails.statusLabel": "状态", + "xpack.fleet.agentDetails.subTabs.activityLogTab": "活动日志", + "xpack.fleet.agentDetails.subTabs.detailsTab": "代理详情", + "xpack.fleet.agentDetails.unexceptedErrorTitle": "加载代理时出错", + "xpack.fleet.agentDetails.upgradeAvailableTooltip": "升级可用", + "xpack.fleet.agentDetails.userProvidedMetadataSectionSubtitle": "用户提供的元数据", + "xpack.fleet.agentDetails.versionLabel": "代理版本", + "xpack.fleet.agentDetails.viewAgentListTitle": "查看所有代理", + "xpack.fleet.agentEnrollment.agentDescription": "将 Elastic 代理添加到您的主机,以收集数据并将其发送到 Elastic Stack。", + "xpack.fleet.agentEnrollment.agentsNotInitializedText": "注册代理前,请{link}。", + "xpack.fleet.agentEnrollment.cancelButtonLabel": "取消", + "xpack.fleet.agentEnrollment.continueButtonLabel": "睧睭", + "xpack.fleet.agentEnrollment.copyPolicyButton": "复制到剪贴板", + "xpack.fleet.agentEnrollment.copyRunInstructionsButton": "复制到剪贴板", + "xpack.fleet.agentEnrollment.downloadDescription": "可从 Elastic 代理下载页面下载代理二进制文件及其验证签名。", + "xpack.fleet.agentEnrollment.downloadLink": "前往下载页面", + "xpack.fleet.agentEnrollment.downloadPolicyButton": "下载策略", + "xpack.fleet.agentEnrollment.enrollFleetTabLabel": "在 Fleet 中注册", + "xpack.fleet.agentEnrollment.enrollStandaloneTabLabel": "独立运行", + "xpack.fleet.agentEnrollment.flyoutTitle": "添加代理", + "xpack.fleet.agentEnrollment.goToDataStreamsLink": "数据流", + "xpack.fleet.agentEnrollment.managedDescription": "在 Fleet 中注册 Elastic 代理,以便自动部署更新并集中管理该代理。", + "xpack.fleet.agentEnrollment.setUpAgentsLink": "为 Elastic 代理设置集中管理", + "xpack.fleet.agentEnrollment.standaloneDescription": "独立运行 Elastic 代理,以在安装代理的主机上手动配置和更新代理。", + "xpack.fleet.agentEnrollment.stepCheckForDataDescription": "该代理应该开始发送数据。前往 {link} 以查看您的数据。", + "xpack.fleet.agentEnrollment.stepCheckForDataTitle": "检查数据", + "xpack.fleet.agentEnrollment.stepChooseAgentPolicyTitle": "选择代理策略", + "xpack.fleet.agentEnrollment.stepConfigureAgentDescription": "在安装 Elastic 代理的主机上将此策略复制到 {fileName}。在 {fileName} 的 {outputSection} 部分中修改 {ESUsernameVariable} 和 {ESPasswordVariable},以使用您的 Elasticsearch 凭据。", + "xpack.fleet.agentEnrollment.stepConfigureAgentTitle": "配置代理", + "xpack.fleet.agentEnrollment.stepDownloadAgentTitle": "将 Elastic 代理下载到您的主机", + "xpack.fleet.agentEnrollment.stepEnrollAndRunAgentTitle": "注册并启动 Elastic 代理", + "xpack.fleet.agentEnrollment.stepRunAgentDescription": "从代理目录运行此命令,以安装、注册并启动 Elastic 代理。您可以重复使用此命令在多个主机上设置代理。需要管理员权限。", + "xpack.fleet.agentEnrollment.stepRunAgentTitle": "启动代理", + "xpack.fleet.agentEventsList.collapseDetailsAriaLabel": "隐藏详情", + "xpack.fleet.agentEventsList.expandDetailsAriaLabel": "显示详情", + "xpack.fleet.agentEventsList.messageColumnTitle": "月息", + "xpack.fleet.agentEventsList.messageDetailsTitle": "月息", + "xpack.fleet.agentEventsList.payloadDetailsTitle": "负载", + "xpack.fleet.agentEventsList.refreshButton": "刷新", + "xpack.fleet.agentEventsList.searchPlaceholderText": "搜索活动日志", + "xpack.fleet.agentEventsList.subtypeColumnTitle": "子类型", + "xpack.fleet.agentEventsList.timestampColumnTitle": "时间戳", + "xpack.fleet.agentEventsList.typeColumnTitle": "类型", + "xpack.fleet.agentEventSubtype.acknowledgedLabel": "塲祎莤", + "xpack.fleet.agentEventSubtype.dataDumpLabel": "数据转储", + "xpack.fleet.agentEventSubtype.degradedLabel": "已降级", + "xpack.fleet.agentEventSubtype.failedLabel": "夹贼", + "xpack.fleet.agentEventSubtype.inProgressLabel": "进行中", + "xpack.fleet.agentEventSubtype.policyLabel": "策略", + "xpack.fleet.agentEventSubtype.runningLabel": "正在运行", + "xpack.fleet.agentEventSubtype.startingLabel": "正在启动", + "xpack.fleet.agentEventSubtype.stoppedLabel": "已停止", + "xpack.fleet.agentEventSubtype.stoppingLabel": "正在停止", + "xpack.fleet.agentEventSubtype.unknownLabel": "未知", + "xpack.fleet.agentEventSubtype.updatingLabel": "正在更新", + "xpack.fleet.agentEventType.actionLabel": "操作", + "xpack.fleet.agentEventType.actionResultLabel": "操作结果", + "xpack.fleet.agentEventType.errorLabel": "错误", + "xpack.fleet.agentEventType.stateLabel": "状态", + "xpack.fleet.agentHealth.checkInTooltipText": "上次签入时间 {lastCheckIn}", + "xpack.fleet.agentHealth.degradedStatusText": "已降级", + "xpack.fleet.agentHealth.enrollingStatusText": "正在注册", + "xpack.fleet.agentHealth.errorStatusText": "错误", + "xpack.fleet.agentHealth.inactiveStatusText": "非活动", + "xpack.fleet.agentHealth.noCheckInTooltipText": "未签入", + "xpack.fleet.agentHealth.offlineStatusText": "脱机", + "xpack.fleet.agentHealth.onlineStatusText": "联机", + "xpack.fleet.agentHealth.unenrollingStatusText": "正在取消注册", + "xpack.fleet.agentHealth.updatingStatusText": "正在更新", + "xpack.fleet.agentHealth.warningStatusText": "错误", + "xpack.fleet.agentList.actionsColumnTitle": "操作", + "xpack.fleet.agentList.addButton": "添加代理", + "xpack.fleet.agentList.agentUpgradeLabel": "升级可用", + "xpack.fleet.agentList.clearFiltersLinkText": "清除筛选", + "xpack.fleet.agentList.enrollButton": "添加代理", + "xpack.fleet.agentList.forceUnenrollOneButton": "强制取消注册", + "xpack.fleet.agentList.hostColumnTitle": "主机", + "xpack.fleet.agentList.lastCheckinTitle": "上次活动", + "xpack.fleet.agentList.loadingAgentsMessage": "正在加载代理……", + "xpack.fleet.agentList.noAgentsPrompt": "未注册任何代理", + "xpack.fleet.agentList.noFilteredAgentsPrompt": "未找到任何代理。{clearFiltersLink}", + "xpack.fleet.agentList.outOfDateLabel": "过时", + "xpack.fleet.agentList.policyColumnTitle": "代理策略", + "xpack.fleet.agentList.policyFilterText": "代理策略", + "xpack.fleet.agentList.reassignActionText": "分配到新策略", + "xpack.fleet.agentList.revisionNumber": "俎莢 {revNumber}", + "xpack.fleet.agentList.showInactiveSwitchLabel": "非活动", + "xpack.fleet.agentList.showUpgradeableFilterLabel": "升级可用", + "xpack.fleet.agentList.statusColumnTitle": "状态", + "xpack.fleet.agentList.statusErrorFilterText": "错误", + "xpack.fleet.agentList.statusFilterText": "状态", + "xpack.fleet.agentList.statusOfflineFilterText": "脱机", + "xpack.fleet.agentList.statusOnlineFilterText": "联机", + "xpack.fleet.agentList.statusUpdatingFilterText": "正在更新", + "xpack.fleet.agentList.unenrollOneButton": "取消注册代理", + "xpack.fleet.agentList.upgradeOneButton": "升级代理", + "xpack.fleet.agentList.versionTitle": "版本", + "xpack.fleet.agentList.viewActionText": "查看代理", + "xpack.fleet.agentListStatus.errorLabel": "错误", + "xpack.fleet.agentListStatus.offlineLabel": "脱机", + "xpack.fleet.agentListStatus.onlineLabel": "联机", + "xpack.fleet.agentListStatus.totalLabel": "代理", + "xpack.fleet.agentPolicy.confirmModalCalloutDescription": "Fleet 检测到您的部分代理已在使用选定代理策略 {policyName}。由于此操作,Fleet 会将更新部署到使用此策略的所有代理。", + "xpack.fleet.agentPolicy.confirmModalCalloutTitle": "此操作将更新 {agentCount, plural, one {# 个代理} other {# 个代理}}", + "xpack.fleet.agentPolicy.confirmModalCancelButtonLabel": "取消", + "xpack.fleet.agentPolicy.confirmModalConfirmButtonLabel": "保存并部署更改", + "xpack.fleet.agentPolicy.confirmModalDescription": "此操作无法撤消。是否确定要继续?", + "xpack.fleet.agentPolicy.confirmModalTitle": "保存并部署更改", + "xpack.fleet.agentPolicy.linkedAgentCountText": "{count, plural, one {# 个代理} other {# 个代理}}", + "xpack.fleet.agentPolicyActionMenu.buttonText": "操作", + "xpack.fleet.agentPolicyActionMenu.copyPolicyActionText": "复制策略", + "xpack.fleet.agentPolicyActionMenu.enrollAgentActionText": "添加代理", + "xpack.fleet.agentPolicyActionMenu.viewPolicyText": "查看策略", + "xpack.fleet.agentPolicyForm.advancedOptionsToggleLabel": "高级选项", + "xpack.fleet.agentPolicyForm.descriptionFieldLabel": "描述", + "xpack.fleet.agentPolicyForm.descriptionFieldPlaceholder": "此策略将如何使用?", + "xpack.fleet.agentPolicyForm.monitoringDescription": "收集有关代理的数据,用于调试和跟踪性能。", + "xpack.fleet.agentPolicyForm.monitoringLabel": "代理监测", + "xpack.fleet.agentPolicyForm.monitoringLogsFieldLabel": "收集代理日志", + "xpack.fleet.agentPolicyForm.monitoringLogsTooltipText": "从使用此策略的 Elastic 代理收集日志。", + "xpack.fleet.agentPolicyForm.monitoringMetricsFieldLabel": "收集代理指标", + "xpack.fleet.agentPolicyForm.monitoringMetricsTooltipText": "从使用此策略的 Elastic 代理收集指标。", + "xpack.fleet.agentPolicyForm.nameFieldLabel": "名称", + "xpack.fleet.agentPolicyForm.nameFieldPlaceholder": "选择名称", + "xpack.fleet.agentPolicyForm.nameRequiredErrorMessage": "“代理策略名称”必填。", + "xpack.fleet.agentPolicyForm.namespaceFieldDescription": "将默认命名空间应用于使用此策略的集成。集成可以指定自己的命名空间。", + "xpack.fleet.agentPolicyForm.namespaceFieldLabel": "默认命名空间", + "xpack.fleet.agentPolicyForm.systemMonitoringFieldLabel": "系统监测", + "xpack.fleet.agentPolicyForm.systemMonitoringText": "收集系统指标", + "xpack.fleet.agentPolicyForm.systemMonitoringTooltipText": "启用此选项可使用收集系统指标和信息的集成启动您的策略。", + "xpack.fleet.agentPolicyList.actionsColumnTitle": "操作", + "xpack.fleet.agentPolicyList.addButton": "创建代理策略", + "xpack.fleet.agentPolicyList.agentsColumnTitle": "代理", + "xpack.fleet.agentPolicyList.clearFiltersLinkText": "清除筛选", + "xpack.fleet.agentPolicyList.descriptionColumnTitle": "描述", + "xpack.fleet.agentPolicyList.loadingAgentPoliciesMessage": "正在加载代理策略…...", + "xpack.fleet.agentPolicyList.nameColumnTitle": "名称", + "xpack.fleet.agentPolicyList.noAgentPoliciesPrompt": "无代理策略", + "xpack.fleet.agentPolicyList.noFilteredAgentPoliciesPrompt": "找不到任何代理策略。{clearFiltersLink}", + "xpack.fleet.agentPolicyList.packagePoliciesCountColumnTitle": "集成", + "xpack.fleet.agentPolicyList.pageSubtitle": "使用代理策略管理代理及其收集的数据。", + "xpack.fleet.agentPolicyList.pageTitle": "代理策略", + "xpack.fleet.agentPolicyList.reloadAgentPoliciesButtonText": "重新加载", + "xpack.fleet.agentPolicyList.revisionNumber": "修订版 {revNumber}", + "xpack.fleet.agentPolicyList.updatedOnColumnTitle": "上次更新时间", + "xpack.fleet.agentReassignPolicy.cancelButtonLabel": "取消", + "xpack.fleet.agentReassignPolicy.continueButtonLabel": "分配策略", + "xpack.fleet.agentReassignPolicy.flyoutDescription": "选择要将选定{count, plural, one {代理} other {代理}}分配到的新代理策略。", + "xpack.fleet.agentReassignPolicy.flyoutTitle": "分配新代理策略", + "xpack.fleet.agentReassignPolicy.policyDescription": "选定代理策略将收集 {count, plural, one {{countValue} 个集成} other {{countValue} 个集成}}的数据:", + "xpack.fleet.agentReassignPolicy.selectPolicyLabel": "代理策略", + "xpack.fleet.agentReassignPolicy.successSingleNotificationTitle": "代理策略已重新分配", + "xpack.fleet.agents.pageSubtitle": "管理策略更新并将其部署到一组任意大小的代理。", + "xpack.fleet.agents.pageTitle": "代理", + "xpack.fleet.alphaMessageDescription": "不推荐在生产环境中使用采集管理器。", + "xpack.fleet.alphaMessageLinkText": "查看更多详情。", + "xpack.fleet.alphaMessageTitle": "公测版", + "xpack.fleet.alphaMessaging.docsLink": "文档", + "xpack.fleet.alphaMessaging.feedbackText": "阅读我们的{docsLink}或前往我们的{forumLink},以了解问题或提供反馈。", + "xpack.fleet.alphaMessaging.flyoutTitle": "关于本版本", + "xpack.fleet.alphaMessaging.forumLink": "讨论论坛", + "xpack.fleet.alphaMessaging.introText": "采集管理器仍处于开发状态,不适用于生产环境。此公测版用于用户测试采集管理器和新 Elastic 代理并提供相关反馈。此插件不受支持 SLA 的约束。", + "xpack.fleet.alphaMessging.closeFlyoutLabel": "关闭", + "xpack.fleet.appNavigation.agentsLinkText": "代理", + "xpack.fleet.appNavigation.dataStreamsLinkText": "数据流", + "xpack.fleet.appNavigation.epmLinkText": "集成", + "xpack.fleet.appNavigation.overviewLinkText": "概览", + "xpack.fleet.appNavigation.policiesLinkText": "策略", + "xpack.fleet.appNavigation.sendFeedbackButton": "发送反馈", + "xpack.fleet.appNavigation.settingsButton": "莞罎", + "xpack.fleet.appTitle": "Fleet", + "xpack.fleet.betaBadge.labelText": "公测版", + "xpack.fleet.betaBadge.tooltipText": "不推荐在生产环境中使用此插件。请在我们讨论论坛中报告错误。", + "xpack.fleet.breadcrumbs.addPackagePolicyPageTitle": "添加集成", + "xpack.fleet.breadcrumbs.agentsPageTitle": "代理", + "xpack.fleet.breadcrumbs.allIntegrationsPageTitle": "全部", + "xpack.fleet.breadcrumbs.appTitle": "Fleet", + "xpack.fleet.breadcrumbs.datastreamsPageTitle": "数据流", + "xpack.fleet.breadcrumbs.editPackagePolicyPageTitle": "编辑集成", + "xpack.fleet.breadcrumbs.enrollmentTokensPageTitle": "注册令牌", + "xpack.fleet.breadcrumbs.installedIntegrationsPageTitle": "已安装", + "xpack.fleet.breadcrumbs.integrationsPageTitle": "集成", + "xpack.fleet.breadcrumbs.overviewPageTitle": "概览", + "xpack.fleet.breadcrumbs.policiesPageTitle": "策略", + "xpack.fleet.copyAgentPolicy.confirmModal.cancelButtonLabel": "取消", + "xpack.fleet.copyAgentPolicy.confirmModal.confirmButtonLabel": "复制策略", + "xpack.fleet.copyAgentPolicy.confirmModal.copyPolicyPrompt": "为您的新代理策略选择名称和描述。", + "xpack.fleet.copyAgentPolicy.confirmModal.copyPolicyTitle": "复制代理策略“{name}”", + "xpack.fleet.copyAgentPolicy.confirmModal.defaultNewPolicyName": "{name}(副本)", + "xpack.fleet.copyAgentPolicy.confirmModal.newDescriptionLabel": "描述", + "xpack.fleet.copyAgentPolicy.confirmModal.newNameLabel": "新策略名称", + "xpack.fleet.copyAgentPolicy.failureNotificationTitle": "复制代理策略“{id}”时出错", + "xpack.fleet.copyAgentPolicy.fatalErrorNotificationTitle": "复制代理策略时出错", + "xpack.fleet.copyAgentPolicy.successNotificationTitle": "代理策略已复制", + "xpack.fleet.createAgentPolicy.cancelButtonLabel": "取消", + "xpack.fleet.createAgentPolicy.errorNotificationTitle": "无法创建代理策略", + "xpack.fleet.createAgentPolicy.flyoutTitle": "创建代理策略", + "xpack.fleet.createAgentPolicy.flyoutTitleDescription": "代理策略用于管理一组代理的设置。您可以将集成添加到代理策略,以指定代理收集的数据。编辑代理策略时,可以使用 Fleet 将更新部署到一组指定代理。", + "xpack.fleet.createAgentPolicy.submitButtonLabel": "创建代理策略", + "xpack.fleet.createAgentPolicy.successNotificationTitle": "代理策略“{name}”已创建", + "xpack.fleet.createPackagePolicy.addedNotificationMessage": "Fleet 会将更新部署到所有使用策略“{agentPolicyName}”的代理。", + "xpack.fleet.createPackagePolicy.addedNotificationTitle": "“{packagePolicyName}”集成已添加。", + "xpack.fleet.createPackagePolicy.agentPolicyNameLabel": "代理策略", + "xpack.fleet.createPackagePolicy.cancelButton": "取消", + "xpack.fleet.createPackagePolicy.cancelLinkText": "取消", + "xpack.fleet.createPackagePolicy.errorOnSaveText": "您的集成策略有错误。请在保存前修复这些错误。", + "xpack.fleet.createPackagePolicy.pageDescriptionfromPackage": "按照以下说明将此集成添加到代理策略。", + "xpack.fleet.createPackagePolicy.pageDescriptionfromPolicy": "为选定代理策略配置集成。", + "xpack.fleet.createPackagePolicy.pageTitle": "添加集成", + "xpack.fleet.createPackagePolicy.pageTitleWithPackageName": "添加 {packageName} 集成", + "xpack.fleet.createPackagePolicy.saveButton": "保存集成", + "xpack.fleet.createPackagePolicy.stepConfigure.advancedOptionsToggleLinkText": "高级选项", + "xpack.fleet.createPackagePolicy.stepConfigure.errorCountText": "{count, plural, one {# 个错误} other {# 个错误}}", + "xpack.fleet.createPackagePolicy.stepConfigure.hideStreamsAriaLabel": "隐藏 {type} 输入", + "xpack.fleet.createPackagePolicy.stepConfigure.inputSettingsDescription": "以下设置适用于下面的所有输入。", + "xpack.fleet.createPackagePolicy.stepConfigure.inputSettingsTitle": "莞罎", + "xpack.fleet.createPackagePolicy.stepConfigure.inputVarFieldOptionalLabel": "可选", + "xpack.fleet.createPackagePolicy.stepConfigure.integrationSettingsSectionDescription": "选择有助于确定如何使用此集成的名称和描述。", + "xpack.fleet.createPackagePolicy.stepConfigure.integrationSettingsSectionTitle": "集成设置", + "xpack.fleet.createPackagePolicy.stepConfigure.noPolicyOptionsMessage": "没有可配置的内容", + "xpack.fleet.createPackagePolicy.stepConfigure.packagePolicyDescriptionInputLabel": "描述", + "xpack.fleet.createPackagePolicy.stepConfigure.packagePolicyNameInputLabel": "集成名称", + "xpack.fleet.createPackagePolicy.stepConfigure.packagePolicyNamespaceInputLabel": "命名空间", + "xpack.fleet.createPackagePolicy.stepConfigure.showStreamsAriaLabel": "昞示 {type} 输入", + "xpack.fleet.createPackagePolicy.stepConfigure.toggleAdvancedOptionsButtonText": "高级选项", + "xpack.fleet.createPackagePolicy.stepConfigurePackagePolicyTitle": "配置集成", + "xpack.fleet.createPackagePolicy.stepSelectAgentPolicyTitle": "选择代理策略", + "xpack.fleet.createPackagePolicy.stepSelectPackage.errorLoadingPackagesTitle": "加载集成时出错", + "xpack.fleet.createPackagePolicy.stepSelectPackage.errorLoadingPolicyTitle": "加载代理策略信息时出错", + "xpack.fleet.createPackagePolicy.stepSelectPackage.errorLoadingSelectedPackageTitle": "加载选定集成时出错", + "xpack.fleet.createPackagePolicy.stepSelectPackage.filterPackagesInputPlaceholder": "搜索集成", + "xpack.fleet.createPackagePolicy.stepSelectPackageTitle": "选择集成", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.addButton": "创建代理策略", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.agentPolicyAgentsCountText": "{count, plural, one {# 个代理} other {# 个代理}}已注册", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.agentPolicyAgentsDescriptionText": "{count, plural, one {# 个代理} other {# 个代理}}已注册到选定代理策略中。", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.agentPolicyLabel": "代理策略", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.agentPolicyPlaceholderText": "选择要将此集成添加到的代理策略", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingAgentPoliciesTitle": "加载代理策略时出错", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingPackageTitle": "加载软件包信息时出错", + "xpack.fleet.createPackagePolicy.StepSelectPolicy.errorLoadingSelectedAgentPolicyTitle": "加载选定代理策略时出错", + "xpack.fleet.dataStreamList.actionsColumnTitle": "操作", + "xpack.fleet.dataStreamList.datasetColumnTitle": "数据集", + "xpack.fleet.dataStreamList.integrationColumnTitle": "集成", + "xpack.fleet.dataStreamList.lastActivityColumnTitle": "上次活动", + "xpack.fleet.dataStreamList.loadingDataStreamsMessage": "正在加载数据流……", + "xpack.fleet.dataStreamList.namespaceColumnTitle": "命名空间", + "xpack.fleet.dataStreamList.noDataStreamsPrompt": "无数据流", + "xpack.fleet.dataStreamList.noFilteredDataStreamsMessage": "找不到匹配的数据流", + "xpack.fleet.dataStreamList.pageSubtitle": "管理您的代理创建的数据。", + "xpack.fleet.dataStreamList.pageTitle": "数据流", + "xpack.fleet.dataStreamList.reloadDataStreamsButtonText": "重新加载", + "xpack.fleet.dataStreamList.searchPlaceholderTitle": "筛选数据流", + "xpack.fleet.dataStreamList.sizeColumnTitle": "大小", + "xpack.fleet.dataStreamList.typeColumnTitle": "类型", + "xpack.fleet.dataStreamList.viewDashboardActionText": "查看仪表板", + "xpack.fleet.dataStreamList.viewDashboardsActionText": "查看仪表板", + "xpack.fleet.dataStreamList.viewDashboardsPanelTitle": "查看仪表板", + "xpack.fleet.defaultSearchPlaceholderText": "搜索", + "xpack.fleet.deleteAgentPolicy.confirmModal.affectedAgentsMessage": "{agentsCount, plural, one {# 个代理} other {# 个代理}}已分配到此代理策略。在删除此策略前取消分配这些代理。", + "xpack.fleet.deleteAgentPolicy.confirmModal.affectedAgentsTitle": "在用的策略", + "xpack.fleet.deleteAgentPolicy.confirmModal.cancelButtonLabel": "取消", + "xpack.fleet.deleteAgentPolicy.confirmModal.confirmButtonLabel": "删除策略", + "xpack.fleet.deleteAgentPolicy.confirmModal.deletePolicyTitle": "删除此代理策略?", + "xpack.fleet.deleteAgentPolicy.confirmModal.irreversibleMessage": "此操作无法撤消。", + "xpack.fleet.deleteAgentPolicy.confirmModal.loadingAgentsCountMessage": "正在检查受影响的代理数量……", + "xpack.fleet.deleteAgentPolicy.confirmModal.loadingButtonLabel": "正在加载……", + "xpack.fleet.deleteAgentPolicy.failureSingleNotificationTitle": "删除代理策略“{id}”时出错", + "xpack.fleet.deleteAgentPolicy.fatalErrorNotificationTitle": "删除代理策略时出错", + "xpack.fleet.deleteAgentPolicy.successSingleNotificationTitle": "已删除代理策略“{id}”", + "xpack.fleet.deletePackagePolicy.confirmModal.affectedAgentsMessage": "Fleet 检测到您的部分代理已在使用 {agentPolicyName}。", + "xpack.fleet.deletePackagePolicy.confirmModal.affectedAgentsTitle": "此操作将影响 {agentsCount} 个{agentsCount, plural, one {代理} other {代理}}。", + "xpack.fleet.deletePackagePolicy.confirmModal.cancelButtonLabel": "取消", + "xpack.fleet.deletePackagePolicy.confirmModal.confirmButtonLabel": "删除{agentPoliciesCount, plural, one {集成} other {集成}}", + "xpack.fleet.deletePackagePolicy.confirmModal.deleteMultipleTitle": "删除 {count, plural, one {集成} other {# 个集成}}?", + "xpack.fleet.deletePackagePolicy.confirmModal.generalMessage": "此操作无法撤消。是否确定要继续?", + "xpack.fleet.deletePackagePolicy.confirmModal.loadingAgentsCountMessage": "正在检查受影响的代理……", + "xpack.fleet.deletePackagePolicy.confirmModal.loadingButtonLabel": "正在加载……", + "xpack.fleet.deletePackagePolicy.failureMultipleNotificationTitle": "删除 {count} 个集成时出错", + "xpack.fleet.deletePackagePolicy.failureSingleNotificationTitle": "删除集成“{id}”时出错", + "xpack.fleet.deletePackagePolicy.fatalErrorNotificationTitle": "删除集成时出错", + "xpack.fleet.deletePackagePolicy.successMultipleNotificationTitle": "已删除 {count} 个集成", + "xpack.fleet.deletePackagePolicy.successSingleNotificationTitle": "已删除集成“{id}”", + "xpack.fleet.disabledSecurityDescription": "必须在 Kibana 和 Elasticsearch 启用安全性,才能使用 Elastic Fleet。", + "xpack.fleet.disabledSecurityTitle": "安全性未启用", + "xpack.fleet.editAgentPolicy.cancelButtonText": "取消", + "xpack.fleet.editAgentPolicy.errorNotificationTitle": "无法更新代理策略", + "xpack.fleet.editAgentPolicy.saveButtonText": "保存更改", + "xpack.fleet.editAgentPolicy.savingButtonText": "正在保存……", + "xpack.fleet.editAgentPolicy.successNotificationTitle": "已成功更新“{name}”设置", + "xpack.fleet.editAgentPolicy.unsavedChangesText": "您有未保存的更改", + "xpack.fleet.editPackagePolicy.cancelButton": "取消", + "xpack.fleet.editPackagePolicy.errorLoadingDataMessage": "加载此集成信息时出错", + "xpack.fleet.editPackagePolicy.errorLoadingDataTitle": "加载数据时出错", + "xpack.fleet.editPackagePolicy.failedConflictNotificationMessage": "数据已过时。刷新页面以获取最新策略。", + "xpack.fleet.editPackagePolicy.failedNotificationTitle": "更新“{packagePolicyName}”时出错", + "xpack.fleet.editPackagePolicy.pageDescription": "修改集成设置并将更改部署到选定代理策略。", + "xpack.fleet.editPackagePolicy.pageTitle": "编辑集成", + "xpack.fleet.editPackagePolicy.pageTitleWithPackageName": "编辑 {packageName} 集成", + "xpack.fleet.editPackagePolicy.saveButton": "保存集成", + "xpack.fleet.editPackagePolicy.updatedNotificationMessage": "Fleet 会将更新部署到所有使用策略“{agentPolicyName}”的代理", + "xpack.fleet.editPackagePolicy.updatedNotificationTitle": "已成功更新“{packagePolicyName}”", + "xpack.fleet.enrollemntAPIKeyList.emptyMessage": "未找到任何注册令牌。", + "xpack.fleet.enrollemntAPIKeyList.loadingTokensMessage": "正在加载注册令牌......", + "xpack.fleet.enrollmentInstructions.descriptionText": "从代理目录运行相应命令,以安装、注册并启动 Elastic 代理。您可以重复使用这些命令在多个主机上设置代理。需要管理员权限。", + "xpack.fleet.enrollmentInstructions.linuxMacOSTitle": "Linux、macOS", + "xpack.fleet.enrollmentInstructions.moreInstructionsLink": "Elastic 代理文档", + "xpack.fleet.enrollmentInstructions.moreInstructionsText": "有关更多说明和选项,请参见 {link}。", + "xpack.fleet.enrollmentInstructions.windowsTitle": "Windows", + "xpack.fleet.enrollmentStepAgentPolicy.enrollmentTokenSelectLabel": "注册令牌", + "xpack.fleet.enrollmentStepAgentPolicy.policySelectAriaLabel": "代理策略", + "xpack.fleet.enrollmentStepAgentPolicy.policySelectLabel": "代理策略", + "xpack.fleet.enrollmentStepAgentPolicy.showAuthenticationSettingsButton": "身份验证设置", + "xpack.fleet.enrollmentTokenDeleteModal.cancelButton": "取消", + "xpack.fleet.enrollmentTokenDeleteModal.deleteButton": "撤销注册令牌", + "xpack.fleet.enrollmentTokenDeleteModal.description": "确定要撤销 {keyName}?使用此令牌的代理将无法再访问策略或发送数据。 ", + "xpack.fleet.enrollmentTokenDeleteModal.title": "撤销注册令牌", + "xpack.fleet.enrollmentTokensList.actionsTitle": "操作", + "xpack.fleet.enrollmentTokensList.activeTitle": "活动", + "xpack.fleet.enrollmentTokensList.createdAtTitle": "创建日期", + "xpack.fleet.enrollmentTokensList.hideTokenButtonLabel": "隐藏令牌", + "xpack.fleet.enrollmentTokensList.nameTitle": "名称", + "xpack.fleet.enrollmentTokensList.newKeyButton": "创建注册令牌", + "xpack.fleet.enrollmentTokensList.pageDescription": "创建和撤销注册令牌。注册令牌允许一个或多个代理注册于 Fleet 中并发送数据。", + "xpack.fleet.enrollmentTokensList.policyTitle": "代理策略", + "xpack.fleet.enrollmentTokensList.revokeTokenButtonLabel": "撤销令牌", + "xpack.fleet.enrollmentTokensList.secretTitle": "密钥", + "xpack.fleet.enrollmentTokensList.showTokenButtonLabel": "显示令牌", + "xpack.fleet.epm.addPackagePolicyButtonText": "添加 {packageName}", + "xpack.fleet.epm.assetGroupTitle": "{assetType} 资产", + "xpack.fleet.epm.browseAllButtonText": "浏览所有集成", + "xpack.fleet.epm.illustrationAltText": "集成的图示", + "xpack.fleet.epm.loadingIntegrationErrorTitle": "加载集成详情时出错", + "xpack.fleet.epm.packageDetailsNav.overviewLinkText": "概览", + "xpack.fleet.epm.packageDetailsNav.packagePoliciesLinkText": "使用情况", + "xpack.fleet.epm.packageDetailsNav.settingsLinkText": "莞罎", + "xpack.fleet.epm.pageSubtitle": "浏览集成以了解热门应用和服务。", + "xpack.fleet.epm.pageTitle": "集成", + "xpack.fleet.epm.releaseBadge.betaDescription": "在生产环境中不推荐使用此集成。", + "xpack.fleet.epm.releaseBadge.betaLabel": "公测版", + "xpack.fleet.epm.releaseBadge.experimentalDescription": "此集成可能有重大更改或将在未来版本中移除。", + "xpack.fleet.epm.releaseBadge.experimentalLabel": "实验性", + "xpack.fleet.epm.screenshotsTitle": "屏幕截图", + "xpack.fleet.epm.updateAvailableTooltip": "有可用更新", + "xpack.fleet.epm.versionLabel": "版本", + "xpack.fleet.epmList.allFilterLinkText": "全部", + "xpack.fleet.epmList.allPackagesFilterLinkText": "全部", + "xpack.fleet.epmList.allTabText": "所有集成", + "xpack.fleet.epmList.allTitle": "按类别浏览", + "xpack.fleet.epmList.installedTabText": "已安装集成", + "xpack.fleet.epmList.installedTitle": "已安装集成", + "xpack.fleet.epmList.noPackagesFoundPlaceholder": "未找到任何软件包", + "xpack.fleet.epmList.searchPackagesPlaceholder": "搜索集成", + "xpack.fleet.epmList.updatesAvailableFilterLinkText": "有可用更新", + "xpack.fleet.featureCatalogueDescription": "添加并管理您所有的 Elastic 代理和集成。", + "xpack.fleet.featureCatalogueTitle": "添加 Elastic 代理", + "xpack.fleet.genericActionsMenuText": "打开", + "xpack.fleet.homeIntegration.tutorialDirectory.dismissNoticeButtonText": "关闭消息", + "xpack.fleet.homeIntegration.tutorialDirectory.noticeText": "通过 Elastic 代理,可以简单统一的方式将日志、指标和其他类型数据的监测添加到主机。不再需要安装多个 Beats 和其他代理,这样将策略部署到整个基础架构更容易也更快速。有关更多信息,请阅读我们的{blogPostLink}。", + "xpack.fleet.homeIntegration.tutorialDirectory.noticeText.blogPostLink": "公告博客", + "xpack.fleet.homeIntegration.tutorialDirectory.noticeTitle": "{newPrefix}Elastic 代理和采集管理器公测版", + "xpack.fleet.homeIntegration.tutorialDirectory.noticeTitle.newPrefix": "新通告:", + "xpack.fleet.homeIntegration.tutorialModule.noticeText": "{notePrefix}此模块的较新版本在采集管理器公测版中{availableAsIntegrationLink}。要详细了解代理策略和新的 Elastic 代理,请阅读我们的{blogPostLink}。", + "xpack.fleet.homeIntegration.tutorialModule.noticeText.blogPostLink": "公告博客", + "xpack.fleet.homeIntegration.tutorialModule.noticeText.integrationLink": "作为集成提供", + "xpack.fleet.homeIntegration.tutorialModule.noticeText.notePrefix": "注意:", + "xpack.fleet.initializationErrorMessageTitle": "无法初始化 Ingest Manager", + "xpack.fleet.integrations.installPackage.installingPackageButtonLabel": "正在安装 {title} 资产", + "xpack.fleet.integrations.installPackage.installPackageButtonLabel": "安装 {title} 资产", + "xpack.fleet.integrations.packageInstallErrorDescription": "尝试安装此软件包时出现问题。请稍后重试。", + "xpack.fleet.integrations.packageInstallErrorTitle": "无法安装 {title} 软件包", + "xpack.fleet.integrations.packageInstallSuccessDescription": "已成功安装 {title}", + "xpack.fleet.integrations.packageInstallSuccessTitle": "已安装 {title}", + "xpack.fleet.integrations.packageUninstallErrorDescription": "尝试卸载此软件包时出现问题。请稍后重试。", + "xpack.fleet.integrations.packageUninstallErrorTitle": "无法卸载 {title} 软件包", + "xpack.fleet.integrations.packageUninstallSuccessDescription": "已成功卸载 {title}", + "xpack.fleet.integrations.packageUninstallSuccessTitle": "已卸载 {title}", + "xpack.fleet.integrations.settings.confirmInstallModal.cancelButtonLabel": "取消", + "xpack.fleet.integrations.settings.confirmInstallModal.installButtonLabel": "安装 {packageName}", + "xpack.fleet.integrations.settings.confirmInstallModal.installCalloutTitle": "此操作将安装 {numOfAssets} 个资产", + "xpack.fleet.integrations.settings.confirmInstallModal.installDescription": "Kibana 资产将安装在当前工作区中(默认),仅有权查看此工作区的用户可访问。Elasticsearch 资产为全局安装,所有 Kibana 用户可访问。", + "xpack.fleet.integrations.settings.confirmInstallModal.installTitle": "安装 {packageName}", + "xpack.fleet.integrations.settings.confirmUninstallModal.cancelButtonLabel": "取消", + "xpack.fleet.integrations.settings.confirmUninstallModal.uninstallButtonLabel": "卸载 {packageName}", + "xpack.fleet.integrations.settings.confirmUninstallModal.uninstallCallout.description": "将会移除由此集成创建的 Kibana 和 Elasticsearch 资产。将不会影响代理策略以及您的代理发送的任何数据。", + "xpack.fleet.integrations.settings.confirmUninstallModal.uninstallCallout.title": "此操作将移除 {numOfAssets} 个资产", + "xpack.fleet.integrations.settings.confirmUninstallModal.uninstallDescription": "此操作无法撤消。是否确定要继续?", + "xpack.fleet.integrations.settings.confirmUninstallModal.uninstallTitle": "卸载 {packageName}", + "xpack.fleet.integrations.settings.packageInstallDescription": "安装此集成以设置专用于 {title} 数据的Kibana 和 Elasticsearch 资产。", + "xpack.fleet.integrations.settings.packageInstallTitle": "安装 {title}", + "xpack.fleet.integrations.settings.packageSettingsTitle": "莞罎", + "xpack.fleet.integrations.settings.packageUninstallDescription": "移除此集成安装的 Kibana 和 Elasticsearch 资产。", + "xpack.fleet.integrations.settings.packageUninstallNoteDescription.packageUninstallNoteDetail": "{strongNote}{title} 无法卸载,因为存在使用此集成的活动代理。要卸载,请从您的代理策略中移除所有 {title} 集成。", + "xpack.fleet.integrations.settings.packageUninstallNoteDescription.packageUninstallNoteLabel": "注意:", + "xpack.fleet.integrations.settings.packageUninstallNoteDescription.packageUninstallUninstallableNoteDetail": "{strongNote} {title} 集成默认安装,无法移除。", + "xpack.fleet.integrations.settings.packageUninstallTitle": "卸载 {title}", + "xpack.fleet.integrations.settings.packageVersionTitle": "{title} 版本", + "xpack.fleet.integrations.settings.versionInfo.installedVersion": "已安装版本", + "xpack.fleet.integrations.settings.versionInfo.latestVersion": "最新版本", + "xpack.fleet.integrations.settings.versionInfo.updatesAvailable": "更新可用", + "xpack.fleet.integrations.uninstallPackage.uninstallingPackageButtonLabel": "正在卸载 {title}", + "xpack.fleet.integrations.uninstallPackage.uninstallPackageButtonLabel": "卸载 {title}", + "xpack.fleet.integrations.updatePackage.updatePackageButtonLabel": "更新到最新版本", + "xpack.fleet.invalidLicenseDescription": "您当前的许可证已过期。已注册 Beats 代理将继续工作,但您需要有效的许可证,才能访问 Elastic Fleet 界面。", + "xpack.fleet.invalidLicenseTitle": "已过期许可证", + "xpack.fleet.listTabs.agentTitle": "代理", + "xpack.fleet.listTabs.enrollmentTokensTitle": "注册令牌", + "xpack.fleet.metadataForm.addButton": "+ 添加元数据", + "xpack.fleet.metadataForm.keyLabel": "键", + "xpack.fleet.metadataForm.submitButtonText": "添加", + "xpack.fleet.metadataForm.valueLabel": "值", + "xpack.fleet.namespaceValidation.invalidCharactersErrorMessage": "命名空间包含无效字符", + "xpack.fleet.namespaceValidation.lowercaseErrorMessage": "命名空间必须小写", + "xpack.fleet.namespaceValidation.requiredErrorMessage": "“命名空间”必填", + "xpack.fleet.namespaceValidation.tooLongErrorMessage": "命名空间不能超过 100 个字节", + "xpack.fleet.newEnrollmentKey.cancelButtonLabel": "取消", + "xpack.fleet.newEnrollmentKey.flyoutTitle": "创建注册令牌", + "xpack.fleet.newEnrollmentKey.keyCreatedToasts": "注册令牌已创建。", + "xpack.fleet.newEnrollmentKey.nameLabel": "名称", + "xpack.fleet.newEnrollmentKey.policyLabel": "策略", + "xpack.fleet.newEnrollmentKey.submitButton": "创建注册令牌", + "xpack.fleet.noAccess.accessDeniedDescription": "您无权访问 Elastic Fleet。要使用 Elastic Fleet,您需要包含此应用程序读取权限或所有权限的用户角色。", + "xpack.fleet.noAccess.accessDeniedTitle": "访问被拒绝", + "xpack.fleet.overviewAgentActiveTitle": "活动", + "xpack.fleet.overviewAgentErrorTitle": "错误", + "xpack.fleet.overviewAgentOfflineTitle": "脱机", + "xpack.fleet.overviewAgentTotalTitle": "代理总数", + "xpack.fleet.overviewDatastreamNamespacesTitle": "命名空间", + "xpack.fleet.overviewDatastreamSizeTitle": "总大小", + "xpack.fleet.overviewDatastreamTotalTitle": "数据流", + "xpack.fleet.overviewIntegrationsInstalledTitle": "安装时间", + "xpack.fleet.overviewIntegrationsTotalTitle": "可用总计", + "xpack.fleet.overviewIntegrationsUpdatesAvailableTitle": "可用更新", + "xpack.fleet.overviewPackagePolicyTitle": "已使用的集成", + "xpack.fleet.overviewPageAgentsPanelTitle": "代理", + "xpack.fleet.overviewPageDataStreamsPanelAction": "查看数据流", + "xpack.fleet.overviewPageDataStreamsPanelTitle": "数据流", + "xpack.fleet.overviewPageDataStreamsPanelTooltip": "您的代理收集的数据组织到各种数据流中。", + "xpack.fleet.overviewPageEnrollAgentButton": "添加代理", + "xpack.fleet.overviewPageFleetPanelAction": "查看代理", + "xpack.fleet.overviewPageFleetPanelTooltip": "使用 Fleet 注册代理并从中央位置管理其策略。", + "xpack.fleet.overviewPageIntegrationsPanelAction": "查看集成", + "xpack.fleet.overviewPageIntegrationsPanelTitle": "集成", + "xpack.fleet.overviewPageIntegrationsPanelTooltip": "浏览并安装适用于 Elastic Stack 的集成。将集成添加到您的代理策略,以开始发送数据。", + "xpack.fleet.overviewPagePoliciesPanelAction": "查看策略", + "xpack.fleet.overviewPagePoliciesPanelTitle": "代理策略", + "xpack.fleet.overviewPagePoliciesPanelTooltip": "使用代理策略控制您的代理收集的数据。", + "xpack.fleet.overviewPageSubtitle": "在集中位置管理 Elastic 代理及其策略。", + "xpack.fleet.overviewPageTitle": "Fleet", + "xpack.fleet.overviewPolicyTotalTitle": "可用总计", + "xpack.fleet.packagePolicyValidation.invalidArrayErrorMessage": "格式无效", + "xpack.fleet.packagePolicyValidation.invalidYamlFormatErrorMessage": "YAML 格式无效", + "xpack.fleet.packagePolicyValidation.nameRequiredErrorMessage": "“名称”必填", + "xpack.fleet.packagePolicyValidation.requiredErrorMessage": "“{fieldName}”必填", + "xpack.fleet.permissionDeniedErrorMessage": "您无权访问 Ingest Manager。Ingest Manager 需要{roleName}权限。", + "xpack.fleet.permissionDeniedErrorTitle": "权限被拒绝", + "xpack.fleet.permissionsRequestErrorMessageDescription": "检查 Ingest Manager 权限时出现问题", + "xpack.fleet.permissionsRequestErrorMessageTitle": "无法检查权限", + "xpack.fleet.policyDetails.addPackagePolicyButtonText": "添加集成", + "xpack.fleet.policyDetails.ErrorGettingFullAgentPolicy": "加载代理策略时出错", + "xpack.fleet.policyDetails.packagePoliciesTable.actionsColumnTitle": "操作", + "xpack.fleet.policyDetails.packagePoliciesTable.deleteActionTitle": "删除集成", + "xpack.fleet.policyDetails.packagePoliciesTable.descriptionColumnTitle": "描述", + "xpack.fleet.policyDetails.packagePoliciesTable.editActionTitle": "编辑集成", + "xpack.fleet.policyDetails.packagePoliciesTable.nameColumnTitle": "名称", + "xpack.fleet.policyDetails.packagePoliciesTable.namespaceColumnTitle": "命名空间", + "xpack.fleet.policyDetails.packagePoliciesTable.packageNameColumnTitle": "集成", + "xpack.fleet.policyDetails.policyDetailsTitle": "策略“{id}”", + "xpack.fleet.policyDetails.policyNotFoundErrorTitle": "找不到策略“{id}”", + "xpack.fleet.policyDetails.subTabs.packagePoliciesTabText": "集成", + "xpack.fleet.policyDetails.subTabs.settingsTabText": "莞罎", + "xpack.fleet.policyDetails.summary.integrations": "集成", + "xpack.fleet.policyDetails.summary.lastUpdated": "上次更新时间", + "xpack.fleet.policyDetails.summary.revision": "俎莢", + "xpack.fleet.policyDetails.summary.usedBy": "使用者", + "xpack.fleet.policyDetails.unexceptedErrorTitle": "加载代理策略时发生错误", + "xpack.fleet.policyDetails.viewAgentListTitle": "查看所有代理策略", + "xpack.fleet.policyDetails.yamlDownloadButtonLabel": "下载策略", + "xpack.fleet.policyDetails.yamlFlyoutCloseButtonLabel": "关闭", + "xpack.fleet.policyDetails.yamlflyoutTitleWithName": "代理策略“{name}”", + "xpack.fleet.policyDetails.yamlflyoutTitleWithoutName": "代理策略", + "xpack.fleet.policyDetailsPackagePolicies.createFirstButtonText": "添加集成", + "xpack.fleet.policyDetailsPackagePolicies.createFirstMessage": "此策略尚无任何集成。", + "xpack.fleet.policyDetailsPackagePolicies.createFirstTitle": "添加您的首个集成", + "xpack.fleet.policyForm.deletePolicyActionText": "删除策略", + "xpack.fleet.policyForm.deletePolicyGroupDescription": "现有数据将不会删除。", + "xpack.fleet.policyForm.deletePolicyGroupTitle": "删除策略", + "xpack.fleet.policyForm.generalSettingsGroupDescription": "为您的代理策略选择名称和描述。", + "xpack.fleet.policyForm.generalSettingsGroupTitle": "常规设置", + "xpack.fleet.policyForm.unableToDeleteDefaultPolicyText": "默认策略无法删除", + "xpack.fleet.securityRequiredErrorMessage": "必须在 Kibana 和 Elasticsearch 启用安全性,才能使用 Ingest Manager。", + "xpack.fleet.securityRequiredErrorTitle": "安全性未启用", + "xpack.fleet.settings.additionalYamlConfig": "Elasticsearch 输出配置", + "xpack.fleet.settings.autoUpgradeDisabledLabel": "手动管理代理二进制文件版本。需要黄金级订阅。", + "xpack.fleet.settings.autoUpgradeEnabledLabel": "自动更新代理二进制文件以使用最新的次要版本。", + "xpack.fleet.settings.autoUpgradeFieldLabel": "Elastic 代理二进制文件版本", + "xpack.fleet.settings.cancelButtonLabel": "取消", + "xpack.fleet.settings.elasticHostError": "URL 无效", + "xpack.fleet.settings.elasticsearchUrlLabel": "Elasticsearch URL", + "xpack.fleet.settings.flyoutTitle": "Ingest Manager 莞罎", + "xpack.fleet.settings.globalOutputDescription": "指定将数据发送到何处。这些设置将应用于所有的 Elastic 代理策略。", + "xpack.fleet.settings.globalOutputTitle": "全局输出", + "xpack.fleet.settings.integrationUpgradeDisabledFieldLabel": "自行手动管理集成版本。", + "xpack.fleet.settings.integrationUpgradeEnabledFieldLabel": "将集成自动更新到最新版本以获取最新资产。您可能需要更新代理策略以使用新功能。", + "xpack.fleet.settings.integrationUpgradeFieldLabel": "集成版本", + "xpack.fleet.settings.invalidYamlFormatErrorMessage": "YAML 无效:{reason}", + "xpack.fleet.settings.kibanaUrlDifferentPathOrProtocolError": "对于每个 URL,协议和路径必须相同", + "xpack.fleet.settings.kibanaUrlEmptyError": "至少需要一个 URL", + "xpack.fleet.settings.kibanaUrlError": "URL 无效", + "xpack.fleet.settings.kibanaUrlLabel": "Kibana URL", + "xpack.fleet.settings.saveButtonLabel": "保存设置", + "xpack.fleet.settings.success.message": "设置已保存", + "xpack.fleet.setupPage.apiKeyServiceLink": "API 密钥服务", + "xpack.fleet.setupPage.elasticsearchApiKeyFlagText": "{apiKeyLink}。将 {apiKeyFlag} 莞罎为 {true}。", + "xpack.fleet.setupPage.elasticsearchSecurityFlagText": "{esSecurityLink}。将 {securityFlag} 莞罎为 {true}。", + "xpack.fleet.setupPage.elasticsearchSecurityLink": "Elasticsearch 安全", + "xpack.fleet.setupPage.enableCentralManagement": "创建用户并启用集中管理", + "xpack.fleet.setupPage.enableText": "集中管理需要可以创建 API 密钥并写入到 logs-* 和 metrics-* 的 Elastic 用户。", + "xpack.fleet.setupPage.enableTitle": "寚 Elastic 代理启用集中管理", + "xpack.fleet.setupPage.encryptionKeyFlagText": "{encryptionKeyLink}。将 {keyFlag} 设置为至少 32 个字符的字母数字值。", + "xpack.fleet.setupPage.gettingStartedLink": "入门", + "xpack.fleet.setupPage.gettingStartedText": "有关更多信息,请阅读我们的{link}指南。", + "xpack.fleet.setupPage.kibanaEncryptionLink": "Kibana 加密密钥", + "xpack.fleet.setupPage.kibanaSecurityLink": "Kibana 安全性", + "xpack.fleet.setupPage.missingRequirementsCalloutDescription": "茁寚 Elastic 代理使用集中管理,请启用下面的 Elasticsearch 和 Kibana 安全功能。", + "xpack.fleet.setupPage.missingRequirementsCalloutTitle": "缺失安全性要求", + "xpack.fleet.setupPage.missingRequirementsElasticsearchTitle": "在 Elasticsearch 策略中,启用:", + "xpack.fleet.setupPage.missingRequirementsKibanaTitle": "在 Kibana 策略中,启用:", + "xpack.fleet.setupPage.tlsFlagText": "{kibanaSecurityLink}。将 {securityFlag} 莞罎为 {true}。出于开发目的,作为非安全的备用方案可以通过将 {tlsFlag} 莞罎为 {true} 来禁用 {tlsLink}。", + "xpack.fleet.setupPage.tlsLink": "TLS", + "xpack.fleet.unenrollAgents.cancelButtonLabel": "取消", + "xpack.fleet.unenrollAgents.confirmMultipleButtonLabel": "取消注册 {count} 个代理", + "xpack.fleet.unenrollAgents.confirmSingleButtonLabel": "取消注册代理", + "xpack.fleet.unenrollAgents.deleteMultipleDescription": "此操作将从 Fleet 中移除多个代理,并防止采集新数据。将不会影响任何已由这些代理发送的数据。此操作无法撤消。", + "xpack.fleet.unenrollAgents.deleteSingleDescription": "此操作将从 Fleet 中移除“{hostName}”上运行的选定代理。由该代理发送的任何数据将不会被删除。此操作无法撤消。", + "xpack.fleet.unenrollAgents.deleteSingleTitle": "取消注册代理", + "xpack.fleet.unenrollAgents.fatalErrorNotificationTitle": "取消注册{count, plural, one {代理} other {代理}}时出错", + "xpack.fleet.unenrollAgents.forceDeleteMultipleTitle": "取消注册 {count} 个代理", + "xpack.fleet.unenrollAgents.forceUnenrollCheckboxLabel": "立即移除{count, plural, one {代理} other {代理}}。不用等待代理发送任何最终数据。", + "xpack.fleet.unenrollAgents.forceUnenrollLegendText": "强制取消注册{count, plural, one {代理} other {代理}}", + "xpack.fleet.unenrollAgents.successForceMultiNotificationTitle": "代理已取消注册", + "xpack.fleet.unenrollAgents.successForceSingleNotificationTitle": "代理已取消注册", + "xpack.fleet.unenrollAgents.successMultiNotificationTitle": "正在取消注册代理", + "xpack.fleet.unenrollAgents.successSingleNotificationTitle": "正在取消注册代理", + "xpack.fleet.upgradeAgents.cancelButtonLabel": "取消", + "xpack.fleet.upgradeAgents.confirmMultipleButtonLabel": "升级 {count} 个代理", + "xpack.fleet.upgradeAgents.confirmSingleButtonLabel": "升级代理", + "xpack.fleet.upgradeAgents.deleteMultipleTitle": "升级 {count} 个代理", + "xpack.fleet.upgradeAgents.deleteSingleTitle": "升级代理", + "xpack.fleet.upgradeAgents.fatalErrorNotificationTitle": "升级{count, plural, one {代理} other {代理}}时出错", + "xpack.fleet.upgradeAgents.successMultiNotificationTitle": "正在升级代理", + "xpack.fleet.upgradeAgents.successSingleNotificationTitle": "正在升级代理", + "xpack.fleet.upgradeAgents.upgradeMultipleDescription": "此操作会将多个代理升级到版本 {version}。此操作无法撤消。是否确定要继续?", + "xpack.fleet.upgradeAgents.upgradeSingleDescription": "此操作会将“{hostName}”上运行的选定代理升级到版本 {version}。此操作无法撤消。是否确定要继续?", "xpack.globalSearch.find.invalidLicenseError": "GlobalSearch API 已禁用,因为许可状态无效:{errorMessage}", "xpack.globalSearchBar.searchBar.mobileSearchButtonAriaLabel": "全站点搜索", "xpack.globalSearchBar.searchBar.noResults": "尝试搜索应用程序、仪表板和可视化等。", @@ -8512,7 +9084,6 @@ "xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeIndexExplanationText": "使索引只读,并最大限度减小其内存占用。", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeText": "冻结", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel": "设置副本", - "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.allocationFieldLabel": "数据层选项", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.helpText": "根据节点属性移动数据。", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.input": "定制", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.helpText": "将数据移到冷层中的节点。", @@ -8576,7 +9147,6 @@ "xpack.indexLifecycleMgmt.editPolicy.nameLabel": "名称", "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.customOption.description": "使用节点属性控制分片分配。{learnMoreLink}。", "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption": "不要修改分配配置", - "xpack.indexLifecycleMgmt.editPolicy.nodeAllocationLabel": "选择节点属性", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesLoadingFailedTitle": "无法加载节点属性", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingLabel": "未配置定制节点属性", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesReloadButton": "重试", @@ -8694,7 +9264,6 @@ "xpack.indexLifecycleMgmt.indexMgmtFilter.managedLabel": "受管", "xpack.indexLifecycleMgmt.indexMgmtFilter.unmanagedLabel": "未受管", "xpack.indexLifecycleMgmt.indexMgmtFilter.warmLabel": "渊", - "xpack.indexLifecycleMgmt.indexPriorityLabel": "索引优先级", "xpack.indexLifecycleMgmt.learnMore": "了解详情", "xpack.indexLifecycleMgmt.licenseCheckErrorMessage": "许可证检查失败", "xpack.indexLifecycleMgmt.nodeAttrDetails.hostField": "主机", @@ -9631,580 +10200,6 @@ "xpack.infra.waffle.unableToSelectMetricErrorTitle": "无法选择指标选项或指标值。", "xpack.infra.waffleTime.autoRefreshButtonLabel": "自动刷新", "xpack.infra.waffleTime.stopRefreshingButtonLabel": "停止刷新", - "xpack.ingestManager.agentBulkActions.agentsSelected": "已选择 {count, plural, one {# 个代理} other {# 个代理}}", - "xpack.ingestManager.agentBulkActions.clearSelection": "清除所选内容", - "xpack.ingestManager.agentBulkActions.reassignPolicy": "分配到新策略", - "xpack.ingestManager.agentBulkActions.selectAll": "选择所有页面上的所有内容", - "xpack.ingestManager.agentBulkActions.totalAgents": "正在显示 {count, plural, one {# 个代理} other {# 个代理}}", - "xpack.ingestManager.agentBulkActions.totalAgentsWithLimit": "正在显示 {count} 个代理(共 {total} 个)", - "xpack.ingestManager.agentBulkActions.unenrollAgents": "取消注册代理", - "xpack.ingestManager.agentBulkActions.upgradeAgents": "升级代理", - "xpack.ingestManager.agentDetails.actionsButton": "操作", - "xpack.ingestManager.agentDetails.agentDetailsTitle": "代理“{id}”", - "xpack.ingestManager.agentDetails.agentNotFoundErrorDescription": "找不到代理 ID {agentId}", - "xpack.ingestManager.agentDetails.agentNotFoundErrorTitle": "未找到代理", - "xpack.ingestManager.agentDetails.agentPolicyLabel": "代理策略", - "xpack.ingestManager.agentDetails.agentVersionLabel": "代理版本", - "xpack.ingestManager.agentDetails.hostIdLabel": "代理 ID", - "xpack.ingestManager.agentDetails.hostNameLabel": "主机名", - "xpack.ingestManager.agentDetails.localMetadataSectionSubtitle": "本地元数据", - "xpack.ingestManager.agentDetails.metadataSectionTitle": "元数据", - "xpack.ingestManager.agentDetails.platformLabel": "平台", - "xpack.ingestManager.agentDetails.policyLabel": "策略", - "xpack.ingestManager.agentDetails.releaseLabel": "代理发行版", - "xpack.ingestManager.agentDetails.statusLabel": "状态", - "xpack.ingestManager.agentDetails.subTabs.activityLogTab": "活动日志", - "xpack.ingestManager.agentDetails.subTabs.detailsTab": "代理详情", - "xpack.ingestManager.agentDetails.unexceptedErrorTitle": "加载代理时出错", - "xpack.ingestManager.agentDetails.upgradeAvailableTooltip": "升级可用", - "xpack.ingestManager.agentDetails.userProvidedMetadataSectionSubtitle": "用户提供的元数据", - "xpack.ingestManager.agentDetails.versionLabel": "代理版本", - "xpack.ingestManager.agentDetails.viewAgentListTitle": "查看所有代理", - "xpack.ingestManager.agentEnrollment.agentDescription": "将 Elastic 代理添加到您的主机,以收集数据并将其发送到 Elastic Stack。", - "xpack.ingestManager.agentEnrollment.agentsNotInitializedText": "注册代理前,请{link}。", - "xpack.ingestManager.agentEnrollment.cancelButtonLabel": "取消", - "xpack.ingestManager.agentEnrollment.continueButtonLabel": "睧睭", - "xpack.ingestManager.agentEnrollment.copyPolicyButton": "复制到剪贴板", - "xpack.ingestManager.agentEnrollment.copyRunInstructionsButton": "复制到剪贴板", - "xpack.ingestManager.agentEnrollment.downloadDescription": "可从 Elastic 代理下载页面下载代理二进制文件及其验证签名。", - "xpack.ingestManager.agentEnrollment.downloadLink": "前往下载页面", - "xpack.ingestManager.agentEnrollment.downloadPolicyButton": "下载策略", - "xpack.ingestManager.agentEnrollment.enrollFleetTabLabel": "在 Fleet 中注册", - "xpack.ingestManager.agentEnrollment.enrollStandaloneTabLabel": "独立运行", - "xpack.ingestManager.agentEnrollment.flyoutTitle": "添加代理", - "xpack.ingestManager.agentEnrollment.goToDataStreamsLink": "数据流", - "xpack.ingestManager.agentEnrollment.managedDescription": "在 Fleet 中注册 Elastic 代理,以便自动部署更新并集中管理该代理。", - "xpack.ingestManager.agentEnrollment.setUpAgentsLink": "为 Elastic 代理设置集中管理", - "xpack.ingestManager.agentEnrollment.standaloneDescription": "独立运行 Elastic 代理,以在安装代理的主机上手动配置和更新代理。", - "xpack.ingestManager.agentEnrollment.stepCheckForDataDescription": "该代理应该开始发送数据。前往 {link} 以查看您的数据。", - "xpack.ingestManager.agentEnrollment.stepCheckForDataTitle": "检查数据", - "xpack.ingestManager.agentEnrollment.stepChooseAgentPolicyTitle": "选择代理策略", - "xpack.ingestManager.agentEnrollment.stepConfigureAgentDescription": "在安装 Elastic 代理的主机上将此策略复制到 {fileName}。在 {fileName} 的 {outputSection} 部分中修改 {ESUsernameVariable} 和 {ESPasswordVariable},以使用您的 Elasticsearch 凭据。", - "xpack.ingestManager.agentEnrollment.stepConfigureAgentTitle": "配置代理", - "xpack.ingestManager.agentEnrollment.stepDownloadAgentTitle": "将 Elastic 代理下载到您的主机", - "xpack.ingestManager.agentEnrollment.stepEnrollAndRunAgentTitle": "注册并启动 Elastic 代理", - "xpack.ingestManager.agentEnrollment.stepRunAgentDescription": "从代理目录运行此命令,以安装、注册并启动 Elastic 代理。您可以重复使用此命令在多个主机上设置代理。需要管理员权限。", - "xpack.ingestManager.agentEnrollment.stepRunAgentTitle": "启动代理", - "xpack.ingestManager.agentEventsList.collapseDetailsAriaLabel": "隐藏详情", - "xpack.ingestManager.agentEventsList.expandDetailsAriaLabel": "显示详情", - "xpack.ingestManager.agentEventsList.messageColumnTitle": "月息", - "xpack.ingestManager.agentEventsList.messageDetailsTitle": "月息", - "xpack.ingestManager.agentEventsList.payloadDetailsTitle": "负载", - "xpack.ingestManager.agentEventsList.refreshButton": "刷新", - "xpack.ingestManager.agentEventsList.searchPlaceholderText": "搜索活动日志", - "xpack.ingestManager.agentEventsList.subtypeColumnTitle": "子类型", - "xpack.ingestManager.agentEventsList.timestampColumnTitle": "时间戳", - "xpack.ingestManager.agentEventsList.typeColumnTitle": "类型", - "xpack.ingestManager.agentEventSubtype.acknowledgedLabel": "塲祎莤", - "xpack.ingestManager.agentEventSubtype.dataDumpLabel": "数据转储", - "xpack.ingestManager.agentEventSubtype.degradedLabel": "已降级", - "xpack.ingestManager.agentEventSubtype.failedLabel": "夹贼", - "xpack.ingestManager.agentEventSubtype.inProgressLabel": "进行中", - "xpack.ingestManager.agentEventSubtype.policyLabel": "策略", - "xpack.ingestManager.agentEventSubtype.runningLabel": "正在运行", - "xpack.ingestManager.agentEventSubtype.startingLabel": "正在启动", - "xpack.ingestManager.agentEventSubtype.stoppedLabel": "已停止", - "xpack.ingestManager.agentEventSubtype.stoppingLabel": "正在停止", - "xpack.ingestManager.agentEventSubtype.unknownLabel": "未知", - "xpack.ingestManager.agentEventSubtype.updatingLabel": "正在更新", - "xpack.ingestManager.agentEventType.actionLabel": "操作", - "xpack.ingestManager.agentEventType.actionResultLabel": "操作结果", - "xpack.ingestManager.agentEventType.errorLabel": "错误", - "xpack.ingestManager.agentEventType.stateLabel": "状态", - "xpack.ingestManager.agentHealth.checkInTooltipText": "上次签入时间 {lastCheckIn}", - "xpack.ingestManager.agentHealth.degradedStatusText": "已降级", - "xpack.ingestManager.agentHealth.enrollingStatusText": "正在注册", - "xpack.ingestManager.agentHealth.errorStatusText": "错误", - "xpack.ingestManager.agentHealth.inactiveStatusText": "非活动", - "xpack.ingestManager.agentHealth.noCheckInTooltipText": "未签入", - "xpack.ingestManager.agentHealth.offlineStatusText": "脱机", - "xpack.ingestManager.agentHealth.onlineStatusText": "联机", - "xpack.ingestManager.agentHealth.unenrollingStatusText": "正在取消注册", - "xpack.ingestManager.agentHealth.updatingStatusText": "正在更新", - "xpack.ingestManager.agentHealth.warningStatusText": "错误", - "xpack.ingestManager.agentList.actionsColumnTitle": "操作", - "xpack.ingestManager.agentList.addButton": "添加代理", - "xpack.ingestManager.agentList.agentUpgradeLabel": "升级可用", - "xpack.ingestManager.agentList.clearFiltersLinkText": "清除筛选", - "xpack.ingestManager.agentList.enrollButton": "添加代理", - "xpack.ingestManager.agentList.forceUnenrollOneButton": "强制取消注册", - "xpack.ingestManager.agentList.hostColumnTitle": "主机", - "xpack.ingestManager.agentList.lastCheckinTitle": "上次活动", - "xpack.ingestManager.agentList.loadingAgentsMessage": "正在加载代理……", - "xpack.ingestManager.agentList.noAgentsPrompt": "未注册任何代理", - "xpack.ingestManager.agentList.noFilteredAgentsPrompt": "未找到任何代理。{clearFiltersLink}", - "xpack.ingestManager.agentList.outOfDateLabel": "过时", - "xpack.ingestManager.agentList.policyColumnTitle": "代理策略", - "xpack.ingestManager.agentList.policyFilterText": "代理策略", - "xpack.ingestManager.agentList.reassignActionText": "分配到新策略", - "xpack.ingestManager.agentList.revisionNumber": "俎莢 {revNumber}", - "xpack.ingestManager.agentList.showInactiveSwitchLabel": "非活动", - "xpack.ingestManager.agentList.showUpgradeableFilterLabel": "升级可用", - "xpack.ingestManager.agentList.statusColumnTitle": "状态", - "xpack.ingestManager.agentList.statusErrorFilterText": "错误", - "xpack.ingestManager.agentList.statusFilterText": "状态", - "xpack.ingestManager.agentList.statusOfflineFilterText": "脱机", - "xpack.ingestManager.agentList.statusOnlineFilterText": "联机", - "xpack.ingestManager.agentList.statusUpdatingFilterText": "正在更新", - "xpack.ingestManager.agentList.unenrollOneButton": "取消注册代理", - "xpack.ingestManager.agentList.upgradeOneButton": "升级代理", - "xpack.ingestManager.agentList.versionTitle": "版本", - "xpack.ingestManager.agentList.viewActionText": "查看代理", - "xpack.ingestManager.agentListStatus.errorLabel": "错误", - "xpack.ingestManager.agentListStatus.offlineLabel": "脱机", - "xpack.ingestManager.agentListStatus.onlineLabel": "联机", - "xpack.ingestManager.agentListStatus.totalLabel": "代理", - "xpack.ingestManager.agentPolicy.confirmModalCalloutDescription": "Fleet 检测到您的部分代理已在使用选定代理策略 {policyName}。由于此操作,Fleet 会将更新部署到使用此策略的所有代理。", - "xpack.ingestManager.agentPolicy.confirmModalCalloutTitle": "此操作将更新 {agentCount, plural, one {# 个代理} other {# 个代理}}", - "xpack.ingestManager.agentPolicy.confirmModalCancelButtonLabel": "取消", - "xpack.ingestManager.agentPolicy.confirmModalConfirmButtonLabel": "保存并部署更改", - "xpack.ingestManager.agentPolicy.confirmModalDescription": "此操作无法撤消。是否确定要继续?", - "xpack.ingestManager.agentPolicy.confirmModalTitle": "保存并部署更改", - "xpack.ingestManager.agentPolicy.linkedAgentCountText": "{count, plural, one {# 个代理} other {# 个代理}}", - "xpack.ingestManager.agentPolicyActionMenu.buttonText": "操作", - "xpack.ingestManager.agentPolicyActionMenu.copyPolicyActionText": "复制策略", - "xpack.ingestManager.agentPolicyActionMenu.enrollAgentActionText": "添加代理", - "xpack.ingestManager.agentPolicyActionMenu.viewPolicyText": "查看策略", - "xpack.ingestManager.agentPolicyForm.advancedOptionsToggleLabel": "高级选项", - "xpack.ingestManager.agentPolicyForm.descriptionFieldLabel": "描述", - "xpack.ingestManager.agentPolicyForm.descriptionFieldPlaceholder": "此策略将如何使用?", - "xpack.ingestManager.agentPolicyForm.monitoringDescription": "收集有关代理的数据,用于调试和跟踪性能。", - "xpack.ingestManager.agentPolicyForm.monitoringLabel": "代理监测", - "xpack.ingestManager.agentPolicyForm.monitoringLogsFieldLabel": "收集代理日志", - "xpack.ingestManager.agentPolicyForm.monitoringLogsTooltipText": "从使用此策略的 Elastic 代理收集日志。", - "xpack.ingestManager.agentPolicyForm.monitoringMetricsFieldLabel": "收集代理指标", - "xpack.ingestManager.agentPolicyForm.monitoringMetricsTooltipText": "从使用此策略的 Elastic 代理收集指标。", - "xpack.ingestManager.agentPolicyForm.nameFieldLabel": "名称", - "xpack.ingestManager.agentPolicyForm.nameFieldPlaceholder": "选择名称", - "xpack.ingestManager.agentPolicyForm.nameRequiredErrorMessage": "“代理策略名称”必填。", - "xpack.ingestManager.agentPolicyForm.namespaceFieldDescription": "将默认命名空间应用于使用此策略的集成。集成可以指定自己的命名空间。", - "xpack.ingestManager.agentPolicyForm.namespaceFieldLabel": "默认命名空间", - "xpack.ingestManager.agentPolicyForm.systemMonitoringFieldLabel": "系统监测", - "xpack.ingestManager.agentPolicyForm.systemMonitoringText": "收集系统指标", - "xpack.ingestManager.agentPolicyForm.systemMonitoringTooltipText": "启用此选项可使用收集系统指标和信息的集成启动您的策略。", - "xpack.ingestManager.agentPolicyList.actionsColumnTitle": "操作", - "xpack.ingestManager.agentPolicyList.addButton": "创建代理策略", - "xpack.ingestManager.agentPolicyList.agentsColumnTitle": "代理", - "xpack.ingestManager.agentPolicyList.clearFiltersLinkText": "清除筛选", - "xpack.ingestManager.agentPolicyList.descriptionColumnTitle": "描述", - "xpack.ingestManager.agentPolicyList.loadingAgentPoliciesMessage": "正在加载代理策略…...", - "xpack.ingestManager.agentPolicyList.nameColumnTitle": "名称", - "xpack.ingestManager.agentPolicyList.noAgentPoliciesPrompt": "无代理策略", - "xpack.ingestManager.agentPolicyList.noFilteredAgentPoliciesPrompt": "找不到任何代理策略。{clearFiltersLink}", - "xpack.ingestManager.agentPolicyList.packagePoliciesCountColumnTitle": "集成", - "xpack.ingestManager.agentPolicyList.pageSubtitle": "使用代理策略管理代理及其收集的数据。", - "xpack.ingestManager.agentPolicyList.pageTitle": "代理策略", - "xpack.ingestManager.agentPolicyList.reloadAgentPoliciesButtonText": "重新加载", - "xpack.ingestManager.agentPolicyList.revisionNumber": "修订版 {revNumber}", - "xpack.ingestManager.agentPolicyList.updatedOnColumnTitle": "上次更新时间", - "xpack.ingestManager.agentReassignPolicy.cancelButtonLabel": "取消", - "xpack.ingestManager.agentReassignPolicy.continueButtonLabel": "分配策略", - "xpack.ingestManager.agentReassignPolicy.flyoutDescription": "选择要将选定{count, plural, one {代理} other {代理}}分配到的新代理策略。", - "xpack.ingestManager.agentReassignPolicy.flyoutTitle": "分配新代理策略", - "xpack.ingestManager.agentReassignPolicy.policyDescription": "选定代理策略将收集 {count, plural, one {{countValue} 个集成} other {{countValue} 个集成}}的数据:", - "xpack.ingestManager.agentReassignPolicy.selectPolicyLabel": "代理策略", - "xpack.ingestManager.agentReassignPolicy.successSingleNotificationTitle": "代理策略已重新分配", - "xpack.ingestManager.agents.pageSubtitle": "管理策略更新并将其部署到一组任意大小的代理。", - "xpack.ingestManager.agents.pageTitle": "代理", - "xpack.ingestManager.alphaMessageDescription": "不推荐在生产环境中使用采集管理器。", - "xpack.ingestManager.alphaMessageLinkText": "查看更多详情。", - "xpack.ingestManager.alphaMessageTitle": "公测版", - "xpack.ingestManager.alphaMessaging.docsLink": "文档", - "xpack.ingestManager.alphaMessaging.feedbackText": "阅读我们的{docsLink}或前往我们的{forumLink},以了解问题或提供反馈。", - "xpack.ingestManager.alphaMessaging.flyoutTitle": "关于本版本", - "xpack.ingestManager.alphaMessaging.forumLink": "讨论论坛", - "xpack.ingestManager.alphaMessaging.introText": "采集管理器仍处于开发状态,不适用于生产环境。此公测版用于用户测试采集管理器和新 Elastic 代理并提供相关反馈。此插件不受支持 SLA 的约束。", - "xpack.ingestManager.alphaMessging.closeFlyoutLabel": "关闭", - "xpack.ingestManager.appNavigation.agentsLinkText": "代理", - "xpack.ingestManager.appNavigation.dataStreamsLinkText": "数据流", - "xpack.ingestManager.appNavigation.epmLinkText": "集成", - "xpack.ingestManager.appNavigation.overviewLinkText": "概览", - "xpack.ingestManager.appNavigation.policiesLinkText": "策略", - "xpack.ingestManager.appNavigation.sendFeedbackButton": "发送反馈", - "xpack.ingestManager.appNavigation.settingsButton": "莞罎", - "xpack.ingestManager.appTitle": "Fleet", - "xpack.ingestManager.betaBadge.labelText": "公测版", - "xpack.ingestManager.betaBadge.tooltipText": "不推荐在生产环境中使用此插件。请在我们讨论论坛中报告错误。", - "xpack.ingestManager.breadcrumbs.addPackagePolicyPageTitle": "添加集成", - "xpack.ingestManager.breadcrumbs.agentsPageTitle": "代理", - "xpack.ingestManager.breadcrumbs.allIntegrationsPageTitle": "全部", - "xpack.ingestManager.breadcrumbs.appTitle": "Fleet", - "xpack.ingestManager.breadcrumbs.datastreamsPageTitle": "数据流", - "xpack.ingestManager.breadcrumbs.editPackagePolicyPageTitle": "编辑集成", - "xpack.ingestManager.breadcrumbs.enrollmentTokensPageTitle": "注册令牌", - "xpack.ingestManager.breadcrumbs.installedIntegrationsPageTitle": "已安装", - "xpack.ingestManager.breadcrumbs.integrationsPageTitle": "集成", - "xpack.ingestManager.breadcrumbs.overviewPageTitle": "概览", - "xpack.ingestManager.breadcrumbs.policiesPageTitle": "策略", - "xpack.ingestManager.copyAgentPolicy.confirmModal.cancelButtonLabel": "取消", - "xpack.ingestManager.copyAgentPolicy.confirmModal.confirmButtonLabel": "复制策略", - "xpack.ingestManager.copyAgentPolicy.confirmModal.copyPolicyPrompt": "为您的新代理策略选择名称和描述。", - "xpack.ingestManager.copyAgentPolicy.confirmModal.copyPolicyTitle": "复制代理策略“{name}”", - "xpack.ingestManager.copyAgentPolicy.confirmModal.defaultNewPolicyName": "{name}(副本)", - "xpack.ingestManager.copyAgentPolicy.confirmModal.newDescriptionLabel": "描述", - "xpack.ingestManager.copyAgentPolicy.confirmModal.newNameLabel": "新策略名称", - "xpack.ingestManager.copyAgentPolicy.failureNotificationTitle": "复制代理策略“{id}”时出错", - "xpack.ingestManager.copyAgentPolicy.fatalErrorNotificationTitle": "复制代理策略时出错", - "xpack.ingestManager.copyAgentPolicy.successNotificationTitle": "代理策略已复制", - "xpack.ingestManager.createAgentPolicy.cancelButtonLabel": "取消", - "xpack.ingestManager.createAgentPolicy.errorNotificationTitle": "无法创建代理策略", - "xpack.ingestManager.createAgentPolicy.flyoutTitle": "创建代理策略", - "xpack.ingestManager.createAgentPolicy.flyoutTitleDescription": "代理策略用于管理一组代理的设置。您可以将集成添加到代理策略,以指定代理收集的数据。编辑代理策略时,可以使用 Fleet 将更新部署到一组指定代理。", - "xpack.ingestManager.createAgentPolicy.submitButtonLabel": "创建代理策略", - "xpack.ingestManager.createAgentPolicy.successNotificationTitle": "代理策略“{name}”已创建", - "xpack.ingestManager.createPackagePolicy.addedNotificationMessage": "Fleet 会将更新部署到所有使用策略“{agentPolicyName}”的代理。", - "xpack.ingestManager.createPackagePolicy.addedNotificationTitle": "“{packagePolicyName}”集成已添加。", - "xpack.ingestManager.createPackagePolicy.agentPolicyNameLabel": "代理策略", - "xpack.ingestManager.createPackagePolicy.cancelButton": "取消", - "xpack.ingestManager.createPackagePolicy.cancelLinkText": "取消", - "xpack.ingestManager.createPackagePolicy.errorOnSaveText": "您的集成策略有错误。请在保存前修复这些错误。", - "xpack.ingestManager.createPackagePolicy.pageDescriptionfromPackage": "按照以下说明将此集成添加到代理策略。", - "xpack.ingestManager.createPackagePolicy.pageDescriptionfromPolicy": "为选定代理策略配置集成。", - "xpack.ingestManager.createPackagePolicy.pageTitle": "添加集成", - "xpack.ingestManager.createPackagePolicy.pageTitleWithPackageName": "添加 {packageName} 集成", - "xpack.ingestManager.createPackagePolicy.saveButton": "保存集成", - "xpack.ingestManager.createPackagePolicy.stepConfigure.advancedOptionsToggleLinkText": "高级选项", - "xpack.ingestManager.createPackagePolicy.stepConfigure.errorCountText": "{count, plural, one {# 个错误} other {# 个错误}}", - "xpack.ingestManager.createPackagePolicy.stepConfigure.hideStreamsAriaLabel": "隐藏 {type} 输入", - "xpack.ingestManager.createPackagePolicy.stepConfigure.inputSettingsDescription": "以下设置适用于下面的所有输入。", - "xpack.ingestManager.createPackagePolicy.stepConfigure.inputSettingsTitle": "莞罎", - "xpack.ingestManager.createPackagePolicy.stepConfigure.inputVarFieldOptionalLabel": "可选", - "xpack.ingestManager.createPackagePolicy.stepConfigure.integrationSettingsSectionDescription": "选择有助于确定如何使用此集成的名称和描述。", - "xpack.ingestManager.createPackagePolicy.stepConfigure.integrationSettingsSectionTitle": "集成设置", - "xpack.ingestManager.createPackagePolicy.stepConfigure.noPolicyOptionsMessage": "没有可配置的内容", - "xpack.ingestManager.createPackagePolicy.stepConfigure.packagePolicyDescriptionInputLabel": "描述", - "xpack.ingestManager.createPackagePolicy.stepConfigure.packagePolicyNameInputLabel": "集成名称", - "xpack.ingestManager.createPackagePolicy.stepConfigure.packagePolicyNamespaceInputLabel": "命名空间", - "xpack.ingestManager.createPackagePolicy.stepConfigure.showStreamsAriaLabel": "昞示 {type} 输入", - "xpack.ingestManager.createPackagePolicy.stepConfigure.toggleAdvancedOptionsButtonText": "高级选项", - "xpack.ingestManager.createPackagePolicy.stepConfigurePackagePolicyTitle": "配置集成", - "xpack.ingestManager.createPackagePolicy.stepSelectAgentPolicyTitle": "选择代理策略", - "xpack.ingestManager.createPackagePolicy.stepSelectPackage.errorLoadingPackagesTitle": "加载集成时出错", - "xpack.ingestManager.createPackagePolicy.stepSelectPackage.errorLoadingPolicyTitle": "加载代理策略信息时出错", - "xpack.ingestManager.createPackagePolicy.stepSelectPackage.errorLoadingSelectedPackageTitle": "加载选定集成时出错", - "xpack.ingestManager.createPackagePolicy.stepSelectPackage.filterPackagesInputPlaceholder": "搜索集成", - "xpack.ingestManager.createPackagePolicy.stepSelectPackageTitle": "选择集成", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.addButton": "创建代理策略", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.agentPolicyAgentsCountText": "{count, plural, one {# 个代理} other {# 个代理}}已注册", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.agentPolicyAgentsDescriptionText": "{count, plural, one {# 个代理} other {# 个代理}}已注册到选定代理策略中。", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.agentPolicyLabel": "代理策略", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.agentPolicyPlaceholderText": "选择要将此集成添加到的代理策略", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.errorLoadingAgentPoliciesTitle": "加载代理策略时出错", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.errorLoadingPackageTitle": "加载软件包信息时出错", - "xpack.ingestManager.createPackagePolicy.StepSelectPolicy.errorLoadingSelectedAgentPolicyTitle": "加载选定代理策略时出错", - "xpack.ingestManager.dataStreamList.actionsColumnTitle": "操作", - "xpack.ingestManager.dataStreamList.datasetColumnTitle": "数据集", - "xpack.ingestManager.dataStreamList.integrationColumnTitle": "集成", - "xpack.ingestManager.dataStreamList.lastActivityColumnTitle": "上次活动", - "xpack.ingestManager.dataStreamList.loadingDataStreamsMessage": "正在加载数据流……", - "xpack.ingestManager.dataStreamList.namespaceColumnTitle": "命名空间", - "xpack.ingestManager.dataStreamList.noDataStreamsPrompt": "无数据流", - "xpack.ingestManager.dataStreamList.noFilteredDataStreamsMessage": "找不到匹配的数据流", - "xpack.ingestManager.dataStreamList.pageSubtitle": "管理您的代理创建的数据。", - "xpack.ingestManager.dataStreamList.pageTitle": "数据流", - "xpack.ingestManager.dataStreamList.reloadDataStreamsButtonText": "重新加载", - "xpack.ingestManager.dataStreamList.searchPlaceholderTitle": "筛选数据流", - "xpack.ingestManager.dataStreamList.sizeColumnTitle": "大小", - "xpack.ingestManager.dataStreamList.typeColumnTitle": "类型", - "xpack.ingestManager.dataStreamList.viewDashboardActionText": "查看仪表板", - "xpack.ingestManager.dataStreamList.viewDashboardsActionText": "查看仪表板", - "xpack.ingestManager.dataStreamList.viewDashboardsPanelTitle": "查看仪表板", - "xpack.ingestManager.defaultSearchPlaceholderText": "搜索", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.affectedAgentsMessage": "{agentsCount, plural, one {# 个代理} other {# 个代理}}已分配到此代理策略。在删除此策略前取消分配这些代理。", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.affectedAgentsTitle": "在用的策略", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.cancelButtonLabel": "取消", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.confirmButtonLabel": "删除策略", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.deletePolicyTitle": "删除此代理策略?", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.irreversibleMessage": "此操作无法撤消。", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.loadingAgentsCountMessage": "正在检查受影响的代理数量……", - "xpack.ingestManager.deleteAgentPolicy.confirmModal.loadingButtonLabel": "正在加载……", - "xpack.ingestManager.deleteAgentPolicy.failureSingleNotificationTitle": "删除代理策略“{id}”时出错", - "xpack.ingestManager.deleteAgentPolicy.fatalErrorNotificationTitle": "删除代理策略时出错", - "xpack.ingestManager.deleteAgentPolicy.successSingleNotificationTitle": "已删除代理策略“{id}”", - "xpack.ingestManager.deletePackagePolicy.confirmModal.affectedAgentsMessage": "Fleet 检测到您的部分代理已在使用 {agentPolicyName}。", - "xpack.ingestManager.deletePackagePolicy.confirmModal.affectedAgentsTitle": "此操作将影响 {agentsCount} 个{agentsCount, plural, one {代理} other {代理}}。", - "xpack.ingestManager.deletePackagePolicy.confirmModal.cancelButtonLabel": "取消", - "xpack.ingestManager.deletePackagePolicy.confirmModal.confirmButtonLabel": "删除{agentPoliciesCount, plural, one {集成} other {集成}}", - "xpack.ingestManager.deletePackagePolicy.confirmModal.deleteMultipleTitle": "删除 {count, plural, one {集成} other {# 个集成}}?", - "xpack.ingestManager.deletePackagePolicy.confirmModal.generalMessage": "此操作无法撤消。是否确定要继续?", - "xpack.ingestManager.deletePackagePolicy.confirmModal.loadingAgentsCountMessage": "正在检查受影响的代理……", - "xpack.ingestManager.deletePackagePolicy.confirmModal.loadingButtonLabel": "正在加载……", - "xpack.ingestManager.deletePackagePolicy.failureMultipleNotificationTitle": "删除 {count} 个集成时出错", - "xpack.ingestManager.deletePackagePolicy.failureSingleNotificationTitle": "删除集成“{id}”时出错", - "xpack.ingestManager.deletePackagePolicy.fatalErrorNotificationTitle": "删除集成时出错", - "xpack.ingestManager.deletePackagePolicy.successMultipleNotificationTitle": "已删除 {count} 个集成", - "xpack.ingestManager.deletePackagePolicy.successSingleNotificationTitle": "已删除集成“{id}”", - "xpack.ingestManager.disabledSecurityDescription": "必须在 Kibana 和 Elasticsearch 启用安全性,才能使用 Elastic Fleet。", - "xpack.ingestManager.disabledSecurityTitle": "安全性未启用", - "xpack.ingestManager.editAgentPolicy.cancelButtonText": "取消", - "xpack.ingestManager.editAgentPolicy.errorNotificationTitle": "无法更新代理策略", - "xpack.ingestManager.editAgentPolicy.saveButtonText": "保存更改", - "xpack.ingestManager.editAgentPolicy.savingButtonText": "正在保存……", - "xpack.ingestManager.editAgentPolicy.successNotificationTitle": "已成功更新“{name}”设置", - "xpack.ingestManager.editAgentPolicy.unsavedChangesText": "您有未保存的更改", - "xpack.ingestManager.editPackagePolicy.cancelButton": "取消", - "xpack.ingestManager.editPackagePolicy.errorLoadingDataMessage": "加载此集成信息时出错", - "xpack.ingestManager.editPackagePolicy.errorLoadingDataTitle": "加载数据时出错", - "xpack.ingestManager.editPackagePolicy.failedConflictNotificationMessage": "数据已过时。刷新页面以获取最新策略。", - "xpack.ingestManager.editPackagePolicy.failedNotificationTitle": "更新“{packagePolicyName}”时出错", - "xpack.ingestManager.editPackagePolicy.pageDescription": "修改集成设置并将更改部署到选定代理策略。", - "xpack.ingestManager.editPackagePolicy.pageTitle": "编辑集成", - "xpack.ingestManager.editPackagePolicy.pageTitleWithPackageName": "编辑 {packageName} 集成", - "xpack.ingestManager.editPackagePolicy.saveButton": "保存集成", - "xpack.ingestManager.editPackagePolicy.updatedNotificationMessage": "Fleet 会将更新部署到所有使用策略“{agentPolicyName}”的代理", - "xpack.ingestManager.editPackagePolicy.updatedNotificationTitle": "已成功更新“{packagePolicyName}”", - "xpack.ingestManager.enrollemntAPIKeyList.emptyMessage": "未找到任何注册令牌。", - "xpack.ingestManager.enrollemntAPIKeyList.loadingTokensMessage": "正在加载注册令牌......", - "xpack.ingestManager.enrollmentInstructions.descriptionText": "从代理目录运行相应命令,以安装、注册并启动 Elastic 代理。您可以重复使用这些命令在多个主机上设置代理。需要管理员权限。", - "xpack.ingestManager.enrollmentInstructions.linuxMacOSTitle": "Linux、macOS", - "xpack.ingestManager.enrollmentInstructions.moreInstructionsLink": "Elastic 代理文档", - "xpack.ingestManager.enrollmentInstructions.moreInstructionsText": "有关更多说明和选项,请参见 {link}。", - "xpack.ingestManager.enrollmentInstructions.windowsTitle": "Windows", - "xpack.ingestManager.enrollmentStepAgentPolicy.enrollmentTokenSelectLabel": "注册令牌", - "xpack.ingestManager.enrollmentStepAgentPolicy.policySelectAriaLabel": "代理策略", - "xpack.ingestManager.enrollmentStepAgentPolicy.policySelectLabel": "代理策略", - "xpack.ingestManager.enrollmentStepAgentPolicy.showAuthenticationSettingsButton": "身份验证设置", - "xpack.ingestManager.enrollmentTokenDeleteModal.cancelButton": "取消", - "xpack.ingestManager.enrollmentTokenDeleteModal.deleteButton": "撤销注册令牌", - "xpack.ingestManager.enrollmentTokenDeleteModal.description": "确定要撤销 {keyName}?使用此令牌的代理将无法再访问策略或发送数据。 ", - "xpack.ingestManager.enrollmentTokenDeleteModal.title": "撤销注册令牌", - "xpack.ingestManager.enrollmentTokensList.actionsTitle": "操作", - "xpack.ingestManager.enrollmentTokensList.activeTitle": "活动", - "xpack.ingestManager.enrollmentTokensList.createdAtTitle": "创建日期", - "xpack.ingestManager.enrollmentTokensList.hideTokenButtonLabel": "隐藏令牌", - "xpack.ingestManager.enrollmentTokensList.nameTitle": "名称", - "xpack.ingestManager.enrollmentTokensList.newKeyButton": "创建注册令牌", - "xpack.ingestManager.enrollmentTokensList.pageDescription": "创建和撤销注册令牌。注册令牌允许一个或多个代理注册于 Fleet 中并发送数据。", - "xpack.ingestManager.enrollmentTokensList.policyTitle": "代理策略", - "xpack.ingestManager.enrollmentTokensList.revokeTokenButtonLabel": "撤销令牌", - "xpack.ingestManager.enrollmentTokensList.secretTitle": "密钥", - "xpack.ingestManager.enrollmentTokensList.showTokenButtonLabel": "显示令牌", - "xpack.ingestManager.epm.addPackagePolicyButtonText": "添加 {packageName}", - "xpack.ingestManager.epm.assetGroupTitle": "{assetType} 资产", - "xpack.ingestManager.epm.browseAllButtonText": "浏览所有集成", - "xpack.ingestManager.epm.illustrationAltText": "集成的图示", - "xpack.ingestManager.epm.loadingIntegrationErrorTitle": "加载集成详情时出错", - "xpack.ingestManager.epm.packageDetailsNav.overviewLinkText": "概览", - "xpack.ingestManager.epm.packageDetailsNav.packagePoliciesLinkText": "使用情况", - "xpack.ingestManager.epm.packageDetailsNav.settingsLinkText": "莞罎", - "xpack.ingestManager.epm.pageSubtitle": "浏览集成以了解热门应用和服务。", - "xpack.ingestManager.epm.pageTitle": "集成", - "xpack.ingestManager.epm.releaseBadge.betaDescription": "在生产环境中不推荐使用此集成。", - "xpack.ingestManager.epm.releaseBadge.betaLabel": "公测版", - "xpack.ingestManager.epm.releaseBadge.experimentalDescription": "此集成可能有重大更改或将在未来版本中移除。", - "xpack.ingestManager.epm.releaseBadge.experimentalLabel": "实验性", - "xpack.ingestManager.epm.screenshotsTitle": "屏幕截图", - "xpack.ingestManager.epm.updateAvailableTooltip": "有可用更新", - "xpack.ingestManager.epm.versionLabel": "版本", - "xpack.ingestManager.epmList.allFilterLinkText": "全部", - "xpack.ingestManager.epmList.allPackagesFilterLinkText": "全部", - "xpack.ingestManager.epmList.allTabText": "所有集成", - "xpack.ingestManager.epmList.allTitle": "按类别浏览", - "xpack.ingestManager.epmList.installedTabText": "已安装集成", - "xpack.ingestManager.epmList.installedTitle": "已安装集成", - "xpack.ingestManager.epmList.noPackagesFoundPlaceholder": "未找到任何软件包", - "xpack.ingestManager.epmList.searchPackagesPlaceholder": "搜索集成", - "xpack.ingestManager.epmList.updatesAvailableFilterLinkText": "有可用更新", - "xpack.ingestManager.featureCatalogueDescription": "添加并管理您所有的 Elastic 代理和集成。", - "xpack.ingestManager.featureCatalogueTitle": "添加 Elastic 代理", - "xpack.ingestManager.genericActionsMenuText": "打开", - "xpack.ingestManager.homeIntegration.tutorialDirectory.dismissNoticeButtonText": "关闭消息", - "xpack.ingestManager.homeIntegration.tutorialDirectory.noticeText": "通过 Elastic 代理,可以简单统一的方式将日志、指标和其他类型数据的监测添加到主机。不再需要安装多个 Beats 和其他代理,这样将策略部署到整个基础架构更容易也更快速。有关更多信息,请阅读我们的{blogPostLink}。", - "xpack.ingestManager.homeIntegration.tutorialDirectory.noticeText.blogPostLink": "公告博客", - "xpack.ingestManager.homeIntegration.tutorialDirectory.noticeTitle": "{newPrefix}Elastic 代理和采集管理器公测版", - "xpack.ingestManager.homeIntegration.tutorialDirectory.noticeTitle.newPrefix": "新通告:", - "xpack.ingestManager.homeIntegration.tutorialModule.noticeText": "{notePrefix}此模块的较新版本在采集管理器公测版中{availableAsIntegrationLink}。要详细了解代理策略和新的 Elastic 代理,请阅读我们的{blogPostLink}。", - "xpack.ingestManager.homeIntegration.tutorialModule.noticeText.blogPostLink": "公告博客", - "xpack.ingestManager.homeIntegration.tutorialModule.noticeText.integrationLink": "作为集成提供", - "xpack.ingestManager.homeIntegration.tutorialModule.noticeText.notePrefix": "注意:", - "xpack.ingestManager.initializationErrorMessageTitle": "无法初始化 Ingest Manager", - "xpack.ingestManager.integrations.installPackage.installingPackageButtonLabel": "正在安装 {title} 资产", - "xpack.ingestManager.integrations.installPackage.installPackageButtonLabel": "安装 {title} 资产", - "xpack.ingestManager.integrations.packageInstallErrorDescription": "尝试安装此软件包时出现问题。请稍后重试。", - "xpack.ingestManager.integrations.packageInstallErrorTitle": "无法安装 {title} 软件包", - "xpack.ingestManager.integrations.packageInstallSuccessDescription": "已成功安装 {title}", - "xpack.ingestManager.integrations.packageInstallSuccessTitle": "已安装 {title}", - "xpack.ingestManager.integrations.packageUninstallErrorDescription": "尝试卸载此软件包时出现问题。请稍后重试。", - "xpack.ingestManager.integrations.packageUninstallErrorTitle": "无法卸载 {title} 软件包", - "xpack.ingestManager.integrations.packageUninstallSuccessDescription": "已成功卸载 {title}", - "xpack.ingestManager.integrations.packageUninstallSuccessTitle": "已卸载 {title}", - "xpack.ingestManager.integrations.settings.confirmInstallModal.cancelButtonLabel": "取消", - "xpack.ingestManager.integrations.settings.confirmInstallModal.installButtonLabel": "安装 {packageName}", - "xpack.ingestManager.integrations.settings.confirmInstallModal.installCalloutTitle": "此操作将安装 {numOfAssets} 个资产", - "xpack.ingestManager.integrations.settings.confirmInstallModal.installDescription": "Kibana 资产将安装在当前工作区中(默认),仅有权查看此工作区的用户可访问。Elasticsearch 资产为全局安装,所有 Kibana 用户可访问。", - "xpack.ingestManager.integrations.settings.confirmInstallModal.installTitle": "安装 {packageName}", - "xpack.ingestManager.integrations.settings.confirmUninstallModal.cancelButtonLabel": "取消", - "xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallButtonLabel": "卸载 {packageName}", - "xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallCallout.description": "将会移除由此集成创建的 Kibana 和 Elasticsearch 资产。将不会影响代理策略以及您的代理发送的任何数据。", - "xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallCallout.title": "此操作将移除 {numOfAssets} 个资产", - "xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallDescription": "此操作无法撤消。是否确定要继续?", - "xpack.ingestManager.integrations.settings.confirmUninstallModal.uninstallTitle": "卸载 {packageName}", - "xpack.ingestManager.integrations.settings.packageInstallDescription": "安装此集成以设置专用于 {title} 数据的Kibana 和 Elasticsearch 资产。", - "xpack.ingestManager.integrations.settings.packageInstallTitle": "安装 {title}", - "xpack.ingestManager.integrations.settings.packageSettingsTitle": "莞罎", - "xpack.ingestManager.integrations.settings.packageUninstallDescription": "移除此集成安装的 Kibana 和 Elasticsearch 资产。", - "xpack.ingestManager.integrations.settings.packageUninstallNoteDescription.packageUninstallNoteDetail": "{strongNote}{title} 无法卸载,因为存在使用此集成的活动代理。要卸载,请从您的代理策略中移除所有 {title} 集成。", - "xpack.ingestManager.integrations.settings.packageUninstallNoteDescription.packageUninstallNoteLabel": "注意:", - "xpack.ingestManager.integrations.settings.packageUninstallNoteDescription.packageUninstallUninstallableNoteDetail": "{strongNote} {title} 集成默认安装,无法移除。", - "xpack.ingestManager.integrations.settings.packageUninstallTitle": "卸载 {title}", - "xpack.ingestManager.integrations.settings.packageVersionTitle": "{title} 版本", - "xpack.ingestManager.integrations.settings.versionInfo.installedVersion": "已安装版本", - "xpack.ingestManager.integrations.settings.versionInfo.latestVersion": "最新版本", - "xpack.ingestManager.integrations.settings.versionInfo.updatesAvailable": "更新可用", - "xpack.ingestManager.integrations.uninstallPackage.uninstallingPackageButtonLabel": "正在卸载 {title}", - "xpack.ingestManager.integrations.uninstallPackage.uninstallPackageButtonLabel": "卸载 {title}", - "xpack.ingestManager.integrations.updatePackage.updatePackageButtonLabel": "更新到最新版本", - "xpack.ingestManager.invalidLicenseDescription": "您当前的许可证已过期。已注册 Beats 代理将继续工作,但您需要有效的许可证,才能访问 Elastic Fleet 界面。", - "xpack.ingestManager.invalidLicenseTitle": "已过期许可证", - "xpack.ingestManager.listTabs.agentTitle": "代理", - "xpack.ingestManager.listTabs.enrollmentTokensTitle": "注册令牌", - "xpack.ingestManager.metadataForm.addButton": "+ 添加元数据", - "xpack.ingestManager.metadataForm.keyLabel": "键", - "xpack.ingestManager.metadataForm.submitButtonText": "添加", - "xpack.ingestManager.metadataForm.valueLabel": "值", - "xpack.ingestManager.namespaceValidation.invalidCharactersErrorMessage": "命名空间包含无效字符", - "xpack.ingestManager.namespaceValidation.lowercaseErrorMessage": "命名空间必须小写", - "xpack.ingestManager.namespaceValidation.requiredErrorMessage": "“命名空间”必填", - "xpack.ingestManager.namespaceValidation.tooLongErrorMessage": "命名空间不能超过 100 个字节", - "xpack.ingestManager.newEnrollmentKey.cancelButtonLabel": "取消", - "xpack.ingestManager.newEnrollmentKey.flyoutTitle": "创建注册令牌", - "xpack.ingestManager.newEnrollmentKey.keyCreatedToasts": "注册令牌已创建。", - "xpack.ingestManager.newEnrollmentKey.nameLabel": "名称", - "xpack.ingestManager.newEnrollmentKey.policyLabel": "策略", - "xpack.ingestManager.newEnrollmentKey.submitButton": "创建注册令牌", - "xpack.ingestManager.noAccess.accessDeniedDescription": "您无权访问 Elastic Fleet。要使用 Elastic Fleet,您需要包含此应用程序读取权限或所有权限的用户角色。", - "xpack.ingestManager.noAccess.accessDeniedTitle": "访问被拒绝", - "xpack.ingestManager.overviewAgentActiveTitle": "活动", - "xpack.ingestManager.overviewAgentErrorTitle": "错误", - "xpack.ingestManager.overviewAgentOfflineTitle": "脱机", - "xpack.ingestManager.overviewAgentTotalTitle": "代理总数", - "xpack.ingestManager.overviewDatastreamNamespacesTitle": "命名空间", - "xpack.ingestManager.overviewDatastreamSizeTitle": "总大小", - "xpack.ingestManager.overviewDatastreamTotalTitle": "数据流", - "xpack.ingestManager.overviewIntegrationsInstalledTitle": "安装时间", - "xpack.ingestManager.overviewIntegrationsTotalTitle": "可用总计", - "xpack.ingestManager.overviewIntegrationsUpdatesAvailableTitle": "可用更新", - "xpack.ingestManager.overviewPackagePolicyTitle": "已使用的集成", - "xpack.ingestManager.overviewPageAgentsPanelTitle": "代理", - "xpack.ingestManager.overviewPageDataStreamsPanelAction": "查看数据流", - "xpack.ingestManager.overviewPageDataStreamsPanelTitle": "数据流", - "xpack.ingestManager.overviewPageDataStreamsPanelTooltip": "您的代理收集的数据组织到各种数据流中。", - "xpack.ingestManager.overviewPageEnrollAgentButton": "添加代理", - "xpack.ingestManager.overviewPageFleetPanelAction": "查看代理", - "xpack.ingestManager.overviewPageFleetPanelTooltip": "使用 Fleet 注册代理并从中央位置管理其策略。", - "xpack.ingestManager.overviewPageIntegrationsPanelAction": "查看集成", - "xpack.ingestManager.overviewPageIntegrationsPanelTitle": "集成", - "xpack.ingestManager.overviewPageIntegrationsPanelTooltip": "浏览并安装适用于 Elastic Stack 的集成。将集成添加到您的代理策略,以开始发送数据。", - "xpack.ingestManager.overviewPagePoliciesPanelAction": "查看策略", - "xpack.ingestManager.overviewPagePoliciesPanelTitle": "代理策略", - "xpack.ingestManager.overviewPagePoliciesPanelTooltip": "使用代理策略控制您的代理收集的数据。", - "xpack.ingestManager.overviewPageSubtitle": "在集中位置管理 Elastic 代理及其策略。", - "xpack.ingestManager.overviewPageTitle": "Fleet", - "xpack.ingestManager.overviewPolicyTotalTitle": "可用总计", - "xpack.ingestManager.packagePolicyValidation.invalidArrayErrorMessage": "格式无效", - "xpack.ingestManager.packagePolicyValidation.invalidYamlFormatErrorMessage": "YAML 格式无效", - "xpack.ingestManager.packagePolicyValidation.nameRequiredErrorMessage": "“名称”必填", - "xpack.ingestManager.packagePolicyValidation.requiredErrorMessage": "“{fieldName}”必填", - "xpack.ingestManager.permissionDeniedErrorMessage": "您无权访问 Ingest Manager。Ingest Manager 需要{roleName}权限。", - "xpack.ingestManager.permissionDeniedErrorTitle": "权限被拒绝", - "xpack.ingestManager.permissionsRequestErrorMessageDescription": "检查 Ingest Manager 权限时出现问题", - "xpack.ingestManager.permissionsRequestErrorMessageTitle": "无法检查权限", - "xpack.ingestManager.policyDetails.addPackagePolicyButtonText": "添加集成", - "xpack.ingestManager.policyDetails.ErrorGettingFullAgentPolicy": "加载代理策略时出错", - "xpack.ingestManager.policyDetails.packagePoliciesTable.actionsColumnTitle": "操作", - "xpack.ingestManager.policyDetails.packagePoliciesTable.deleteActionTitle": "删除集成", - "xpack.ingestManager.policyDetails.packagePoliciesTable.descriptionColumnTitle": "描述", - "xpack.ingestManager.policyDetails.packagePoliciesTable.editActionTitle": "编辑集成", - "xpack.ingestManager.policyDetails.packagePoliciesTable.nameColumnTitle": "名称", - "xpack.ingestManager.policyDetails.packagePoliciesTable.namespaceColumnTitle": "命名空间", - "xpack.ingestManager.policyDetails.packagePoliciesTable.packageNameColumnTitle": "集成", - "xpack.ingestManager.policyDetails.policyDetailsTitle": "策略“{id}”", - "xpack.ingestManager.policyDetails.policyNotFoundErrorTitle": "找不到策略“{id}”", - "xpack.ingestManager.policyDetails.subTabs.packagePoliciesTabText": "集成", - "xpack.ingestManager.policyDetails.subTabs.settingsTabText": "莞罎", - "xpack.ingestManager.policyDetails.summary.integrations": "集成", - "xpack.ingestManager.policyDetails.summary.lastUpdated": "上次更新时间", - "xpack.ingestManager.policyDetails.summary.revision": "俎莢", - "xpack.ingestManager.policyDetails.summary.usedBy": "使用者", - "xpack.ingestManager.policyDetails.unexceptedErrorTitle": "加载代理策略时发生错误", - "xpack.ingestManager.policyDetails.viewAgentListTitle": "查看所有代理策略", - "xpack.ingestManager.policyDetails.yamlDownloadButtonLabel": "下载策略", - "xpack.ingestManager.policyDetails.yamlFlyoutCloseButtonLabel": "关闭", - "xpack.ingestManager.policyDetails.yamlflyoutTitleWithName": "代理策略“{name}”", - "xpack.ingestManager.policyDetails.yamlflyoutTitleWithoutName": "代理策略", - "xpack.ingestManager.policyDetailsPackagePolicies.createFirstButtonText": "添加集成", - "xpack.ingestManager.policyDetailsPackagePolicies.createFirstMessage": "此策略尚无任何集成。", - "xpack.ingestManager.policyDetailsPackagePolicies.createFirstTitle": "添加您的首个集成", - "xpack.ingestManager.policyForm.deletePolicyActionText": "删除策略", - "xpack.ingestManager.policyForm.deletePolicyGroupDescription": "现有数据将不会删除。", - "xpack.ingestManager.policyForm.deletePolicyGroupTitle": "删除策略", - "xpack.ingestManager.policyForm.generalSettingsGroupDescription": "为您的代理策略选择名称和描述。", - "xpack.ingestManager.policyForm.generalSettingsGroupTitle": "常规设置", - "xpack.ingestManager.policyForm.unableToDeleteDefaultPolicyText": "默认策略无法删除", - "xpack.ingestManager.securityRequiredErrorMessage": "必须在 Kibana 和 Elasticsearch 启用安全性,才能使用 Ingest Manager。", - "xpack.ingestManager.securityRequiredErrorTitle": "安全性未启用", - "xpack.ingestManager.settings.additionalYamlConfig": "Elasticsearch 输出配置", - "xpack.ingestManager.settings.autoUpgradeDisabledLabel": "手动管理代理二进制文件版本。需要黄金级订阅。", - "xpack.ingestManager.settings.autoUpgradeEnabledLabel": "自动更新代理二进制文件以使用最新的次要版本。", - "xpack.ingestManager.settings.autoUpgradeFieldLabel": "Elastic 代理二进制文件版本", - "xpack.ingestManager.settings.cancelButtonLabel": "取消", - "xpack.ingestManager.settings.elasticHostError": "URL 无效", - "xpack.ingestManager.settings.elasticsearchUrlLabel": "Elasticsearch URL", - "xpack.ingestManager.settings.flyoutTitle": "Ingest Manager 莞罎", - "xpack.ingestManager.settings.globalOutputDescription": "指定将数据发送到何处。这些设置将应用于所有的 Elastic 代理策略。", - "xpack.ingestManager.settings.globalOutputTitle": "全局输出", - "xpack.ingestManager.settings.integrationUpgradeDisabledFieldLabel": "自行手动管理集成版本。", - "xpack.ingestManager.settings.integrationUpgradeEnabledFieldLabel": "将集成自动更新到最新版本以获取最新资产。您可能需要更新代理策略以使用新功能。", - "xpack.ingestManager.settings.integrationUpgradeFieldLabel": "集成版本", - "xpack.ingestManager.settings.invalidYamlFormatErrorMessage": "YAML 无效:{reason}", - "xpack.ingestManager.settings.kibanaUrlDifferentPathOrProtocolError": "对于每个 URL,协议和路径必须相同", - "xpack.ingestManager.settings.kibanaUrlEmptyError": "至少需要一个 URL", - "xpack.ingestManager.settings.kibanaUrlError": "URL 无效", - "xpack.ingestManager.settings.kibanaUrlLabel": "Kibana URL", - "xpack.ingestManager.settings.saveButtonLabel": "保存设置", - "xpack.ingestManager.settings.success.message": "设置已保存", - "xpack.ingestManager.setupPage.apiKeyServiceLink": "API 密钥服务", - "xpack.ingestManager.setupPage.elasticsearchApiKeyFlagText": "{apiKeyLink}。将 {apiKeyFlag} 莞罎为 {true}。", - "xpack.ingestManager.setupPage.elasticsearchSecurityFlagText": "{esSecurityLink}。将 {securityFlag} 莞罎为 {true}。", - "xpack.ingestManager.setupPage.elasticsearchSecurityLink": "Elasticsearch 安全", - "xpack.ingestManager.setupPage.enableCentralManagement": "创建用户并启用集中管理", - "xpack.ingestManager.setupPage.enableText": "集中管理需要可以创建 API 密钥并写入到 logs-* 和 metrics-* 的 Elastic 用户。", - "xpack.ingestManager.setupPage.enableTitle": "寚 Elastic 代理启用集中管理", - "xpack.ingestManager.setupPage.encryptionKeyFlagText": "{encryptionKeyLink}。将 {keyFlag} 设置为至少 32 个字符的字母数字值。", - "xpack.ingestManager.setupPage.gettingStartedLink": "入门", - "xpack.ingestManager.setupPage.gettingStartedText": "有关更多信息,请阅读我们的{link}指南。", - "xpack.ingestManager.setupPage.kibanaEncryptionLink": "Kibana 加密密钥", - "xpack.ingestManager.setupPage.kibanaSecurityLink": "Kibana 安全性", - "xpack.ingestManager.setupPage.missingRequirementsCalloutDescription": "茁寚 Elastic 代理使用集中管理,请启用下面的 Elasticsearch 和 Kibana 安全功能。", - "xpack.ingestManager.setupPage.missingRequirementsCalloutTitle": "缺失安全性要求", - "xpack.ingestManager.setupPage.missingRequirementsElasticsearchTitle": "在 Elasticsearch 策略中,启用:", - "xpack.ingestManager.setupPage.missingRequirementsKibanaTitle": "在 Kibana 策略中,启用:", - "xpack.ingestManager.setupPage.tlsFlagText": "{kibanaSecurityLink}。将 {securityFlag} 莞罎为 {true}。出于开发目的,作为非安全的备用方案可以通过将 {tlsFlag} 莞罎为 {true} 来禁用 {tlsLink}。", - "xpack.ingestManager.setupPage.tlsLink": "TLS", - "xpack.ingestManager.unenrollAgents.cancelButtonLabel": "取消", - "xpack.ingestManager.unenrollAgents.confirmMultipleButtonLabel": "取消注册 {count} 个代理", - "xpack.ingestManager.unenrollAgents.confirmSingleButtonLabel": "取消注册代理", - "xpack.ingestManager.unenrollAgents.deleteMultipleDescription": "此操作将从 Fleet 中移除多个代理,并防止采集新数据。将不会影响任何已由这些代理发送的数据。此操作无法撤消。", - "xpack.ingestManager.unenrollAgents.deleteSingleDescription": "此操作将从 Fleet 中移除“{hostName}”上运行的选定代理。由该代理发送的任何数据将不会被删除。此操作无法撤消。", - "xpack.ingestManager.unenrollAgents.deleteSingleTitle": "取消注册代理", - "xpack.ingestManager.unenrollAgents.fatalErrorNotificationTitle": "取消注册{count, plural, one {代理} other {代理}}时出错", - "xpack.ingestManager.unenrollAgents.forceDeleteMultipleTitle": "取消注册 {count} 个代理", - "xpack.ingestManager.unenrollAgents.forceUnenrollCheckboxLabel": "立即移除{count, plural, one {代理} other {代理}}。不用等待代理发送任何最终数据。", - "xpack.ingestManager.unenrollAgents.forceUnenrollLegendText": "强制取消注册{count, plural, one {代理} other {代理}}", - "xpack.ingestManager.unenrollAgents.successForceMultiNotificationTitle": "代理已取消注册", - "xpack.ingestManager.unenrollAgents.successForceSingleNotificationTitle": "代理已取消注册", - "xpack.ingestManager.unenrollAgents.successMultiNotificationTitle": "正在取消注册代理", - "xpack.ingestManager.unenrollAgents.successSingleNotificationTitle": "正在取消注册代理", - "xpack.ingestManager.upgradeAgents.cancelButtonLabel": "取消", - "xpack.ingestManager.upgradeAgents.confirmMultipleButtonLabel": "升级 {count} 个代理", - "xpack.ingestManager.upgradeAgents.confirmSingleButtonLabel": "升级代理", - "xpack.ingestManager.upgradeAgents.deleteMultipleTitle": "升级 {count} 个代理", - "xpack.ingestManager.upgradeAgents.deleteSingleTitle": "升级代理", - "xpack.ingestManager.upgradeAgents.fatalErrorNotificationTitle": "升级{count, plural, one {代理} other {代理}}时出错", - "xpack.ingestManager.upgradeAgents.successMultiNotificationTitle": "正在升级代理", - "xpack.ingestManager.upgradeAgents.successSingleNotificationTitle": "正在升级代理", - "xpack.ingestManager.upgradeAgents.upgradeMultipleDescription": "此操作会将多个代理升级到版本 {version}。此操作无法撤消。是否确定要继续?", - "xpack.ingestManager.upgradeAgents.upgradeSingleDescription": "此操作会将“{hostName}”上运行的选定代理升级到版本 {version}。此操作无法撤消。是否确定要继续?", "xpack.ingestPipelines.addProcesorFormOnFailureFlyout.cancelButtonLabel": "取消", "xpack.ingestPipelines.addProcessorFormOnFailureFlyout.addButtonLabel": "添加", "xpack.ingestPipelines.app.checkingPrivilegesDescription": "正在检查权限……", @@ -20219,7 +20214,6 @@ "xpack.triggersActionsUI.geoThreshold.whenEntityLabel": "当实体", "xpack.triggersActionsUI.home.alertsTabTitle": "告警", "xpack.triggersActionsUI.home.appTitle": "告警和操作", - "xpack.triggersActionsUI.home.betaBadgeTooltipContent": "{pluginName} 为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。", "xpack.triggersActionsUI.home.breadcrumbTitle": "告警和操作", "xpack.triggersActionsUI.home.connectorsTabTitle": "连接器", "xpack.triggersActionsUI.home.sectionDescription": "使用告警检测条件,并使用连接器采取操作。", @@ -20271,18 +20265,14 @@ "xpack.triggersActionsUI.sections.addAlert.error.requiredTimeFieldText": "时间字段必填。", "xpack.triggersActionsUI.sections.addAlert.error.requiredTimeWindowSizeText": "“时间窗大小”必填。", "xpack.triggersActionsUI.sections.addAlert.error.requiredtTermFieldText": "词字段必填。", - "xpack.triggersActionsUI.sections.addConnectorForm.betaBadgeTooltipContent": "{pluginName} 为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。", "xpack.triggersActionsUI.sections.addConnectorForm.flyoutTitle": "{actionTypeName} 连接器", "xpack.triggersActionsUI.sections.addConnectorForm.selectConnectorFlyoutTitle": "选择连接器", "xpack.triggersActionsUI.sections.addConnectorForm.updateErrorNotificationText": "无法创建连接器。", "xpack.triggersActionsUI.sections.addConnectorForm.updateSuccessNotificationText": "已创建“{connectorName}”", - "xpack.triggersActionsUI.sections.addFlyout.betaBadgeTooltipContent": "{pluginName} 为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。", - "xpack.triggersActionsUI.sections.addModalConnectorForm.betaBadgeTooltipContent": "{pluginName} 为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。", "xpack.triggersActionsUI.sections.addModalConnectorForm.cancelButtonLabel": "取消", "xpack.triggersActionsUI.sections.addModalConnectorForm.flyoutTitle": "{actionTypeName} 连接器", "xpack.triggersActionsUI.sections.addModalConnectorForm.saveButtonLabel": "保存", "xpack.triggersActionsUI.sections.addModalConnectorForm.updateSuccessNotificationText": "已创建“{connectorName}”", - "xpack.triggersActionsUI.sections.alertAdd.betaBadgeTooltipContent": "{pluginName} 为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。", "xpack.triggersActionsUI.sections.alertAdd.conditionPrompt": "定义条件", "xpack.triggersActionsUI.sections.alertAdd.errorLoadingAlertVisualizationTitle": "无法加载告警可视化", "xpack.triggersActionsUI.sections.alertAdd.flyoutTitle": "创建告警", @@ -20312,7 +20302,6 @@ "xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.columns.status": "状态", "xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.active": "活动", "xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.status.inactive": "确定", - "xpack.triggersActionsUI.sections.alertDetails.betaBadgeTooltipContent": "{pluginName} 为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。", "xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.disableTitle": "禁用", "xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.muteTitle": "静音", "xpack.triggersActionsUI.sections.alertDetails.dismissButtonTitle": "关闭", @@ -20320,7 +20309,6 @@ "xpack.triggersActionsUI.sections.alertDetails.unableToLoadAlertInstanceSummaryMessage": "无法加载告警实例摘要:{message}", "xpack.triggersActionsUI.sections.alertDetails.unableToLoadAlertMessage": "无法加载告警:{message}", "xpack.triggersActionsUI.sections.alertDetails.viewAlertInAppButtonLabel": "在应用中查看", - "xpack.triggersActionsUI.sections.alertEdit.betaBadgeTooltipContent": "{pluginName} 为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。", "xpack.triggersActionsUI.sections.alertEdit.cancelButtonLabel": "取消", "xpack.triggersActionsUI.sections.alertEdit.disabledActionsWarningTitle": "此告警具有已禁用的操作", "xpack.triggersActionsUI.sections.alertEdit.flyoutTitle": "编辑告警", @@ -20433,7 +20421,6 @@ "xpack.triggersActionsUI.sections.builtinActionTypes.emailAction.subjectTextFieldLabel": "丝题", "xpack.triggersActionsUI.sections.builtinActionTypes.emailAction.userTextFieldLabel": "用户名", "xpack.triggersActionsUI.sections.editConnectorForm.actionTypeDescription": "{actionDescription}", - "xpack.triggersActionsUI.sections.editConnectorForm.betaBadgeTooltipContent": "{pluginName} 为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。", "xpack.triggersActionsUI.sections.editConnectorForm.cancelButtonLabel": "取消", "xpack.triggersActionsUI.sections.editConnectorForm.descriptionText": "此连接器为只读。", "xpack.triggersActionsUI.sections.editConnectorForm.flyoutPreconfiguredTitle": "编辑连接器", @@ -20443,7 +20430,6 @@ "xpack.triggersActionsUI.sections.editConnectorForm.tabText": "配置", "xpack.triggersActionsUI.sections.editConnectorForm.updateErrorNotificationText": "无法更新连接器。", "xpack.triggersActionsUI.sections.editConnectorForm.updateSuccessNotificationText": "已更新“{connectorName}”", - "xpack.triggersActionsUI.sections.preconfiguredConnectorForm.betaBadgeTooltipContent": "{pluginName} 为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束。", "xpack.triggersActionsUI.sections.preconfiguredConnectorForm.flyoutTitle": "{connectorName}", "xpack.triggersActionsUI.sections.preconfiguredConnectorForm.tooltipContent": "这是预配置连接器,无法编辑", "xpack.triggersActionsUI.sections.testConnectorForm.awaitingExecutionDescription": "执行该操作时,结果将显示在此处。", diff --git a/x-pack/plugins/triggers_actions_ui/kibana.json b/x-pack/plugins/triggers_actions_ui/kibana.json index c9187096821d..a4446e0a7512 100644 --- a/x-pack/plugins/triggers_actions_ui/kibana.json +++ b/x-pack/plugins/triggers_actions_ui/kibana.json @@ -3,9 +3,9 @@ "version": "kibana", "server": true, "ui": true, - "optionalPlugins": ["alerts", "stackAlerts"], + "optionalPlugins": ["home", "alerts", "stackAlerts"], "requiredPlugins": ["management", "charts", "data", "kibanaReact"], "configPath": ["xpack", "trigger_actions_ui"], "extraPublicDirs": ["public/common", "public/common/constants"], - "requiredBundles": ["alerts", "esUiShared"] + "requiredBundles": ["home", "alerts", "esUiShared"] } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx index f009a04d4097..482b38ffc0d6 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx @@ -16,11 +16,9 @@ import { EuiTab, EuiTabs, EuiTitle, - EuiBetaBadge, EuiText, } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import { Section, routeToConnectors, routeToAlerts } from './constants'; import { getAlertingSectionBreadcrumb } from './lib/breadcrumb'; import { getCurrentDocTitle } from './lib/doc_title'; @@ -29,7 +27,6 @@ import { hasShowActionsCapability } from './lib/capabilities'; import { ActionsConnectorsList } from './sections/actions_connectors_list/components/actions_connectors_list'; import { AlertsList } from './sections/alerts_list/components/alerts_list'; -import { PLUGIN } from './constants/plugin'; import { HealthCheck } from './components/health_check'; import { HealthContextProvider } from './context/health_context'; @@ -91,20 +88,6 @@ export const TriggersActionsUIHome: React.FunctionComponent -   -

    diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx index 060a751677de..2e222884dab5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_flyout.tsx @@ -17,7 +17,6 @@ import { EuiButtonEmpty, EuiButton, EuiFlyoutBody, - EuiBetaBadge, EuiCallOut, EuiSpacer, } from '@elastic/eui'; @@ -31,7 +30,6 @@ import { hasSaveActionsCapability } from '../../lib/capabilities'; import { createActionConnector } from '../../lib/action_connector_api'; import { useActionsConnectorsContext } from '../../context/actions_connectors_context'; import { VIEW_LICENSE_OPTIONS_LINK } from '../../../common/constants'; -import { PLUGIN } from '../../constants/plugin'; export interface ConnectorAddFlyoutProps { addFlyoutVisible: boolean; @@ -189,20 +187,6 @@ export const ConnectorAddFlyout = ({ actionTypeName: actionType.name, }} /> -   -

    @@ -216,20 +200,6 @@ export const ConnectorAddFlyout = ({ defaultMessage="Select a connector" id="xpack.triggersActionsUI.sections.addConnectorForm.selectConnectorFlyoutTitle" /> -   -

    )} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx index 90abb986517d..d7ca91218d4d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_add_modal.tsx @@ -5,7 +5,7 @@ */ import React, { useCallback, useReducer, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiTitle, EuiFlexItem, EuiIcon, EuiFlexGroup, EuiBetaBadge } from '@elastic/eui'; +import { EuiTitle, EuiFlexItem, EuiIcon, EuiFlexGroup } from '@elastic/eui'; import { EuiModal, EuiButton, @@ -24,7 +24,6 @@ import { connectorReducer } from './connector_reducer'; import { createActionConnector } from '../../lib/action_connector_api'; import { TypeRegistry } from '../../type_registry'; import './connector_add_modal.scss'; -import { PLUGIN } from '../../constants/plugin'; import { hasSaveActionsCapability } from '../../lib/capabilities'; interface ConnectorAddModalProps { @@ -135,20 +134,6 @@ export const ConnectorAddModal = ({ actionTypeName: actionType.name, }} /> -   -

    diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.tsx index 4d8981f25aed..e89eb8c95fba 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/connector_edit_flyout.tsx @@ -31,7 +31,6 @@ import { connectorReducer } from './connector_reducer'; import { updateActionConnector, executeAction } from '../../lib/action_connector_api'; import { hasSaveActionsCapability } from '../../lib/capabilities'; import { useActionsConnectorsContext } from '../../context/actions_connectors_context'; -import { PLUGIN } from '../../constants/plugin'; import { ActionTypeExecutorResult, isActionTypeExecutorResult, @@ -156,20 +155,6 @@ export const ConnectorEditFlyout = ({ } )} /> -   -

    @@ -187,20 +172,6 @@ export const ConnectorEditFlyout = ({ defaultMessage="Edit connector" id="xpack.triggersActionsUI.sections.editConnectorForm.flyoutPreconfiguredTitle" /> -   -

    ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx index 51c3e030f44e..662db81101ee 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx @@ -8,18 +8,8 @@ import uuid from 'uuid'; import { shallow } from 'enzyme'; import { AlertDetails } from './alert_details'; import { Alert, ActionType, ValidationResult } from '../../../../types'; -import { - EuiTitle, - EuiBadge, - EuiFlexItem, - EuiSwitch, - EuiBetaBadge, - EuiButtonEmpty, - EuiText, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; +import { EuiTitle, EuiBadge, EuiFlexItem, EuiSwitch, EuiButtonEmpty, EuiText } from '@elastic/eui'; import { ViewInApp } from './view_in_app'; -import { PLUGIN } from '../../../constants/plugin'; import { coreMock } from 'src/core/public/mocks'; import { ALERTS_FEATURE_ID } from '../../../../../../alerts/common'; @@ -104,20 +94,6 @@ describe('alert_details', () => {

    {alert.name} -   -

    ) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx index 0af01114731a..1272024557bb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx @@ -22,12 +22,10 @@ import { EuiSwitch, EuiCallOut, EuiSpacer, - EuiBetaBadge, EuiButtonEmpty, EuiButton, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; import { useAppDependencies } from '../../../app_context'; import { hasAllPrivilege, hasExecuteActionsCapability } from '../../../lib/capabilities'; import { getAlertingSectionBreadcrumb, getAlertDetailsBreadcrumb } from '../../../lib/breadcrumb'; @@ -39,7 +37,6 @@ import { } from '../../common/components/with_bulk_alert_api_operations'; import { AlertInstancesRouteWithApi } from './alert_instances_route'; import { ViewInApp } from './view_in_app'; -import { PLUGIN } from '../../../constants/plugin'; import { AlertEdit } from '../../alert_form'; import { AlertsContextProvider } from '../../../context/alerts_context'; import { routeToAlertDetails } from '../../../constants'; @@ -130,20 +127,6 @@ export const AlertDetails: React.FunctionComponent = ({

    {alert.name} -   -

    diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.tsx index 763462ba6ebf..89deb4b26f01 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.tsx @@ -6,14 +6,7 @@ import React, { useCallback, useReducer, useState, useEffect } from 'react'; import { isObject } from 'lodash'; import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiTitle, - EuiFlyoutHeader, - EuiFlyout, - EuiFlyoutBody, - EuiPortal, - EuiBetaBadge, -} from '@elastic/eui'; +import { EuiTitle, EuiFlyoutHeader, EuiFlyout, EuiFlyoutBody, EuiPortal } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useAlertsContext } from '../../context/alerts_context'; import { Alert, AlertAction, IErrorObject } from '../../../types'; @@ -21,7 +14,6 @@ import { AlertForm, validateBaseProperties } from './alert_form'; import { alertReducer } from './alert_reducer'; import { createAlert } from '../../lib/alert_api'; import { HealthCheck } from '../../components/health_check'; -import { PLUGIN } from '../../constants/plugin'; import { ConfirmAlertSave } from './confirm_alert_save'; import { hasShowActionsCapability } from '../../lib/capabilities'; import AlertAddFooter from './alert_add_footer'; @@ -163,20 +155,6 @@ export const AlertAdd = ({ defaultMessage="Create alert" id="xpack.triggersActionsUI.sections.alertAdd.flyoutTitle" /> -   -

    diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.tsx index 0435a4cc33cb..5eadc742a9dc 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_edit.tsx @@ -16,7 +16,6 @@ import { EuiButton, EuiFlyoutBody, EuiPortal, - EuiBetaBadge, EuiCallOut, EuiSpacer, } from '@elastic/eui'; @@ -27,7 +26,6 @@ import { AlertForm, validateBaseProperties } from './alert_form'; import { alertReducer } from './alert_reducer'; import { updateAlert } from '../../lib/alert_api'; import { HealthCheck } from '../../components/health_check'; -import { PLUGIN } from '../../constants/plugin'; import { HealthContextProvider } from '../../context/health_context'; interface AlertEditProps { @@ -119,20 +117,6 @@ export const AlertEdit = ({ initialAlert, onClose }: AlertEditProps) => { defaultMessage="Edit alert" id="xpack.triggersActionsUI.sections.alertEdit.flyoutTitle" /> -   -

diff --git a/x-pack/plugins/triggers_actions_ui/public/plugin.ts b/x-pack/plugins/triggers_actions_ui/public/plugin.ts index 874a380f56b5..393ac5bc1b74 100644 --- a/x-pack/plugins/triggers_actions_ui/public/plugin.ts +++ b/x-pack/plugins/triggers_actions_ui/public/plugin.ts @@ -20,6 +20,10 @@ import { ManagementAppMountParams, ManagementSetup, } from '../../../../src/plugins/management/public'; +import { + FeatureCatalogueCategory, + HomePublicPluginSetup, +} from '../../../../src/plugins/home/public'; import { ChartsPluginStart } from '../../../../src/plugins/charts/public'; import { PluginStartContract as AlertingStart } from '../../alerts/public'; import { DataPublicPluginStart } from '../../../../src/plugins/data/public'; @@ -40,6 +44,7 @@ export interface TriggersAndActionsUIPublicPluginStart { interface PluginsSetup { management: ManagementSetup; + home?: HomePublicPluginSetup; } interface PluginsStart { @@ -73,11 +78,31 @@ export class Plugin const actionTypeRegistry = this.actionTypeRegistry; const alertTypeRegistry = this.alertTypeRegistry; + const featureTitle = i18n.translate('xpack.triggersActionsUI.managementSection.displayName', { + defaultMessage: 'Alerts and Actions', + }); + const featureDescription = i18n.translate( + 'xpack.triggersActionsUI.managementSection.displayDescription', + { + defaultMessage: 'Detect conditions using alerts, and take actions using connectors.', + } + ); + + if (plugins.home) { + plugins.home.featureCatalogue.register({ + id: 'triggersActions', + title: featureTitle, + description: featureDescription, + icon: 'watchesApp', + path: '/app/management/insightsAndAlerting/triggersActions', + showOnHomePage: false, + category: FeatureCatalogueCategory.ADMIN, + }); + } + plugins.management.sections.section.insightsAndAlerting.registerApp({ id: 'triggersActions', - title: i18n.translate('xpack.triggersActionsUI.managementSection.displayName', { - defaultMessage: 'Alerts and Actions', - }), + title: featureTitle, order: 0, async mount(params: ManagementAppMountParams) { const [coreStart, pluginsStart] = (await core.getStartServices()) as [ diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index 148facdee248..f24a9a2e3b65 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -3,7 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { HttpSetup, DocLinksStart, ToastsSetup } from 'kibana/public'; +import type { PublicMethodsOf } from '@kbn/utility-types'; +import type { HttpSetup, DocLinksStart, ToastsSetup } from 'kibana/public'; import { ComponentType } from 'react'; import { ActionGroup } from '../../alerts/common'; import { ActionType } from '../../actions/common'; diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/test_data.ts b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/test_data.ts index 78eec05eb2d0..06f63949f6d6 100644 --- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/test_data.ts +++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/test_data.ts @@ -5,6 +5,7 @@ */ import uuid from 'uuid'; +import type { PublicMethodsOf } from '@kbn/utility-types'; import { UiActionsEnhancedDynamicActionManager as DynamicActionManager, UiActionsEnhancedDynamicActionManagerState as DynamicActionManagerState, diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/__tests__/executed_journey.test.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/__tests__/executed_journey.test.tsx index 5ab815a3c0b5..9fec9439b3ad 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/__tests__/executed_journey.test.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/__tests__/executed_journey.test.tsx @@ -253,6 +253,9 @@ describe('ExecutedJourney component', () => { } } /> + `); }); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/executed_journey.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/executed_journey.tsx index 2ffb3f0feb4d..9a3e045017f9 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/executed_journey.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/executed_journey.tsx @@ -79,6 +79,7 @@ export const ExecutedJourney: FC = ({ journey }) => ( {journey.steps.filter(isStepEnd).map((step, index) => ( ))} + ); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/executed_step.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/executed_step.tsx index 3c26ba12eea6..5966851973af 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/executed_step.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/executed_step.tsx @@ -41,7 +41,7 @@ export const ExecutedStep: FC = ({ step, index }) => (
- +
@@ -87,6 +87,5 @@ export const ExecutedStep: FC = ({ step, index }) => (
- ); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_screenshot_display.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_screenshot_display.tsx index 2e8ad4bd0c9a..b81cf6bc1ec1 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_screenshot_display.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_screenshot_display.tsx @@ -16,7 +16,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import React, { useContext, useEffect, useRef, useState, FC } from 'react'; import { useIntersection } from 'react-use'; -import { UptimeThemeContext } from '../../../contexts'; +import { UptimeSettingsContext, UptimeThemeContext } from '../../../contexts'; interface StepScreenshotDisplayProps { screenshotExists?: boolean; @@ -41,6 +41,8 @@ export const StepScreenshotDisplay: FC = ({ colors: { lightestShade: pageBackground }, } = useContext(UptimeThemeContext); + const { basePath } = useContext(UptimeSettingsContext); + const [isImagePopoverOpen, setIsImagePopoverOpen] = useState(false); const [isOverlayOpen, setIsOverlayOpen] = useState(false); @@ -59,7 +61,7 @@ export const StepScreenshotDisplay: FC = ({ }, [hasIntersected, isIntersecting, setHasIntersected]); let content: JSX.Element | null = null; - const imgSrc = `/api/uptime/journey/screenshot/${checkGroup}/${stepIndex}`; + const imgSrc = basePath + `/api/uptime/journey/screenshot/${checkGroup}/${stepIndex}`; if (hasIntersected && screenshotExists) { content = ( <> diff --git a/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts b/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts index 98db43c5b262..a864bfa59142 100644 --- a/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts +++ b/x-pack/plugins/uptime/server/lib/requests/search/refine_potential_matches.ts @@ -38,6 +38,12 @@ export const fullyMatchingIds = (queryResult: any, statusFilter?: string): Monit for (const locBucket of monBucket.location.buckets) { const latest = locBucket.summaries.latest.hits.hits[0]; + // It is possible for no latest summary to exist in this bucket if only partial + // non-summary docs exist + if (!latest) { + continue; + } + const latestStillMatching = locBucket.latest_matching.top.hits.hits[0]; // If the most recent document still matches the most recent document matching the current filters // we can include this in the result diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js index b15a2cf8d1f1..ad6ec7bf8228 100644 --- a/x-pack/scripts/functional_tests.js +++ b/x-pack/scripts/functional_tests.js @@ -7,6 +7,7 @@ const alwaysImportedTests = [ require.resolve('../test/functional/config.js'), require.resolve('../test/security_solution_endpoint/config.ts'), + require.resolve('../test/plugin_functional/config.ts'), require.resolve('../test/functional_with_es_ssl/config.ts'), require.resolve('../test/functional/config_security_basic.ts'), require.resolve('../test/security_functional/login_selector.config.ts'), diff --git a/x-pack/test/api_integration/apis/maps/proxy_api.js b/x-pack/test/api_integration/apis/maps/proxy_api.js index 45ce84cabcac..5dc6b372ced7 100644 --- a/x-pack/test/api_integration/apis/maps/proxy_api.js +++ b/x-pack/test/api_integration/apis/maps/proxy_api.js @@ -9,8 +9,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - // Failing: See https://github.com/elastic/kibana/issues/81844 - describe.skip('EMS proxy', () => { + describe('EMS proxy', () => { it('should correctly rewrite url and format', async () => { const resp = await supertest .get(`/api/maps/ems/files/v7.10/manifest`) @@ -22,7 +21,7 @@ export default function ({ getService }) { //Check world-layer const worldLayer = resp.body.layers.find((layer) => layer.layer_id === 'world_countries'); expect(worldLayer.formats.length).to.be.greaterThan(0); - expect(worldLayer.formats[0].type).to.be('geojson'); + expect(worldLayer.formats[0].type).to.be('topojson'); expect(worldLayer.formats[0].url).to.be('file?id=world_countries'); }); }); diff --git a/x-pack/test/api_integration/apis/metrics_ui/log_item.ts b/x-pack/test/api_integration/apis/metrics_ui/log_item.ts index 6e0148f13277..3bb7a9a76690 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/log_item.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/log_item.ts @@ -44,107 +44,107 @@ export default function ({ getService }: FtrProviderContext) { expect(logItem.fields).to.eql([ { field: '@timestamp', - value: '2018-10-17T19:42:22.000Z', + value: ['2018-10-17T19:42:22.000Z'], }, { field: '_id', - value: 'yT2Mg2YBh-opCxJv8Vqj', + value: ['yT2Mg2YBh-opCxJv8Vqj'], }, { field: '_index', - value: 'filebeat-7.0.0-alpha1-2018.10.17', + value: ['filebeat-7.0.0-alpha1-2018.10.17'], }, { field: 'apache2.access.body_sent.bytes', - value: '1336', + value: ['1336'], }, { field: 'apache2.access.http_version', - value: '1.1', + value: ['1.1'], }, { field: 'apache2.access.method', - value: 'GET', + value: ['GET'], }, { field: 'apache2.access.referrer', - value: '-', + value: ['-'], }, { field: 'apache2.access.remote_ip', - value: '10.128.0.11', + value: ['10.128.0.11'], }, { field: 'apache2.access.response_code', - value: '200', + value: ['200'], }, { field: 'apache2.access.url', - value: '/a-fresh-start-will-put-you-on-your-way', + value: ['/a-fresh-start-will-put-you-on-your-way'], }, { field: 'apache2.access.user_agent.device', - value: 'Other', + value: ['Other'], }, { field: 'apache2.access.user_agent.name', - value: 'Other', + value: ['Other'], }, { field: 'apache2.access.user_agent.os', - value: 'Other', + value: ['Other'], }, { field: 'apache2.access.user_agent.os_name', - value: 'Other', + value: ['Other'], }, { field: 'apache2.access.user_name', - value: '-', + value: ['-'], }, { field: 'beat.hostname', - value: 'demo-stack-apache-01', + value: ['demo-stack-apache-01'], }, { field: 'beat.name', - value: 'demo-stack-apache-01', + value: ['demo-stack-apache-01'], }, { field: 'beat.version', - value: '7.0.0-alpha1', + value: ['7.0.0-alpha1'], }, { field: 'fileset.module', - value: 'apache2', + value: ['apache2'], }, { field: 'fileset.name', - value: 'access', + value: ['access'], }, { field: 'host.name', - value: 'demo-stack-apache-01', + value: ['demo-stack-apache-01'], }, { field: 'input.type', - value: 'log', + value: ['log'], }, { field: 'offset', - value: '5497614', + value: ['5497614'], }, { field: 'prospector.type', - value: 'log', + value: ['log'], }, { field: 'read_timestamp', - value: '2018-10-17T19:42:23.160Z', + value: ['2018-10-17T19:42:23.160Z'], }, { field: 'source', - value: '/var/log/apache2/access.log', + value: ['/var/log/apache2/access.log'], }, ]); }); diff --git a/x-pack/test/api_integration/apis/uptime/rest/monitor_states_generated.ts b/x-pack/test/api_integration/apis/uptime/rest/monitor_states_generated.ts index 3e06373042d5..69571099a264 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/monitor_states_generated.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/monitor_states_generated.ts @@ -24,6 +24,30 @@ export default function ({ getService }: FtrProviderContext) { before('load heartbeat data', () => getService('esArchiver').load('uptime/blank')); after('unload heartbeat index', () => getService('esArchiver').unload('uptime/blank')); + // In this case we don't actually have any monitors to display + // but the query should still return successfully. This has + // caused bugs in the past because a bucket of monitor data + // was available and the query code assumed at least one + // event would be a summary for each monitor. + // See https://github.com/elastic/kibana/issues/81950 + describe('checks with no summaries', async () => { + const testMonitorId = 'scope-test-id'; + before(async () => { + const es = getService('legacyEs'); + dateRangeStart = new Date().toISOString(); + await makeChecksWithStatus(es, testMonitorId, 1, numIps, 1, {}, 'up', (d) => { + delete d.summary; + return d; + }); + }); + + it('should return no monitors and have no errors', async () => { + const url = getBaseUrl(dateRangeStart, new Date().toISOString()); + const apiResponse = await supertest.get(url); + expect(apiResponse.status).to.equal(200); + }); + }); + describe('query document scoping with mismatched check statuses', async () => { let checks: any[] = []; let nonSummaryIp: string | null = null; diff --git a/x-pack/test/apm_api_integration/trial/tests/csm/web_core_vitals.ts b/x-pack/test/apm_api_integration/trial/tests/csm/web_core_vitals.ts index efbdb75c47cc..5dbe266deeb8 100644 --- a/x-pack/test/apm_api_integration/trial/tests/csm/web_core_vitals.ts +++ b/x-pack/test/apm_api_integration/trial/tests/csm/web_core_vitals.ts @@ -21,14 +21,12 @@ export default function rumServicesApiTests({ getService }: FtrProviderContext) expect(response.status).to.be(200); expect(response.body).to.eql({ - cls: '0', - fid: '0.00', - lcp: '0.00', - tbt: '0.00', - fcp: 0, - lcpRanks: [0, 0, 100], - fidRanks: [0, 0, 100], - clsRanks: [0, 0, 100], + coreVitalPages: 0, + cls: null, + tbt: 0, + lcpRanks: [100, 0, 0], + fidRanks: [100, 0, 0], + clsRanks: [100, 0, 0], }); }); }); @@ -52,20 +50,21 @@ export default function rumServicesApiTests({ getService }: FtrProviderContext) expectSnapshot(response.body).toMatchInline(` Object { - "cls": "0.00", + "cls": "0.000", "clsRanks": Array [ 100, 0, 0, ], - "fcp": 1072, + "coreVitalPages": 6, + "fcp": 817.5, "fid": 1352.13, "fidRanks": Array [ 0, 0, 100, ], - "lcp": 1270.5, + "lcp": 1019, "lcpRanks": Array [ 100, 0, diff --git a/x-pack/test/functional/apps/spaces/copy_saved_objects.ts b/x-pack/test/functional/apps/spaces/copy_saved_objects.ts index 2ee6b903cc3a..8f29ae6a27c3 100644 --- a/x-pack/test/functional/apps/spaces/copy_saved_objects.ts +++ b/x-pack/test/functional/apps/spaces/copy_saved_objects.ts @@ -115,5 +115,33 @@ export default function spaceSelectorFunctonalTests({ await PageObjects.copySavedObjectsToSpace.finishCopy(); }); + + it('allows a dashboard to be copied to the marketing space, with circular references', async () => { + const destinationSpaceId = 'marketing'; + + await PageObjects.copySavedObjectsToSpace.openCopyToSpaceFlyoutForObject('Dashboard Foo'); + + await PageObjects.copySavedObjectsToSpace.setupForm({ + overwrite: true, + destinationSpaceId, + }); + + await PageObjects.copySavedObjectsToSpace.startCopy(); + + // Wait for successful copy + await testSubjects.waitForDeleted(`cts-summary-indicator-loading-${destinationSpaceId}`); + await testSubjects.existOrFail(`cts-summary-indicator-success-${destinationSpaceId}`); + + const summaryCounts = await PageObjects.copySavedObjectsToSpace.getSummaryCounts(); + + expect(summaryCounts).to.eql({ + success: 2, + pending: 0, + skipped: 0, + errors: 0, + }); + + await PageObjects.copySavedObjectsToSpace.finishCopy(); + }); }); } diff --git a/x-pack/test/functional/es_archives/event_log_multiple_indicies/data.json b/x-pack/test/functional/es_archives/event_log_multiple_indicies/data.json new file mode 100644 index 000000000000..4e871f6308b7 --- /dev/null +++ b/x-pack/test/functional/es_archives/event_log_multiple_indicies/data.json @@ -0,0 +1,274 @@ +{ + "type": "doc", + "value": { + "id": "config:8.0.0", + "index": ".kibana_1", + "source": { + "config": { + "buildNum": 9007199254740991 + }, + "migrationVersion": { + "config": "7.9.0" + }, + "references": [ + ], + "type": "config", + "updated_at": "2020-10-28T15:19:15.795Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "space:default", + "index": ".kibana_1", + "source": { + "migrationVersion": { + "space": "6.6.0" + }, + "references": [ + ], + "space": { + "_reserved": true, + "color": "#00bfb3", + "description": "This is your default space!", + "disabledFeatures": [ + ], + "name": "Default" + }, + "type": "space", + "updated_at": "2020-10-28T15:19:15.857Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "space:namespace-a", + "index": ".kibana_1", + "source": { + "migrationVersion": { + "space": "6.6.0" + }, + "references": [ + ], + "space": { + "disabledFeatures": [ + ], + "name": "Space A" + }, + "type": "space", + "updated_at": "2020-10-28T15:19:52.887Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "event_log_test:421f2511-5cd1-44fd-95df-e0df83e354d5", + "index": ".kibana_1", + "source": { + "event_log_test": { + }, + "references": [ + ], + "type": "event_log_test", + "updated_at": "2020-10-28T15:19:53.861Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "XKbLb3UBt6Z_MVvSSPbe", + "index": ".kibana-event-log-7.9.0-000001", + "source": { + "@timestamp": "2020-10-28T15:19:54.841Z", + "ecs": { + "version": "1.5.0" + }, + "event": { + "action": "test", + "duration": 0, + "end": "2020-10-28T15:19:54.841Z", + "provider": "event_log_fixture", + "start": "2020-10-28T15:19:54.841Z" + }, + "kibana": { + "saved_objects": [ + { + "id": "421f2511-5cd1-44fd-95df-e0df83e354d5", + "rel": "primary", + "type": "event_log_test" + } + ], + "server_uuid": "5b2de169-2785-441b-ae8c-186a1936b17d" + }, + "message": "test 2020-10-28T15:19:53.825Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "XabLb3UBt6Z_MVvSSfYD", + "index": ".kibana-event-log-7.9.0-000001", + "source": { + "@timestamp": "2020-10-28T15:19:54.879Z", + "ecs": { + "version": "1.5.0" + }, + "event": { + "action": "test", + "duration": 0, + "end": "2020-10-28T15:19:54.879Z", + "provider": "event_log_fixture", + "start": "2020-10-28T15:19:54.879Z" + }, + "kibana": { + "saved_objects": [ + { + "id": "421f2511-5cd1-44fd-95df-e0df83e354d5", + "rel": "primary", + "type": "event_log_test" + } + ], + "server_uuid": "5b2de169-2785-441b-ae8c-186a1936b17d" + }, + "message": "test 2020-10-28T15:19:54.849Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "XqbLb3UBt6Z_MVvSSfYe", + "index": ".kibana-event-log-7.9.0-000001", + "source": { + "@timestamp": "2020-10-28T15:19:54.905Z", + "ecs": { + "version": "1.5.0" + }, + "event": { + "action": "test", + "duration": 0, + "end": "2020-10-28T15:19:54.905Z", + "provider": "event_log_fixture", + "start": "2020-10-28T15:19:54.905Z" + }, + "kibana": { + "saved_objects": [ + { + "id": "421f2511-5cd1-44fd-95df-e0df83e354d5", + "rel": "primary", + "type": "event_log_test" + } + ], + "server_uuid": "5b2de169-2785-441b-ae8c-186a1936b17d" + }, + "message": "test 2020-10-28T15:19:54.881Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "X6bLb3UBt6Z_MVvSTfYk", + "index": ".kibana-event-log-8.0.0-000001", + "source": { + "@timestamp": "2020-10-28T15:19:55.933Z", + "ecs": { + "version": "1.5.0" + }, + "event": { + "action": "test", + "duration": 0, + "end": "2020-10-28T15:19:55.933Z", + "provider": "event_log_fixture", + "start": "2020-10-28T15:19:55.933Z" + }, + "kibana": { + "saved_objects": [ + { + "id": "421f2511-5cd1-44fd-95df-e0df83e354d5", + "rel": "primary", + "type": "event_log_test" + } + ], + "server_uuid": "5b2de169-2785-441b-ae8c-186a1936b17d" + }, + "message": "test 2020-10-28T15:19:55.913Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "YKbLb3UBt6Z_MVvSTfY8", + "index": ".kibana-event-log-8.0.0-000001", + "source": { + "@timestamp": "2020-10-28T15:19:55.957Z", + "ecs": { + "version": "1.5.0" + }, + "event": { + "action": "test", + "duration": 0, + "end": "2020-10-28T15:19:55.957Z", + "provider": "event_log_fixture", + "start": "2020-10-28T15:19:55.957Z" + }, + "kibana": { + "saved_objects": [ + { + "id": "421f2511-5cd1-44fd-95df-e0df83e354d5", + "rel": "primary", + "type": "event_log_test" + } + ], + "server_uuid": "5b2de169-2785-441b-ae8c-186a1936b17d" + }, + "message": "test 2020-10-28T15:19:55.938Z" + } + } +} + +{ + "type": "doc", + "value": { + "id": "YabLb3UBt6Z_MVvSTfZc", + "index": ".kibana-event-log-8.0.0-000001", + "source": { + "@timestamp": "2020-10-28T15:19:55.991Z", + "ecs": { + "version": "1.5.0" + }, + "event": { + "action": "test", + "duration": 0, + "end": "2020-10-28T15:19:55.991Z", + "provider": "event_log_fixture", + "start": "2020-10-28T15:19:55.991Z" + }, + "kibana": { + "saved_objects": [ + { + "id": "421f2511-5cd1-44fd-95df-e0df83e354d5", + "rel": "primary", + "type": "event_log_test" + } + ], + "server_uuid": "5b2de169-2785-441b-ae8c-186a1936b17d" + }, + "message": "test 2020-10-28T15:19:55.962Z" + } + } +} \ No newline at end of file diff --git a/x-pack/test/functional/es_archives/event_log_multiple_indicies/mappings.json b/x-pack/test/functional/es_archives/event_log_multiple_indicies/mappings.json new file mode 100644 index 000000000000..b418ccc1343a --- /dev/null +++ b/x-pack/test/functional/es_archives/event_log_multiple_indicies/mappings.json @@ -0,0 +1,576 @@ +{ + "type": "index", + "value": { + "aliases": { + ".kibana": { + } + }, + "index": ".kibana_1", + "mappings": { + "_meta": { + "migrationMappingPropertyHashes": { + "action": "6e96ac5e648f57523879661ea72525b7", + "action_task_params": "a9d49f184ee89641044be0ca2950fa3a", + "alert": "eaf6f5841dbf4cb5e3045860f75f53ca", + "apm-indices": "9bb9b2bf1fa636ed8619cbab5ce6a1dd", + "apm-telemetry": "3d1b76c39bfb2cc8296b024d73854724", + "app_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724", + "application_usage_daily": "43b8830d5d0df85a6823d290885fc9fd", + "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724", + "application_usage_transactional": "3d1b76c39bfb2cc8296b024d73854724", + "canvas-element": "7390014e1091044523666d97247392fc", + "canvas-workpad": "b0a1706d356228dbdcb4a17e6b9eb231", + "canvas-workpad-template": "ae2673f678281e2c055d764b153e9715", + "cases": "477f214ff61acc3af26a7b7818e380c1", + "cases-comments": "c2061fb929f585df57425102fa928b4b", + "cases-configure": "387c5f3a3bda7e0ae0dd4e106f914a69", + "cases-user-actions": "32277330ec6b721abe3b846cfd939a71", + "config": "c63748b75f39d0c54de12d12c1ccbc20", + "dashboard": "40554caf09725935e2c02e02563a2d07", + "endpoint:user-artifact": "4a11183eee21e6fbad864f7a30b39ad0", + "endpoint:user-artifact-manifest": "4b9c0e7cfaf86d82a7ee9ed68065e50d", + "enterprise_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724", + "epm-packages": "2b83397e3eaaaa8ef15e38813f3721c3", + "event_log_test": "bef808d4a9c27f204ffbda3359233931", + "exception-list": "67f055ab8c10abd7b2ebfd969b836788", + "exception-list-agnostic": "67f055ab8c10abd7b2ebfd969b836788", + "file-upload-telemetry": "0ed4d3e1983d1217a30982630897092e", + "fleet-agent-actions": "9511b565b1cc6441a42033db3d5de8e9", + "fleet-agent-events": "e20a508b6e805189356be381dbfac8db", + "fleet-agents": "cb661e8ede2b640c42c8e5ef99db0683", + "fleet-enrollment-api-keys": "a69ef7ae661dab31561d6c6f052ef2a7", + "graph-workspace": "cd7ba1330e6682e9cc00b78850874be1", + "index-pattern": "45915a1ad866812242df474eb0479052", + "infrastructure-ui-source": "3d1b76c39bfb2cc8296b024d73854724", + "ingest-agent-policies": "8b0733cce189659593659dad8db426f0", + "ingest-outputs": "8854f34453a47e26f86a29f8f3b80b4e", + "ingest-package-policies": "f74dfe498e1849267cda41580b2be110", + "ingest_manager_settings": "02a03095f0e05b7a538fa801b88a217f", + "inventory-view": "3d1b76c39bfb2cc8296b024d73854724", + "kql-telemetry": "d12a98a6f19a2d273696597547e064ee", + "lens": "52346cfec69ff7b47d5f0c12361a2797", + "lens-ui-telemetry": "509bfa5978586998e05f9e303c07a327", + "map": "4a05b35c3a3a58fbc72dd0202dc3487f", + "maps-telemetry": "5ef305b18111b77789afefbd36b66171", + "metrics-explorer-view": "3d1b76c39bfb2cc8296b024d73854724", + "migrationVersion": "4a1746014a75ade3a714e1db5763276f", + "ml-telemetry": "257fd1d4b4fdbb9cb4b8a3b27da201e9", + "monitoring-telemetry": "2669d5ec15e82391cf58df4294ee9c68", + "namespace": "2f4316de49999235636386fe51dc06c1", + "namespaces": "2f4316de49999235636386fe51dc06c1", + "originId": "2f4316de49999235636386fe51dc06c1", + "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9", + "references": "7997cf5a56cc02bdc9c93361bde732b0", + "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4", + "search": "43012c7ebc4cb57054e0a490e4b43023", + "search-telemetry": "3d1b76c39bfb2cc8296b024d73854724", + "siem-detection-engine-rule-actions": "6569b288c169539db10cb262bf79de18", + "siem-detection-engine-rule-status": "ae783f41c6937db6b7a2ef5c93a9e9b0", + "siem-ui-timeline": "d12c5474364d737d17252acf1dc4585c", + "siem-ui-timeline-note": "8874706eedc49059d4cf0f5094559084", + "siem-ui-timeline-pinned-event": "20638091112f0e14f0e443d512301c29", + "space": "c5ca8acafa0beaa4d08d014a97b6bc6b", + "telemetry": "36a616f7026dfa617d6655df850fe16d", + "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf", + "tsvb-validation-telemetry": "3a37ef6c8700ae6fc97d5c7da00e9215", + "type": "2f4316de49999235636386fe51dc06c1", + "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3", + "updated_at": "00da57df13e94e9d98437d13ace4bfe0", + "upgrade-assistant-reindex-operation": "215107c281839ea9b3ad5f6419819763", + "upgrade-assistant-telemetry": "56702cec857e0a9dacfb696655b4ff7b", + "uptime-dynamic-settings": "3d1b76c39bfb2cc8296b024d73854724", + "url": "c7f66a0df8b1b52f17c28c4adb111105", + "visualization": "f819cf6636b75c9e76ba733a0c6ef355", + "workplace_search_telemetry": "3d1b76c39bfb2cc8296b024d73854724" + } + }, + "dynamic": "strict", + "properties": { + "config": { + "dynamic": "false", + "properties": { + "buildNum": { + "type": "keyword" + } + } + }, + "event_log_test": { + "type": "object" + }, + "migrationVersion": { + "dynamic": "true", + "properties": { + "config": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "space": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "ml-telemetry": { + "properties": { + "file_data_visualizer": { + "properties": { + "index_creation_count": { + "type": "long" + } + } + } + } + }, + "monitoring-telemetry": { + "properties": { + "reportedClusterUuids": { + "type": "keyword" + } + } + }, + "namespace": { + "type": "keyword" + }, + "namespaces": { + "type": "keyword" + }, + "originId": { + "type": "keyword" + }, + "query": { + "properties": { + "description": { + "type": "text" + }, + "filters": { + "enabled": false, + "type": "object" + }, + "query": { + "properties": { + "language": { + "type": "keyword" + }, + "query": { + "index": false, + "type": "keyword" + } + } + }, + "timefilter": { + "enabled": false, + "type": "object" + }, + "title": { + "type": "text" + } + } + }, + "references": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + }, + "type": { + "type": "keyword" + }, + "space": { + "properties": { + "_reserved": { + "type": "boolean" + }, + "color": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "disabledFeatures": { + "type": "keyword" + }, + "imageUrl": { + "index": false, + "type": "text" + }, + "initials": { + "type": "keyword" + }, + "name": { + "fields": { + "keyword": { + "ignore_above": 2048, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "ui-metric": { + "properties": { + "count": { + "type": "integer" + } + } + }, + "updated_at": { + "type": "date" + }, + "url": { + "properties": { + "accessCount": { + "type": "long" + }, + "accessDate": { + "type": "date" + }, + "createDate": { + "type": "date" + }, + "url": { + "fields": { + "keyword": { + "ignore_above": 2048, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "visualization": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "index": false, + "type": "text" + } + } + }, + "savedSearchRefName": { + "doc_values": false, + "index": false, + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "index": false, + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "index": false, + "type": "text" + } + } + }, + "workplace_search_telemetry": { + "dynamic": "false", + "type": "object" + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "number_of_replicas": "0", + "number_of_shards": "1" + } + } + } +} + +{ + "type": "index", + "value": { + "aliases": { + ".kibana-event-log-7.9.0": { + "is_write_index": true + } + }, + "index": ".kibana-event-log-7.9.0-000001", + "mappings": { + "dynamic": "false", + "properties": { + "@timestamp": { + "type": "date" + }, + "ecs": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "error": { + "properties": { + "message": { + "norms": false, + "type": "text" + } + } + }, + "event": { + "properties": { + "action": { + "ignore_above": 1024, + "type": "keyword" + }, + "duration": { + "type": "long" + }, + "end": { + "type": "date" + }, + "outcome": { + "ignore_above": 1024, + "type": "keyword" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "start": { + "type": "date" + } + } + }, + "kibana": { + "properties": { + "alerting": { + "properties": { + "instance_id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_objects": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "namespace": { + "ignore_above": 1024, + "type": "keyword" + }, + "rel": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "server_uuid": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "message": { + "norms": false, + "type": "text" + }, + "tags": { + "ignore_above": 1024, + "meta": { + "isArray": "true" + }, + "type": "keyword" + }, + "user": { + "properties": { + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "lifecycle": { + "name": "kibana-event-log-policy", + "rollover_alias": ".kibana-event-log-7.9.0" + }, + "number_of_replicas": "0", + "number_of_shards": "1" + } + } + } +} + +{ + "type": "index", + "value": { + "aliases": { + ".kibana-event-log-8.0.0": { + "is_write_index": true + } + }, + "index": ".kibana-event-log-8.0.0-000001", + "mappings": { + "dynamic": "false", + "properties": { + "@timestamp": { + "type": "date" + }, + "ecs": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "error": { + "properties": { + "message": { + "norms": false, + "type": "text" + } + } + }, + "event": { + "properties": { + "action": { + "ignore_above": 1024, + "type": "keyword" + }, + "duration": { + "type": "long" + }, + "end": { + "type": "date" + }, + "outcome": { + "ignore_above": 1024, + "type": "keyword" + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + }, + "start": { + "type": "date" + } + } + }, + "kibana": { + "properties": { + "alerting": { + "properties": { + "instance_id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "saved_objects": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "namespace": { + "ignore_above": 1024, + "type": "keyword" + }, + "rel": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "server_uuid": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "message": { + "norms": false, + "type": "text" + }, + "tags": { + "ignore_above": 1024, + "meta": { + "isArray": "true" + }, + "type": "keyword" + }, + "user": { + "properties": { + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "lifecycle": { + "name": "kibana-event-log-policy", + "rollover_alias": ".kibana-event-log-8.0.0" + }, + "number_of_replicas": "0", + "number_of_shards": "1" + } + } + } +} \ No newline at end of file diff --git a/x-pack/test/functional/es_archives/spaces/copy_saved_objects/data.json b/x-pack/test/functional/es_archives/spaces/copy_saved_objects/data.json index 944b91e8be11..3434e1f80a7c 100644 --- a/x-pack/test/functional/es_archives/spaces/copy_saved_objects/data.json +++ b/x-pack/test/functional/es_archives/spaces/copy_saved_objects/data.json @@ -109,3 +109,63 @@ } } } + +{ + "type": "doc", + "value": { + "index": ".kibana", + "type": "doc", + "id": "dashboard:dashboard-foo", + "source": { + "references": [{ + "id":"dashboard-bar", + "name":"dashboard-circular-ref", + "type":"dashboard" + }], + "dashboard": { + "title": "Dashboard Foo", + "hits": 0, + "description": "", + "panelsJSON": "[{}]", + "optionsJSON": "{}", + "version": 1, + "timeRestore": false, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}" + } + }, + "type": "dashboard", + "updated_at": "2019-01-22T19:32:47.232Z" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".kibana", + "type": "doc", + "id": "dashboard:dashboard-bar", + "source": { + "references": [{ + "id":"dashboard-foo", + "name":"dashboard-circular-ref", + "type":"dashboard" + }], + "dashboard": { + "title": "Dashboard Bar", + "hits": 0, + "description": "", + "panelsJSON": "[{}]", + "optionsJSON": "{}", + "version": 1, + "timeRestore": false, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}" + } + }, + "type": "dashboard", + "updated_at": "2019-01-22T19:32:47.232Z" + } + } +} diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts index 3b9360783267..bd799947256d 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts @@ -23,7 +23,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await log.debug('Checking for section heading to say Triggers and Actions.'); const headingText = await pageObjects.triggersActionsUI.getSectionHeadingText(); - expect(headingText).to.be('Alerts and Actions BETA'); + expect(headingText).to.be('Alerts and Actions'); }); describe('Connectors tab', () => { diff --git a/x-pack/test/ingest_manager_api_integration/apis/agent_policy/agent_policy_with_agents_setup.ts b/x-pack/test/ingest_manager_api_integration/apis/agent_policy/agent_policy_with_agents_setup.ts new file mode 100644 index 000000000000..d99e6a69c512 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/agent_policy/agent_policy_with_agents_setup.ts @@ -0,0 +1,137 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { skipIfNoDockerRegistry } from '../../helpers'; +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { setupIngest, getSupertestWithoutAuth } from '../fleet/agents/services'; + +export default function (providerContext: FtrProviderContext) { + const { getService } = providerContext; + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + const supertestWithoutAuth = getSupertestWithoutAuth(providerContext); + const kibanaServer = getService('kibanaServer'); + + async function getEnrollmentKeyForPolicyId(policyId: string) { + const listRes = await supertest.get(`/api/fleet/enrollment-api-keys`).expect(200); + + const key = listRes.body.list.find( + (item: { policy_id: string; id: string }) => item.policy_id === policyId + ); + + expect(key).not.empty(); + + const res = await supertest.get(`/api/fleet/enrollment-api-keys/${key.id}`).expect(200); + + return res.body.item; + } + + // Enroll an agent to get the actions for an agent as encrypted saved object are not expose otherwise + async function getAgentActionsForEnrollmentKey(enrollmentAPIToken: string) { + const kibanaVersionAccessor = kibanaServer.version; + const kibanaVersion = await kibanaVersionAccessor.get(); + + const { body: enrollmentResponse } = await supertestWithoutAuth + .post(`/api/ingest_manager/fleet/agents/enroll`) + .set('kbn-xsrf', 'xxx') + .set('Authorization', `ApiKey ${enrollmentAPIToken}`) + .send({ + type: 'PERMANENT', + metadata: { + local: { + elastic: { agent: { version: kibanaVersion } }, + }, + user_provided: {}, + }, + }) + .expect(200); + + const agentAccessAPIKey = enrollmentResponse.item.access_api_key; + + // Agent checkin + const { body: checkinApiResponse } = await supertestWithoutAuth + .post(`/api/ingest_manager/fleet/agents/${enrollmentResponse.item.id}/checkin`) + .set('kbn-xsrf', 'xx') + .set('Authorization', `ApiKey ${agentAccessAPIKey}`) + .send({ + events: [], + }) + .expect(200); + + expect(checkinApiResponse.actions).length(1); + + return checkinApiResponse.actions[0]; + } + + // Test all the side effect that should occurs when we create|update an agent policy + describe('ingest_manager_agent_policies_with_agents_setup', () => { + skipIfNoDockerRegistry(providerContext); + + before(async () => { + await esArchiver.loadIfNeeded('fleet/agents'); + }); + after(async () => { + await esArchiver.unload('fleet/agents'); + }); + + setupIngest(providerContext); + + describe('POST /api/fleet/agent_policies', () => { + it('should create an enrollment key and an agent action `POLICY_CHANGE` for the policy', async () => { + const name = `test-${Date.now()}`; + + const res = await supertest + .post(`/api/fleet/agent_policies?sys_monitoring=true`) + .set('kbn-xsrf', 'xxxx') + .send({ + name, + namespace: 'default', + }) + .expect(200); + + const policyId = res.body.item.id; + const enrollmentKey = await getEnrollmentKeyForPolicyId(policyId); + expect(enrollmentKey).not.empty(); + + const action = await getAgentActionsForEnrollmentKey(enrollmentKey.api_key); + + expect(action.type).to.be('POLICY_CHANGE'); + const agentPolicy = action.data.policy; + expect(agentPolicy.id).to.be(policyId); + // should have system inputs + expect(agentPolicy.inputs).length(2); + // should have default output + expect(agentPolicy.outputs.default).not.empty(); + }); + }); + + describe('POST /api/fleet/agent_policies/copy', () => { + const TEST_POLICY_ID = `policy1`; + + it('should create an enrollment key and an agent action `POLICY_CHANGE` for the policy', async () => { + const name = `test-${Date.now()}`; + + const res = await supertest + .post(`/api/fleet/agent_policies/${TEST_POLICY_ID}/copy`) + .set('kbn-xsrf', 'xxxx') + .send({ + name, + description: 'Test', + }) + .expect(200); + + const policyId = res.body.item.id; + const enrollmentKey = await getEnrollmentKeyForPolicyId(policyId); + expect(enrollmentKey).not.empty(); + + const action = await getAgentActionsForEnrollmentKey(enrollmentKey.api_key); + expect(action.type).to.be('POLICY_CHANGE'); + expect(action.data.policy.id).to.be(policyId); + }); + }); + }); +} diff --git a/x-pack/test/ingest_manager_api_integration/apis/agent_policy/index.js b/x-pack/test/ingest_manager_api_integration/apis/agent_policy/index.js index a513e7991fa7..da608b7057c0 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/agent_policy/index.js +++ b/x-pack/test/ingest_manager_api_integration/apis/agent_policy/index.js @@ -6,6 +6,7 @@ export default function loadTests({ loadTestFile }) { describe('Ingest Manager Endpoints', () => { + loadTestFile(require.resolve('./agent_policy_with_agents_setup')); loadTestFile(require.resolve('./agent_policy')); }); } diff --git a/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_multiple.ts b/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_multiple.ts new file mode 100644 index 000000000000..82072f59a482 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/epm/install_remove_multiple.ts @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { skipIfNoDockerRegistry } from '../../helpers'; + +export default function (providerContext: FtrProviderContext) { + const { getService } = providerContext; + const kibanaServer = getService('kibanaServer'); + const supertest = getService('supertest'); + const dockerServers = getService('dockerServers'); + const server = dockerServers.get('registry'); + const pkgName = 'all_assets'; + const pkgVersion = '0.1.0'; + const pkgKey = `${pkgName}-${pkgVersion}`; + const experimentalPkgName = 'experimental'; + const experimentalPkgKey = `${experimentalPkgName}-${pkgVersion}`; + const experimental2PkgName = 'experimental2'; + const experimental2PkgKey = `${experimental2PkgName}-${pkgVersion}`; + + const uninstallPackage = async (pkg: string) => { + await supertest.delete(`/api/fleet/epm/packages/${pkg}`).set('kbn-xsrf', 'xxxx'); + }; + const installPackage = async (pkg: string) => { + await supertest + .post(`/api/fleet/epm/packages/${pkg}`) + .set('kbn-xsrf', 'xxxx') + .send({ force: true }); + }; + + const installPackages = async (pkgs: string[]) => { + const installingPackagesPromise = pkgs.map((pkg) => installPackage(pkg)); + return Promise.all(installingPackagesPromise); + }; + const uninstallPackages = async (pkgs: string[]) => { + const uninstallingPackagesPromise = pkgs.map((pkg) => uninstallPackage(pkg)); + return Promise.all(uninstallingPackagesPromise); + }; + const expectPkgFieldToExist = async ( + fields: any[], + fieldName: string, + exists: boolean = true + ) => { + const fieldExists = fields.find((field: { name: string }) => field.name === fieldName); + if (exists) { + expect(fieldExists).not.to.be(undefined); + } else { + expect(fieldExists).to.be(undefined); + } + }; + describe('installs and uninstalls multiple packages side effects', async () => { + skipIfNoDockerRegistry(providerContext); + before(async () => { + if (!server.enabled) return; + await installPackages([pkgKey, experimentalPkgKey, experimental2PkgKey]); + }); + after(async () => { + if (!server.enabled) return; + await uninstallPackages([pkgKey, experimentalPkgKey, experimental2PkgKey]); + }); + it('should create index patterns from all installed packages, experimental or beta', async () => { + const resIndexPatternLogs = await kibanaServer.savedObjects.get({ + type: 'index-pattern', + id: 'logs-*', + }); + + const fieldsLogs = JSON.parse(resIndexPatternLogs.attributes.fields); + + expectPkgFieldToExist(fieldsLogs, 'logs_test_name'); + expectPkgFieldToExist(fieldsLogs, 'logs_experimental_name'); + expectPkgFieldToExist(fieldsLogs, 'logs_experimental2_name'); + const resIndexPatternMetrics = await kibanaServer.savedObjects.get({ + type: 'index-pattern', + id: 'metrics-*', + }); + const fieldsMetrics = JSON.parse(resIndexPatternMetrics.attributes.fields); + expectPkgFieldToExist(fieldsMetrics, 'metrics_test_name'); + expectPkgFieldToExist(fieldsMetrics, 'metrics_experimental_name'); + expectPkgFieldToExist(fieldsMetrics, 'metrics_experimental2_name'); + }); + it('should correctly recreate index patterns when a package is uninstalled', async () => { + await uninstallPackage(experimental2PkgKey); + const resIndexPatternLogs = await kibanaServer.savedObjects.get({ + type: 'index-pattern', + id: 'logs-*', + }); + const fields = JSON.parse(resIndexPatternLogs.attributes.fields); + expectPkgFieldToExist(fields, 'logs_test_name'); + expectPkgFieldToExist(fields, 'logs_experimental_name'); + expectPkgFieldToExist(fields, 'logs_experimental2_name', false); + const resIndexPatternMetrics = await kibanaServer.savedObjects.get({ + type: 'index-pattern', + id: 'metrics-*', + }); + const fieldsMetrics = JSON.parse(resIndexPatternMetrics.attributes.fields); + + expectPkgFieldToExist(fieldsMetrics, 'metrics_test_name'); + expectPkgFieldToExist(fieldsMetrics, 'metrics_experimental_name'); + expectPkgFieldToExist(fieldsMetrics, 'metrics_experimental2_name', false); + }); + }); +} diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_logs/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_logs/fields/ecs.yml new file mode 100644 index 000000000000..4c18291b7c5a --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_logs/fields/ecs.yml @@ -0,0 +1,3 @@ +- name: logs_experimental_name + title: logs_experimental_title + type: keyword \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_logs/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_logs/fields/fields.yml new file mode 100644 index 000000000000..6e003ed0ad14 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_logs/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_logs/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_logs/manifest.yml new file mode 100644 index 000000000000..9ac3c68a0be9 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_logs/manifest.yml @@ -0,0 +1,9 @@ +title: Test Dataset + +type: logs + +elasticsearch: + index_template.mappings: + dynamic: false + index_template.settings: + index.lifecycle.name: reference diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_metrics/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_metrics/fields/ecs.yml new file mode 100644 index 000000000000..3cd2db230f43 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_metrics/fields/ecs.yml @@ -0,0 +1,3 @@ +- name: metrics_experimental_name + title: metrics_experimental_title + type: keyword \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_metrics/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_metrics/fields/fields.yml new file mode 100644 index 000000000000..6e003ed0ad14 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_metrics/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_metrics/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_metrics/manifest.yml new file mode 100644 index 000000000000..6bc20442bd43 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/data_stream/test_metrics/manifest.yml @@ -0,0 +1,3 @@ +title: Test Dataset + +type: metrics \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/docs/README.md b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/docs/README.md new file mode 100644 index 000000000000..8e524c4c71b5 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/docs/README.md @@ -0,0 +1,3 @@ +# Test package + +For testing side effects when installing and removing multiple packages diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/img/logo_overrides_64_color.svg b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/img/logo_overrides_64_color.svg new file mode 100644 index 000000000000..b03007a76ffc --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/img/logo_overrides_64_color.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/manifest.yml new file mode 100644 index 000000000000..9c83569a69cb --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental/0.1.0/manifest.yml @@ -0,0 +1,20 @@ +format_version: 1.0.0 +name: experimental +title: experimental integration +description: This is a test package for testing experimental packages +version: 0.1.0 +categories: [] +release: experimental +type: integration +license: basic + +requirement: + elasticsearch: + versions: '>7.7.0' + kibana: + versions: '>7.7.0' + +icons: + - src: '/img/logo_overrides_64_color.svg' + size: '16x16' + type: 'image/svg+xml' diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_logs/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_logs/fields/ecs.yml new file mode 100644 index 000000000000..dad07fa9637a --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_logs/fields/ecs.yml @@ -0,0 +1,3 @@ +- name: logs_experimental2_name + title: logs_experimental2_title + type: keyword \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_logs/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_logs/fields/fields.yml new file mode 100644 index 000000000000..6e003ed0ad14 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_logs/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_logs/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_logs/manifest.yml new file mode 100644 index 000000000000..9ac3c68a0be9 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_logs/manifest.yml @@ -0,0 +1,9 @@ +title: Test Dataset + +type: logs + +elasticsearch: + index_template.mappings: + dynamic: false + index_template.settings: + index.lifecycle.name: reference diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_metrics/fields/ecs.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_metrics/fields/ecs.yml new file mode 100644 index 000000000000..0b6a2efaacd3 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_metrics/fields/ecs.yml @@ -0,0 +1,3 @@ +- name: metrics_experimental2_name + title: metrics_experimental2_title + type: keyword \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_metrics/fields/fields.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_metrics/fields/fields.yml new file mode 100644 index 000000000000..6e003ed0ad14 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_metrics/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_metrics/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_metrics/manifest.yml new file mode 100644 index 000000000000..6bc20442bd43 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/data_stream/test_metrics/manifest.yml @@ -0,0 +1,3 @@ +title: Test Dataset + +type: metrics \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/docs/README.md b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/docs/README.md new file mode 100644 index 000000000000..8e524c4c71b5 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/docs/README.md @@ -0,0 +1,3 @@ +# Test package + +For testing side effects when installing and removing multiple packages diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/img/logo_overrides_64_color.svg b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/img/logo_overrides_64_color.svg new file mode 100644 index 000000000000..b03007a76ffc --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/img/logo_overrides_64_color.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/manifest.yml b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/manifest.yml new file mode 100644 index 000000000000..766835dbde03 --- /dev/null +++ b/x-pack/test/ingest_manager_api_integration/apis/fixtures/test_packages/experimental2/0.1.0/manifest.yml @@ -0,0 +1,20 @@ +format_version: 1.0.0 +name: experimental2 +title: experimental integration +description: This is a test package for testing experimental packages +version: 0.1.0 +categories: [] +release: experimental +type: integration +license: basic + +requirement: + elasticsearch: + versions: '>7.7.0' + kibana: + versions: '>7.7.0' + +icons: + - src: '/img/logo_overrides_64_color.svg' + size: '16x16' + type: 'image/svg+xml' diff --git a/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts b/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts index eea18863e3be..dff10daafbdb 100644 --- a/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts +++ b/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts @@ -157,6 +157,32 @@ export default function ({ getService }: FtrProviderContext) { }); }); } + + describe(`Index Lifecycle`, () => { + it('should query across indicies matching the Event Log index pattern', async () => { + await esArchiver.load('event_log_multiple_indicies'); + + const id = `421f2511-5cd1-44fd-95df-e0df83e354d5`; + + const { + body: { data, total }, + } = await findEvents(undefined, id, {}); + + expect(data.length).to.be(6); + expect(total).to.be(6); + + expect(data.map((foundEvent: IEvent) => foundEvent?.message)).to.eql([ + 'test 2020-10-28T15:19:53.825Z', + 'test 2020-10-28T15:19:54.849Z', + 'test 2020-10-28T15:19:54.881Z', + 'test 2020-10-28T15:19:55.913Z', + 'test 2020-10-28T15:19:55.938Z', + 'test 2020-10-28T15:19:55.962Z', + ]); + + await esArchiver.unload('event_log_multiple_indicies'); + }); + }); }); async function findEvents( diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts index 348ff35b2968..f34cb7594d28 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts @@ -57,8 +57,7 @@ export default function ({ getService }: FtrProviderContext) { const testHistoryIndex = '.kibana_task_manager_test_result'; const supertest = supertestAsPromised(url.format(config.get('servers.kibana'))); - // Failing: See https://github.com/elastic/kibana/issues/81853 - describe.skip('scheduling and running tasks', () => { + describe('scheduling and running tasks', () => { beforeEach( async () => await supertest.delete('/api/sample_tasks').set('kbn-xsrf', 'xxx').expect(200) ); @@ -673,7 +672,7 @@ export default function ({ getService }: FtrProviderContext) { const [scheduledTask] = (await currentTasks()).docs; expect(scheduledTask.id).to.eql(task.id); expect(scheduledTask.status).to.eql('claiming'); - expect(scheduledTask.attempts).to.eql(4); + expect(scheduledTask.attempts).to.be.greaterThan(3); }); }); }); diff --git a/x-pack/test/plugin_functional/config.ts b/x-pack/test/plugin_functional/config.ts index e7d96023f365..37d35662eb15 100644 --- a/x-pack/test/plugin_functional/config.ts +++ b/x-pack/test/plugin_functional/config.ts @@ -59,7 +59,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { apps: { ...xpackFunctionalConfig.get('apps'), resolverTest: { - pathname: '/app/resolver_test', + pathname: '/app/resolverTest', }, }, diff --git a/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts b/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts index 2b7ae3e57659..005d516e2943 100644 --- a/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts +++ b/x-pack/test/plugin_functional/test_suites/global_search/global_search_bar.ts @@ -8,7 +8,8 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { - describe('GlobalSearchBar', function () { + // See: https://github.com/elastic/kibana/issues/81397 + describe.skip('GlobalSearchBar', function () { const { common } = getPageObjects(['common']); const find = getService('find'); const testSubjects = getService('testSubjects'); diff --git a/x-pack/test/plugin_functional/test_suites/global_search/index.ts b/x-pack/test/plugin_functional/test_suites/global_search/index.ts index a54e6933be69..f43e293c30fd 100644 --- a/x-pack/test/plugin_functional/test_suites/global_search/index.ts +++ b/x-pack/test/plugin_functional/test_suites/global_search/index.ts @@ -7,7 +7,8 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { - describe('GlobalSearch API', function () { + // See https://github.com/elastic/kibana/issues/81397 + describe.skip('GlobalSearch API', function () { this.tags('ciGroup7'); loadTestFile(require.resolve('./global_search_api')); loadTestFile(require.resolve('./global_search_providers')); diff --git a/x-pack/test/plugin_functional/test_suites/resolver/index.ts b/x-pack/test/plugin_functional/test_suites/resolver/index.ts index 9cc2751a4287..8cdf54a50bc5 100644 --- a/x-pack/test/plugin_functional/test_suites/resolver/index.ts +++ b/x-pack/test/plugin_functional/test_suites/resolver/index.ts @@ -10,18 +10,18 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const pageObjects = getPageObjects(['common']); const testSubjects = getService('testSubjects'); - describe('Resolver embeddable test app', function () { + describe('Resolver test app', function () { this.tags('ciGroup7'); beforeEach(async function () { await pageObjects.common.navigateToApp('resolverTest'); }); - it('renders a container div for the embeddable', async function () { - await testSubjects.existOrFail('resolverEmbeddableContainer'); - }); - it('renders resolver', async function () { - await testSubjects.existOrFail('resolverEmbeddable'); + it('renders at least one node, one node-list, one edge line, and graph controls', async function () { + await testSubjects.existOrFail('resolver:node'); + await testSubjects.existOrFail('resolver:node-list'); + await testSubjects.existOrFail('resolver:graph:edgeline'); + await testSubjects.existOrFail('resolver:graph-controls'); }); }); } diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts index 1af9ec88df85..b45c08242362 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts @@ -262,11 +262,21 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await esArchiver.load('endpoint/resolver_tree/library_events', { useCreate: true }); await queryBar.setQuery(''); await queryBar.submitQuery(); - const expectedLibraryData = ['329 network', '1 library', '1 library']; + const expectedLibraryData = [ + '1 authentication', + '1 session', + '329 network', + '1 library', + '1 library', + ]; await pageObjects.hosts.navigateToEventsPanel(); await pageObjects.hosts.executeQueryAndOpenResolver( 'event.dataset : endpoint.events.library' ); + // This lines will move the resolver view for clear visibility of the related events. + for (let i = 0; i < 7; i++) { + await (await testSubjects.find('resolver:graph-controls:west-button')).click(); + } await pageObjects.hosts.runNodeEvents(expectedLibraryData); }); }); diff --git a/x-pack/test/security_solution_endpoint/page_objects/hosts_page.ts b/x-pack/test/security_solution_endpoint/page_objects/hosts_page.ts index 3301217e41a9..988fadbbdfe3 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/hosts_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/hosts_page.ts @@ -127,6 +127,7 @@ export function SecurityHostsPageProvider({ getService, getPageObjects }: FtrPro expect(EventName).to.equal(linkText); expect(EventName).to.equal(expectedData[i]); } + await testSubjects.click('full-screen'); }, /** * Navigate to Events Panel @@ -146,7 +147,6 @@ export function SecurityHostsPageProvider({ getService, getPageObjects }: FtrPro await queryBar.submitQuery(); await testSubjects.click('full-screen'); await testSubjects.click('investigate-in-resolver-button'); - await testSubjects.click('full-screen'); }, }; } diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index 057441304f09..5c76a11315a5 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -22,13 +22,14 @@ }, "references": [ { "path": "../src/core/tsconfig.json" }, + { "path": "../src/plugins/inspector/tsconfig.json" }, { "path": "../src/plugins/kibana_legacy/tsconfig.json" }, { "path": "../src/plugins/kibana_react/tsconfig.json" }, { "path": "../src/plugins/kibana_usage_collection/tsconfig.json" }, { "path": "../src/plugins/kibana_utils/tsconfig.json" }, { "path": "../src/plugins/newsfeed/tsconfig.json" }, - { "path": "../src/plugins/telemetry/tsconfig.json" }, { "path": "../src/plugins/telemetry_collection_manager/tsconfig.json" }, + { "path": "../src/plugins/telemetry/tsconfig.json" }, { "path": "../src/plugins/url_forwarding/tsconfig.json" }, { "path": "../src/plugins/usage_collection/tsconfig.json" }, { "path": "./plugins/global_search/tsconfig.json" }, diff --git a/x-pack/typings/hapi.d.ts b/x-pack/typings/hapi.d.ts deleted file mode 100644 index dd9e0239aeee..000000000000 --- a/x-pack/typings/hapi.d.ts +++ /dev/null @@ -1,23 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import 'hapi'; - -import { ActionsPlugin, ActionsClient } from '../plugins/actions/server'; -import { AlertingPlugin, AlertsClient } from '../plugins/alerts/server'; -import { TaskManager } from '../plugins/task_manager/server'; - -declare module 'hapi' { - interface Request { - getActionsClient?: () => ActionsClient; - getAlertsClient?: () => AlertsClient; - } - interface PluginProperties { - actions?: ActionsPlugin; - alerts?: AlertingPlugin; - task_manager?: TaskManager; - } -} diff --git a/x-pack/typings/index.d.ts b/x-pack/typings/index.d.ts index 90e2fa586874..3168026a8679 100644 --- a/x-pack/typings/index.d.ts +++ b/x-pack/typings/index.d.ts @@ -22,18 +22,8 @@ declare module '*.svg' { export default content; } -type MethodKeysOf = { - [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never; -}[keyof T]; - -type PublicMethodsOf = Pick>; - declare module 'axios/lib/adapters/xhr'; -type Writable = { - -readonly [K in keyof T]: T[K]; -}; - // Storybook references this module. It's @ts-ignored in the codebase but when // built into its dist it strips that out. Add it here to avoid a type checking // error. diff --git a/x-pack/typings/jest.d.ts b/x-pack/typings/jest.d.ts deleted file mode 100644 index 488df5ad9237..000000000000 --- a/x-pack/typings/jest.d.ts +++ /dev/null @@ -1,14 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -type MockedKeys = { [P in keyof T]: jest.Mocked> }; - -type DeeplyMockedKeys = { - [P in keyof T]: T[P] extends (...args: any[]) => any - ? jest.MockInstance, Parameters> - : DeeplyMockedKeys; -} & - T; diff --git a/yarn.lock b/yarn.lock index dc6c7be1e553..560a0e312b44 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8153,9 +8153,9 @@ camelize@^1.0.0: integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs= caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001043, caniuse-lite@^1.0.30001097: - version "1.0.30001114" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001114.tgz#2e88119afb332ead5eaa330e332e951b1c4bfea9" - integrity sha512-ml/zTsfNBM+T1+mjglWRPgVsu2L76GAaADKX5f4t0pbhttEp0WMawJsHDYlFkVZkoA+89uvBRrVrEE4oqenzXQ== + version "1.0.30001150" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001150.tgz" + integrity sha512-kiNKvihW0m36UhAFnl7bOAv0i1K1f6wpfVtTF5O5O82XzgtBnb05V0XeV3oZ968vfg2sRNChsHw8ASH2hDfoYQ== capture-exit@^2.0.0: version "2.0.0" @@ -8227,7 +8227,7 @@ chai@3.5.0: deep-eql "^0.1.3" type-detect "^1.0.0" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2, chalk@~2.4.1: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2, chalk@~2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -17217,6 +17217,14 @@ jest-serializer@^26.5.0: "@types/node" "*" graceful-fs "^4.2.4" +jest-silent-reporter@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/jest-silent-reporter/-/jest-silent-reporter-0.2.1.tgz#554dd62b800989cdbcfba22bf30a1c0db6ad289c" + integrity sha512-nEO3oOFHtEXFjlRCbJOlvEWA7ZHyyyvMsU4WHuAhinYBOI4PiX1EIbsZfQZ/cxHcYliHBU9zY8bPxMPdBGksYw== + dependencies: + chalk "^2.3.1" + jest-util "^24.0.0" + jest-snapshot@^26.3.0, jest-snapshot@^26.4.2: version "26.4.2" resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.4.2.tgz#87d3ac2f2bd87ea8003602fbebd8fcb9e94104f6"