diff --git a/dev_docs/kibana_platform_plugin_intro.mdx b/dev_docs/kibana_platform_plugin_intro.mdx
index bf009a3c5251..f70c42cb520c 100644
--- a/dev_docs/kibana_platform_plugin_intro.mdx
+++ b/dev_docs/kibana_platform_plugin_intro.mdx
@@ -68,7 +68,7 @@ We will continue to focus on adding clarity around these types of services and w
### Core services
-Sometimes referred to just as Core, Core services provide the most basic and fundamental tools neccessary for building a plugin, like creating saved objects,
+Sometimes referred to just as provide the most basic and fundamental tools neccessary for building a plugin, like creating saved objects,
routing, application registration, notifications and . The Core platform is not a plugin itself, although
there are some plugins that provide platform functionality. We call these .
@@ -141,4 +141,4 @@ plugins to customize the Kibana experience. Examples of extension points are:
## Follow up material
-Learn how to build your own plugin by following
+Learn how to build your own plugin by following .
diff --git a/dev_docs/kibana_server_core_components.mdx b/dev_docs/kibana_server_core_components.mdx
new file mode 100644
index 000000000000..701043059be0
--- /dev/null
+++ b/dev_docs/kibana_server_core_components.mdx
@@ -0,0 +1,30 @@
+---
+id: kibServerAndCoreComponents
+slug: /kibana-dev-docs/core-intro
+title: Core components
+summary: An introduction to the Kibana server and core components.
+date: 2021-02-26
+tags: ['kibana','onboarding', 'dev', 'architecture']
+---
+
+Core is a set of systems (frontend, backend etc.) that Kibana and its plugins are built on top of.
+
+## Integration with the "legacy" Kibana
+
+Most of the existing core functionality is still spread over "legacy" Kibana and it will take some time to upgrade it.
+Kibana is started using existing "legacy" CLI that bootstraps `core` which in turn creates the "legacy" Kibana server.
+At the moment `core` manages HTTP connections, handles TLS configuration and base path proxy. All requests to Kibana server
+will hit HTTP server exposed by the `core` first and it will decide whether request can be solely handled by the new
+platform or request should be proxied to the "legacy" Kibana. This setup allows `core` to gradually introduce any "pre-route"
+processing logic, expose new routes or replace old ones handled by the "legacy" Kibana currently.
+
+Once config has been loaded and some of its parts were validated by the `core` it's passed to the "legacy" Kibana where
+it will be additionally validated so that we can make config validation stricter with the new config validation system.
+Even though the new validation system provided by the `core` is also based on Joi internally it is complemented with custom
+rules tailored to our needs (e.g. `byteSize`, `duration` etc.). That means that config values that were previously accepted
+by the "legacy" Kibana may be rejected by the `core` now.
+
+### Logging
+`core` has its own and will output log records directly (e.g. to file or terminal) when configured. When no specific configuration is provided, logs are forwarded to the "legacy" Kibana so that they look the same as the rest of the
+log records throughout Kibana.
+
diff --git a/docs/settings/task-manager-settings.asciidoc b/docs/settings/task-manager-settings.asciidoc
index 507e54349276..52878279ff06 100644
--- a/docs/settings/task-manager-settings.asciidoc
+++ b/docs/settings/task-manager-settings.asciidoc
@@ -27,6 +27,6 @@ Task Manager runs background tasks by polling for work on an interval. You can
| `xpack.task_manager.max_workers`
| The maximum number of tasks that this Kibana instance will run simultaneously. Defaults to 10.
-
+ Starting in 8.0, it will not be possible to set the value greater than 100.
|===
diff --git a/docs/user/alerting/defining-alerts.asciidoc b/docs/user/alerting/defining-alerts.asciidoc
index 27f3a6c7309c..8f1a0f06f75a 100644
--- a/docs/user/alerting/defining-alerts.asciidoc
+++ b/docs/user/alerting/defining-alerts.asciidoc
@@ -95,6 +95,10 @@ Some cases exist where the variable values will be "escaped", when used in a con
Mustache also supports "triple braces" of the form `{{{variable name}}}`, which indicates no escaping should be done at all. Care should be used when using this form, as it could end up rendering the variable content in such a way as to make the resulting parameter invalid or formatted incorrectly.
+Each alert type defines additional variables as properties of the variable `context`. For example, if an alert type defines a variable `value`, it can be used in an action parameter as `{{context.value}}`.
+
+For diagnostic or exploratory purposes, action variables whose values are objects, such as `context`, can be referenced directly as variables. The resulting value will be a JSON representation of the object. For example, if an action parameter includes `{{context}}`, it will expand to the JSON representation of all the variables and values provided by the alert type.
+
You can attach more than one action. Clicking the "Add action" button will prompt you to select another alert type and repeat the above steps again.
[role="screenshot"]
diff --git a/package.json b/package.json
index 6e5feac8a16a..0baafd101dfb 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,7 @@
"kbn:watch": "node scripts/kibana --dev --logging.json=false",
"build:types": "rm -rf ./target/types && tsc --p tsconfig.types.json",
"docs:acceptApiChanges": "node --max-old-space-size=6144 scripts/check_published_api_changes.js --accept",
- "kbn:bootstrap": "node scripts/build_ts_refs",
+ "kbn:bootstrap": "node scripts/build_ts_refs --ignore-type-failures",
"spec_to_console": "node scripts/spec_to_console",
"backport-skip-ci": "backport --prDescription \"[skip-ci]\"",
"storybook": "node scripts/storybook",
@@ -82,7 +82,7 @@
"**/load-grunt-config/lodash": "^4.17.21",
"**/minimist": "^1.2.5",
"**/node-jose/node-forge": "^0.10.0",
- "**/prismjs": "1.22.0",
+ "**/prismjs": "1.23.0",
"**/react-syntax-highlighter": "^15.3.1",
"**/react-syntax-highlighter/**/highlight.js": "^10.4.1",
"**/request": "^2.88.2",
diff --git a/src/core/CONVENTIONS.md b/src/core/CONVENTIONS.md
index 6a519d44de0d..67476af87b6d 100644
--- a/src/core/CONVENTIONS.md
+++ b/src/core/CONVENTIONS.md
@@ -202,14 +202,14 @@ export class MyPlugin implements Plugin {
}
```
-Prefer the pattern shown above, using `core.getStartServices()`, rather than store local references retrieved from `start`.
+Prefer the pattern shown above, using `core.getStartServices()`, rather than store local references retrieved from `start`.
**Bad:**
```ts
export class MyPlugin implements Plugin {
// Anti pattern
private coreStart?: CoreStart;
- private depsStart?: DepsStart;
+ private depsStart?: DepsStart;
public setup(core) {
core.application.register({
@@ -220,7 +220,7 @@ export class MyPlugin implements Plugin {
return renderApp(this.coreStart, this.depsStart, params);
}
});
- }
+ }
public start(core, deps) {
// Anti pattern
@@ -361,5 +361,5 @@ Migration example from the legacy format is available in `src/core/MIGRATION_EXA
### Naming conventions
-Export start and setup contracts as `MyPluginStart` and `MyPluginSetup`.
+Export start and setup contracts as `MyPluginStart` and `MyPluginSetup`.
This avoids naming clashes, if everyone exported them simply as `Start` and `Setup`.
diff --git a/src/core/CORE_CONVENTIONS.md b/src/core/CORE_CONVENTIONS.md
index 76f3be159525..1cd997d570b6 100644
--- a/src/core/CORE_CONVENTIONS.md
+++ b/src/core/CORE_CONVENTIONS.md
@@ -15,7 +15,7 @@ area of Core API's and does not apply to internal types.
- 1.1 All API types must be exported from the top-level `server` or `public`
directories.
-
+
```ts
// -- good --
import { IRouter } from 'src/core/server';
@@ -23,15 +23,15 @@ area of Core API's and does not apply to internal types.
// -- bad --
import { IRouter } from 'src/core/server/http/router.ts';
```
-
+
> Why? This is required for generating documentation from our inline
> typescript doc comments, makes it easier for API consumers to find the
> relevant types and creates a clear distinction between external and
> internal types.
-
+
- 1.2 Classes must not be exposed directly. Instead, use a separate type,
prefixed with an 'I', to describe the public contract of the class.
-
+
```ts
// -- good (alternative 1) --
/**
@@ -66,14 +66,14 @@ area of Core API's and does not apply to internal types.
```
> Why? Classes' private members form part of their type signature making it
- > impossible to mock a dependency typed as a `class`.
+ > impossible to mock a dependency typed as a `class`.
>
> Until we can use ES private field support in Typescript 3.8
> https://github.com/elastic/kibana/issues/54906 we have two alternatives
> each with their own pro's and cons:
>
> #### Using a derived class (alternative 1)
- >
+ >
> Pro's:
> - TSDoc comments are located with the source code
> - The class acts as a single source of type information
@@ -81,12 +81,12 @@ area of Core API's and does not apply to internal types.
> Con's:
> - "Go to definition" first takes you to where the type gets derived
> requiring a second "Go to definition" to navigate to the type source.
- >
+ >
> #### Using a separate interface (alternative 2)
> Pro's:
> - Creates an explicit external API contract
> - "Go to definition" will take you directly to the type definition.
- >
+ >
> Con's:
> - TSDoc comments are located with the interface not next to the
> implementation source code.
diff --git a/src/core/README.md b/src/core/README.md
index 799cdb5c799a..4dd045f37b48 100644
--- a/src/core/README.md
+++ b/src/core/README.md
@@ -9,7 +9,7 @@ Core Plugin API Documentation:
- [Conventions for Plugins](./CONVENTIONS.md)
- [Testing Kibana Plugins](./TESTING.md)
- [Kibana Platform Plugin API](./docs/developer/architecture/kibana-platform-plugin-api.asciidoc )
-
+
Internal Documentation:
- [Saved Objects Migrations](./server/saved_objects/migrations/README.md)
@@ -18,18 +18,18 @@ Internal Documentation:
Most of the existing core functionality is still spread over "legacy" Kibana and it will take some time to upgrade it.
Kibana is started using existing "legacy" CLI that bootstraps `core` which in turn creates the "legacy" Kibana server.
At the moment `core` manages HTTP connections, handles TLS configuration and base path proxy. All requests to Kibana server
-will hit HTTP server exposed by the `core` first and it will decide whether request can be solely handled by the new
+will hit HTTP server exposed by the `core` first and it will decide whether request can be solely handled by the new
platform or request should be proxied to the "legacy" Kibana. This setup allows `core` to gradually introduce any "pre-route"
processing logic, expose new routes or replace old ones handled by the "legacy" Kibana currently.
-Once config has been loaded and some of its parts were validated by the `core` it's passed to the "legacy" Kibana where
+Once config has been loaded and some of its parts were validated by the `core` it's passed to the "legacy" Kibana where
it will be additionally validated so that we can make config validation stricter with the new config validation system.
-Even though the new validation system provided by the `core` is also based on Joi internally it is complemented with custom
+Even though the new validation system provided by the `core` is also based on Joi internally it is complemented with custom
rules tailored to our needs (e.g. `byteSize`, `duration` etc.). That means that config values that were previously accepted
by the "legacy" Kibana may be rejected by the `core` now.
### Logging
-`core` has its own [logging system](./server/logging/README.mdx) and will output log records directly (e.g. to file or terminal) when configured. When no
+`core` has its own [logging system](./server/logging/README.mdx) and will output log records directly (e.g. to file or terminal) when configured. When no
specific configuration is provided, logs are forwarded to the "legacy" Kibana so that they look the same as the rest of the
log records throughout Kibana.
diff --git a/src/dev/bazel_workspace_status.js b/src/dev/bazel_workspace_status.js
index 3c3ef1574cd8..c7ae05ce4874 100644
--- a/src/dev/bazel_workspace_status.js
+++ b/src/dev/bazel_workspace_status.js
@@ -17,13 +17,21 @@
// If the script exits with non-zero code, it's considered as a failure
// and the output will be discarded.
-(async () => {
- const execa = require('execa');
+(() => {
+ const cp = require('child_process');
const os = require('os');
- async function runCmd(cmd, args) {
+ function runCmd(cmd, args) {
try {
- return await execa(cmd, args);
+ const spawnResult = cp.spawnSync(cmd, args);
+ const exitCode = spawnResult.status !== null ? spawnResult.status : 1;
+ const stdoutStr = spawnResult.stdout.toString();
+ const stdout = stdoutStr ? stdoutStr.trim() : null;
+
+ return {
+ exitCode,
+ stdout,
+ };
} catch (e) {
return { exitCode: 1 };
}
@@ -31,29 +39,25 @@
// Git repo
const kbnGitOriginName = process.env.KBN_GIT_ORIGIN_NAME || 'origin';
- const repoUrlCmdResult = await runCmd('git', [
- 'config',
- '--get',
- `remote.${kbnGitOriginName}.url`,
- ]);
+ const repoUrlCmdResult = runCmd('git', ['config', '--get', `remote.${kbnGitOriginName}.url`]);
if (repoUrlCmdResult.exitCode === 0) {
// Only output REPO_URL when found it
console.log(`REPO_URL ${repoUrlCmdResult.stdout}`);
}
// Commit SHA
- const commitSHACmdResult = await runCmd('git', ['rev-parse', 'HEAD']);
+ const commitSHACmdResult = runCmd('git', ['rev-parse', 'HEAD']);
if (commitSHACmdResult.exitCode === 0) {
console.log(`COMMIT_SHA ${commitSHACmdResult.stdout}`);
// Branch
- const gitBranchCmdResult = await runCmd('git', ['rev-parse', '--abbrev-ref', 'HEAD']);
+ const gitBranchCmdResult = runCmd('git', ['rev-parse', '--abbrev-ref', 'HEAD']);
if (gitBranchCmdResult.exitCode === 0) {
console.log(`GIT_BRANCH ${gitBranchCmdResult.stdout}`);
}
// Tree status
- const treeStatusCmdResult = await runCmd('git', ['diff-index', '--quiet', 'HEAD', '--']);
+ const treeStatusCmdResult = runCmd('git', ['diff-index', '--quiet', 'HEAD', '--']);
const treeStatusVarStr = 'GIT_TREE_STATUS';
if (treeStatusCmdResult.exitCode === 0) {
console.log(`${treeStatusVarStr} Clean`);
@@ -64,7 +68,7 @@
// Host
if (process.env.CI) {
- const hostCmdResult = await runCmd('hostname');
+ const hostCmdResult = runCmd('hostname');
const hostStr = hostCmdResult.stdout.split('-').slice(0, -1).join('-');
const coresStr = os.cpus().filter((cpu, index) => {
return !cpu.model.includes('Intel') || index % 2 === 1;
diff --git a/src/dev/typescript/build_ts_refs_cli.ts b/src/dev/typescript/build_ts_refs_cli.ts
index a073e5862327..42b278ce6450 100644
--- a/src/dev/typescript/build_ts_refs_cli.ts
+++ b/src/dev/typescript/build_ts_refs_cli.ts
@@ -18,9 +18,24 @@ import { concurrentMap } from './concurrent_map';
const CACHE_WORKING_DIR = Path.resolve(REPO_ROOT, 'data/ts_refs_output_cache');
+const TS_ERROR_REF = /\sTS\d{1,6}:\s/;
+
+const isTypeFailure = (error: any) =>
+ error.exitCode === 1 &&
+ error.stderr === '' &&
+ typeof error.stdout === 'string' &&
+ TS_ERROR_REF.test(error.stdout);
+
export async function runBuildRefsCli() {
run(
async ({ log, flags }) => {
+ if (process.env.BUILD_TS_REFS_DISABLE === 'true' && !flags.force) {
+ log.info(
+ 'Building ts refs is disabled because the BUILD_TS_REFS_DISABLE environment variable is set to "true". Pass `--force` to run the build anyway.'
+ );
+ return;
+ }
+
const outDirs = getOutputsDeep(REF_CONFIG_PATHS);
const cacheEnabled = process.env.BUILD_TS_REFS_CACHE_ENABLE !== 'false' && !!flags.cache;
@@ -48,7 +63,20 @@ export async function runBuildRefsCli() {
await outputCache.initCaches();
}
- await buildAllTsRefs(log);
+ try {
+ await buildAllTsRefs(log);
+ log.success('ts refs build successfully');
+ } catch (error) {
+ const typeFailure = isTypeFailure(error);
+
+ if (flags['ignore-type-failures'] && typeFailure) {
+ log.warning(
+ 'tsc reported type errors but we are ignoring them for now, to see them please run `node scripts/type_check` or `node scripts/build_ts_refs` without the `--ignore-type-failures` flag.'
+ );
+ } else {
+ throw error;
+ }
+ }
if (outputCache && doCapture) {
await outputCache.captureCache(Path.resolve(REPO_ROOT, 'target/ts_refs_cache'));
@@ -61,10 +89,16 @@ export async function runBuildRefsCli() {
{
description: 'Build TypeScript projects',
flags: {
- boolean: ['clean', 'cache'],
+ boolean: ['clean', 'force', 'cache', 'ignore-type-failures'],
default: {
cache: true,
},
+ help: `
+ --force Run the build even if the BUILD_TS_REFS_DISABLE is set to "true"
+ --clean Delete outDirs for each ts project before building
+ --no-cache Disable fetching/extracting outDir caches based on the mergeBase with upstream
+ --ignore-type-failures If tsc reports type errors, ignore them and just log a small warning.
+ `,
},
log: {
defaultLevel: 'debug',
diff --git a/src/plugins/maps_legacy/public/map/_legend.scss b/src/plugins/maps_legacy/public/map/_legend.scss
index 2c50e214c248..27016840cfab 100644
--- a/src/plugins/maps_legacy/public/map/_legend.scss
+++ b/src/plugins/maps_legacy/public/map/_legend.scss
@@ -1,6 +1,6 @@
.visMapLegend {
@include fontSize(11px);
- @include euiBottomShadowMedium($color: $euiShadowColorLarge, $opacity: .1);
+ @include euiBottomShadowMedium($color: $euiShadowColorLarge);
font-family: $euiFontFamily;
font-weight: $euiFontWeightMedium;
line-height: $euiLineHeight;
diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts
index 6e9225041b19..7e43c8f68437 100644
--- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts
+++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts
@@ -30,10 +30,8 @@ export function getConnections({
if (!paths) {
return [];
}
- const isEnvironmentSelected =
- environment && environment !== ENVIRONMENT_ALL.value;
- if (serviceName || isEnvironmentSelected) {
+ if (serviceName || environment) {
paths = paths.filter((path) => {
return (
path
@@ -46,7 +44,7 @@ export function getConnections({
return false;
}
- if (!environment) {
+ if (!environment || environment === ENVIRONMENT_ALL.value) {
return true;
}
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/index.tsx
index 2d442744bb13..8b278204ca2c 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/index.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/index.tsx
@@ -21,6 +21,7 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
+import semverLt from 'semver/functions/lt';
import { useUIExtension } from '../../../../hooks/use_ui_extension';
import { PAGE_ROUTING_PATHS, PLUGIN_ID } from '../../../../constants';
@@ -80,7 +81,7 @@ export function Detail() {
packageInfo &&
'savedObject' in packageInfo &&
packageInfo.savedObject &&
- packageInfo.savedObject.attributes.version < packageInfo.latestVersion;
+ semverLt(packageInfo.savedObject.attributes.version, packageInfo.latestVersion);
// Fetch package info
const { data: packageInfoData, error: packageInfoError, isLoading } = useGetPackageInfoByKey(
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/settings/settings.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/settings/settings.tsx
index e69d148f89e0..94c03f76cdda 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/settings/settings.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/epm/screens/detail/settings/settings.tsx
@@ -8,6 +8,8 @@
import React, { memo } from 'react';
import styled from 'styled-components';
import { FormattedMessage } from '@kbn/i18n/react';
+import semverLt from 'semver/functions/lt';
+
import { EuiTitle, EuiFlexGroup, EuiFlexItem, EuiText, EuiSpacer } from '@elastic/eui';
import { InstallStatus, PackageInfo } from '../../../../../types';
@@ -57,7 +59,9 @@ export const SettingsPage: React.FC = memo(({ packageInfo }: Props) => {
});
const { status: installationStatus, version: installedVersion } = getPackageInstallStatus(name);
const packageHasUsages = !!packagePoliciesData?.total;
- const updateAvailable = installedVersion && installedVersion < latestVersion ? true : false;
+ const updateAvailable =
+ installedVersion && semverLt(installedVersion, latestVersion) ? true : false;
+
const isViewingOldPackage = version < latestVersion;
// hide install/remove options if the user has version of the package is installed
// and this package is out of date or if they do have a version installed but it's not this one
diff --git a/x-pack/plugins/lists/server/routes/delete_list_route.ts b/x-pack/plugins/lists/server/routes/delete_list_route.ts
index 4732b25dbf5e..3e9b76a1b330 100644
--- a/x-pack/plugins/lists/server/routes/delete_list_route.ts
+++ b/x-pack/plugins/lists/server/routes/delete_list_route.ts
@@ -19,6 +19,7 @@ import {
} from '../../common/schemas';
import { getSavedObjectType } from '../services/exception_lists/utils';
import { ExceptionListClient } from '../services/exception_lists/exception_list_client';
+import { escapeQuotes } from '../services/utils/escape_query';
import { getExceptionListClient, getListClient } from '.';
@@ -142,7 +143,7 @@ const getReferencedExceptionLists = async (
(item) =>
`${getSavedObjectType({
namespaceType: item.namespace_type,
- })}.attributes.list_id: ${item.list_id}`
+ })}.attributes.list_id: "${escapeQuotes(item.list_id)}"`
)
.join(' OR ');
return exceptionLists.findExceptionList({
diff --git a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.test.ts b/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.test.ts
index 0d3dd2d9b65c..3a2b12c35891 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.test.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.test.ts
@@ -18,7 +18,18 @@ describe('find_exception_list_items', () => {
savedObjectType: ['exception-list'],
});
expect(filter).toEqual(
- '(exception-list.attributes.list_type: item AND exception-list.attributes.list_id: some-list-id)'
+ '(exception-list.attributes.list_type: item AND exception-list.attributes.list_id: "some-list-id")'
+ );
+ });
+
+ test('It should create a filter escaping quotes in list ids', () => {
+ const filter = getExceptionListsItemFilter({
+ filter: [],
+ listId: ['list-id-"-with-quote'],
+ savedObjectType: ['exception-list'],
+ });
+ expect(filter).toEqual(
+ '(exception-list.attributes.list_type: item AND exception-list.attributes.list_id: "list-id-\\"-with-quote")'
);
});
@@ -29,7 +40,7 @@ describe('find_exception_list_items', () => {
savedObjectType: ['exception-list'],
});
expect(filter).toEqual(
- '((exception-list.attributes.list_type: item AND exception-list.attributes.list_id: some-list-id) AND exception-list.attributes.name: "Sample Endpoint Exception List")'
+ '((exception-list.attributes.list_type: item AND exception-list.attributes.list_id: "some-list-id") AND exception-list.attributes.name: "Sample Endpoint Exception List")'
);
});
@@ -40,7 +51,7 @@ describe('find_exception_list_items', () => {
savedObjectType: ['exception-list', 'exception-list-agnostic'],
});
expect(filter).toEqual(
- '(exception-list.attributes.list_type: item AND exception-list.attributes.list_id: list-1) OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: list-2)'
+ '(exception-list.attributes.list_type: item AND exception-list.attributes.list_id: "list-1") OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: "list-2")'
);
});
@@ -51,7 +62,7 @@ describe('find_exception_list_items', () => {
savedObjectType: ['exception-list', 'exception-list-agnostic'],
});
expect(filter).toEqual(
- '((exception-list.attributes.list_type: item AND exception-list.attributes.list_id: list-1) AND exception-list.attributes.name: "Sample Endpoint Exception List") OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: list-2)'
+ '((exception-list.attributes.list_type: item AND exception-list.attributes.list_id: "list-1") AND exception-list.attributes.name: "Sample Endpoint Exception List") OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: "list-2")'
);
});
@@ -62,7 +73,7 @@ describe('find_exception_list_items', () => {
savedObjectType: ['exception-list', 'exception-list-agnostic', 'exception-list-agnostic'],
});
expect(filter).toEqual(
- '(exception-list.attributes.list_type: item AND exception-list.attributes.list_id: list-1) OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: list-2) OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: list-3)'
+ '(exception-list.attributes.list_type: item AND exception-list.attributes.list_id: "list-1") OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: "list-2") OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: "list-3")'
);
});
@@ -73,7 +84,7 @@ describe('find_exception_list_items', () => {
savedObjectType: ['exception-list', 'exception-list-agnostic', 'exception-list-agnostic'],
});
expect(filter).toEqual(
- '((exception-list.attributes.list_type: item AND exception-list.attributes.list_id: list-1) AND exception-list.attributes.name: "Sample Endpoint Exception List") OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: list-2) OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: list-3)'
+ '((exception-list.attributes.list_type: item AND exception-list.attributes.list_id: "list-1") AND exception-list.attributes.name: "Sample Endpoint Exception List") OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: "list-2") OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: "list-3")'
);
});
@@ -88,7 +99,7 @@ describe('find_exception_list_items', () => {
savedObjectType: ['exception-list', 'exception-list-agnostic', 'exception-list-agnostic'],
});
expect(filter).toEqual(
- '((exception-list.attributes.list_type: item AND exception-list.attributes.list_id: list-1) AND exception-list.attributes.name: "Sample Endpoint Exception List 1") OR ((exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: list-2) AND exception-list.attributes.name: "Sample Endpoint Exception List 2") OR ((exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: list-3) AND exception-list.attributes.name: "Sample Endpoint Exception List 3")'
+ '((exception-list.attributes.list_type: item AND exception-list.attributes.list_id: "list-1") AND exception-list.attributes.name: "Sample Endpoint Exception List 1") OR ((exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: "list-2") AND exception-list.attributes.name: "Sample Endpoint Exception List 2") OR ((exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.list_id: "list-3") AND exception-list.attributes.name: "Sample Endpoint Exception List 3")'
);
});
});
diff --git a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.ts b/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.ts
index cc84314eaa7a..155408dafc79 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/find_exception_list_items.ts
@@ -24,6 +24,7 @@ import {
SortFieldOrUndefined,
SortOrderOrUndefined,
} from '../../../common/schemas';
+import { escapeQuotes } from '../utils/escape_query';
import { getSavedObjectTypes, transformSavedObjectsToFoundExceptionListItem } from './utils';
import { getExceptionList } from './get_exception_list';
@@ -89,7 +90,8 @@ export const getExceptionListsItemFilter = ({
savedObjectType: SavedObjectType[];
}): string => {
return listId.reduce((accum, singleListId, index) => {
- const listItemAppend = `(${savedObjectType[index]}.attributes.list_type: item AND ${savedObjectType[index]}.attributes.list_id: ${singleListId})`;
+ const escapedListId = escapeQuotes(singleListId);
+ const listItemAppend = `(${savedObjectType[index]}.attributes.list_type: item AND ${savedObjectType[index]}.attributes.list_id: "${escapedListId}")`;
const listItemAppendWithFilter =
filter[index] != null ? `(${listItemAppend} AND ${filter[index]})` : listItemAppend;
if (accum === '') {
@@ -117,8 +119,9 @@ export const findValueListExceptionListItems = async ({
sortField,
sortOrder,
}: FindValueListExceptionListsItems): Promise => {
+ const escapedValueListId = escapeQuotes(valueListId);
const savedObjectsFindResponse = await savedObjectsClient.find({
- filter: `(exception-list.attributes.list_type: item AND exception-list.attributes.entries.list.id:${valueListId}) OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.entries.list.id:${valueListId}) `,
+ filter: `(exception-list.attributes.list_type: item AND exception-list.attributes.entries.list.id:"${escapedValueListId}") OR (exception-list-agnostic.attributes.list_type: item AND exception-list-agnostic.attributes.entries.list.id:"${escapedValueListId}") `,
page,
perPage,
sortField,
diff --git a/x-pack/plugins/lists/server/services/utils/escape_query.ts b/x-pack/plugins/lists/server/services/utils/escape_query.ts
new file mode 100644
index 000000000000..f654b8a2b9eb
--- /dev/null
+++ b/x-pack/plugins/lists/server/services/utils/escape_query.ts
@@ -0,0 +1,10 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export const escapeQuotes = (str: string): string => {
+ return str.replace(/[\\"]/g, '\\$&');
+};
diff --git a/x-pack/plugins/lists/server/services/utils/get_query_filter.test.ts b/x-pack/plugins/lists/server/services/utils/get_query_filter.test.ts
index d189012aec0e..0f6cc171bc04 100644
--- a/x-pack/plugins/lists/server/services/utils/get_query_filter.test.ts
+++ b/x-pack/plugins/lists/server/services/utils/get_query_filter.test.ts
@@ -46,7 +46,7 @@ describe('get_query_filter', () => {
minimum_should_match: 1,
should: [
{
- match: {
+ match_phrase: {
list_id: 'list-123',
},
},
@@ -74,7 +74,7 @@ describe('get_query_filter', () => {
minimum_should_match: 1,
should: [
{
- match: {
+ match_phrase: {
list_id: 'list-123',
},
},
diff --git a/x-pack/plugins/lists/server/services/utils/get_query_filter.ts b/x-pack/plugins/lists/server/services/utils/get_query_filter.ts
index 5cbad8c284a5..25c8f9880063 100644
--- a/x-pack/plugins/lists/server/services/utils/get_query_filter.ts
+++ b/x-pack/plugins/lists/server/services/utils/get_query_filter.ts
@@ -9,6 +9,8 @@ import { DslQuery, EsQueryConfig } from 'src/plugins/data/common';
import { Filter, Query, esQuery } from '../../../../../../src/plugins/data/server';
+import { escapeQuotes } from './escape_query';
+
export interface GetQueryFilterOptions {
filter: string;
}
@@ -41,7 +43,10 @@ export const getQueryFilterWithListId = ({
filter,
listId,
}: GetQueryFilterWithListIdOptions): GetQueryFilterReturn => {
+ const escapedListId = escapeQuotes(listId);
const filterWithListId =
- filter.trim() !== '' ? `list_id: ${listId} AND (${filter})` : `list_id: ${listId}`;
+ filter.trim() !== ''
+ ? `list_id: "${escapedListId}" AND (${filter})`
+ : `list_id: "${escapedListId}"`;
return getQueryFilter({ filter: filterWithListId });
};
diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/advanced_step_form.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/advanced_step_form.tsx
index 71770dcf952d..21243351dab7 100644
--- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/advanced_step_form.tsx
+++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/advanced_step_form.tsx
@@ -560,7 +560,7 @@ export const AdvancedStepForm: FC = ({
})}
helpText={i18n.translate('xpack.ml.dataframe.analytics.create.maxNumThreadsHelpText', {
defaultMessage:
- 'The maximum number of threads to be used by the analysis. The default value is 1',
+ 'The maximum number of threads to be used by the analysis. The default value is 1.',
})}
isInvalid={maxNumThreads === 0}
error={
diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/outlier_hyper_parameters.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/outlier_hyper_parameters.tsx
index d591c8c60275..d347a8147469 100644
--- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/outlier_hyper_parameters.tsx
+++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/advanced_step/outlier_hyper_parameters.tsx
@@ -30,7 +30,7 @@ export const OutlierHyperParameters: FC = ({ actions, state, advancedPara
})}
helpText={i18n.translate('xpack.ml.dataframe.analytics.create.methodHelpText', {
defaultMessage:
- 'Sets the method that outlier detection uses. If not set, uses an ensemble of different methods and normalises and combines their individual outlier scores to obtain the overall outlier score. We recommend to use the ensemble method',
+ 'Sets the method that outlier detection uses. If not set, uses an ensemble of different methods, normalizes and combines their individual outlier scores to obtain the overall outlier score. It is recommended to use the ensemble method.',
})}
isInvalid={advancedParamErrors[ANALYSIS_ADVANCED_FIELDS.METHOD] !== undefined}
error={advancedParamErrors[ANALYSIS_ADVANCED_FIELDS.METHOD]}
@@ -56,7 +56,7 @@ export const OutlierHyperParameters: FC = ({ actions, state, advancedPara
})}
helpText={i18n.translate('xpack.ml.dataframe.analytics.create.nNeighborsHelpText', {
defaultMessage:
- 'The value for how many nearest neighbors each method of outlier detection will use to calculate its outlier score. When not set, different values will be used for different ensemble members. Must be a positive integer',
+ 'The value for how many nearest neighbors each method of outlier detection uses to calculate its outlier score. When not set, different values are used for different ensemble members. Must be a positive integer.',
})}
isInvalid={advancedParamErrors[ANALYSIS_ADVANCED_FIELDS.N_NEIGHBORS] !== undefined}
error={advancedParamErrors[ANALYSIS_ADVANCED_FIELDS.N_NEIGHBORS]}
@@ -66,7 +66,7 @@ export const OutlierHyperParameters: FC = ({ actions, state, advancedPara
'xpack.ml.dataframe.analytics.create.nNeighborsInputAriaLabel',
{
defaultMessage:
- 'The value for how many nearest neighbors each method of outlier detection will use to calculate its outlier score.',
+ 'The value for how many nearest neighbors each method of outlier detection uses to calculate its outlier score.',
}
)}
data-test-subj="mlAnalyticsCreateJobWizardnNeighborsInput"
diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx
index aa008192bbce..206fb511a4d2 100644
--- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx
+++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx
@@ -539,7 +539,7 @@ export const ConfigurationStepForm: FC = ({
'xpack.ml.dataframe.analytics.create.scatterplotMatrixLabelHelpText',
{
defaultMessage:
- 'Visualizes the relationships between pairs of selected included fields',
+ 'Visualizes the relationships between pairs of selected included fields.',
}
)}
fullWidth
diff --git a/x-pack/plugins/security_solution/common/endpoint/models/event.ts b/x-pack/plugins/security_solution/common/endpoint/models/event.ts
index 692c1d3757b8..9c102e77b694 100644
--- a/x-pack/plugins/security_solution/common/endpoint/models/event.ts
+++ b/x-pack/plugins/security_solution/common/endpoint/models/event.ts
@@ -160,12 +160,12 @@ export function md5HashForProcess(event: SafeResolverEvent): string | undefined
/**
* First non-null value for the `event.process.args` field.
*/
-export function argsForProcess(event: SafeResolverEvent): string | undefined {
+export function argsForProcess(event: SafeResolverEvent): string[] | undefined {
if (isLegacyEventSafeVersion(event)) {
// There is not currently a key for this on Legacy event types
return undefined;
}
- return firstNonNullValue(event.process?.args);
+ return values(event.process?.args);
}
/**
diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/data_providers.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timelines/data_providers.spec.ts
index 3505a9b6a791..7d72747c8493 100644
--- a/x-pack/plugins/security_solution/cypress/integration/timelines/data_providers.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/timelines/data_providers.spec.ts
@@ -10,6 +10,7 @@ import {
TIMELINE_DATA_PROVIDERS_EMPTY,
TIMELINE_DROPPED_DATA_PROVIDERS,
TIMELINE_DATA_PROVIDERS_ACTION_MENU,
+ TIMELINE_FLYOUT_HEADER,
} from '../../screens/timeline';
import { HOSTS_NAMES_DRAGGABLE } from '../../screens/hosts/all_hosts';
@@ -60,8 +61,13 @@ describe('timeline data providers', () => {
openTimelineUsingToggle();
cy.get(TIMELINE_DATA_PROVIDERS_ACTION_MENU).should('not.exist');
- cy.get(TIMELINE_DROPPED_DATA_PROVIDERS).first().focus();
- cy.get(TIMELINE_DROPPED_DATA_PROVIDERS).first().parent().type('{enter}');
+ cy.get(`${TIMELINE_FLYOUT_HEADER} ${TIMELINE_DROPPED_DATA_PROVIDERS}`)
+ .pipe(($el) => $el.trigger('focus'))
+ .should('exist');
+ cy.get(`${TIMELINE_FLYOUT_HEADER} ${TIMELINE_DROPPED_DATA_PROVIDERS}`)
+ .first()
+ .parent()
+ .type('{enter}');
cy.get(TIMELINE_DATA_PROVIDERS_ACTION_MENU).should('exist');
});
diff --git a/x-pack/plugins/security_solution/public/common/components/ml_popover/ml_popover.tsx b/x-pack/plugins/security_solution/public/common/components/ml_popover/ml_popover.tsx
index 1f216bb8da1a..561805217e8a 100644
--- a/x-pack/plugins/security_solution/public/common/components/ml_popover/ml_popover.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/ml_popover/ml_popover.tsx
@@ -27,6 +27,10 @@ import { useSecurityJobs } from './hooks/use_security_jobs';
const PopoverContentsDiv = styled.div`
max-width: 684px;
+ max-height: 90vh;
+ overflow-y: auto;
+ overflow-x: hidden;
+ padding-bottom: 15px;
`;
PopoverContentsDiv.displayName = 'PopoverContentsDiv';
diff --git a/x-pack/plugins/security_solution/public/resolver/mocks/endpoint_event.ts b/x-pack/plugins/security_solution/public/resolver/mocks/endpoint_event.ts
index 04541189683a..59089af4a22f 100644
--- a/x-pack/plugins/security_solution/public/resolver/mocks/endpoint_event.ts
+++ b/x-pack/plugins/security_solution/public/resolver/mocks/endpoint_event.ts
@@ -51,7 +51,7 @@ export function mockEndpointEvent({
process: {
entity_id: entityID,
executable: 'executable',
- args: 'args',
+ args: ['args0', 'args1', 'args2'],
name: processName,
pid,
hash: {
diff --git a/x-pack/plugins/security_solution/public/resolver/view/panel.test.tsx b/x-pack/plugins/security_solution/public/resolver/view/panel.test.tsx
index eeb9d65cd6ac..332f806b59ec 100644
--- a/x-pack/plugins/security_solution/public/resolver/view/panel.test.tsx
+++ b/x-pack/plugins/security_solution/public/resolver/view/panel.test.tsx
@@ -34,7 +34,7 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and
/**
* These are the details we expect to see in the node detail view when the origin is selected.
*/
- const originEventDetailEntries: ReadonlyMap = new Map([
+ const originEventDetailEntries: Array<[string, string]> = [
['@timestamp', 'Sep 23, 2020 @ 08:25:32.316'],
['process.executable', 'executable'],
['process.pid', '0'],
@@ -42,8 +42,10 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and
['user.domain', 'user.domain'],
['process.parent.pid', '0'],
['process.hash.md5', 'hash.md5'],
- ['process.args', 'args'],
- ]);
+ ['process.args', 'args0'],
+ ['process.args', 'args1'],
+ ['process.args', 'args2'],
+ ];
beforeEach(() => {
// create a mock data access layer
@@ -129,11 +131,16 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and
describe.each([...originEventDetailEntries])(
'when the user hovers over the description for the field (%p) with their mouse',
(fieldTitleText, value) => {
+ // If there are multiple values for a field, i.e. an array, this is the index for the value we are testing.
+ const entryIndex = originEventDetailEntries
+ .filter(([fieldName]) => fieldName === fieldTitleText)
+ .findIndex(([_, fieldValue]) => fieldValue === value);
beforeEach(async () => {
const dt = await simulator().resolveWrapper(() => {
return simulator()
.testSubject('resolver:node-detail:entry-title')
- .filterWhere((title) => title.text() === fieldTitleText);
+ .filterWhere((title) => title.text() === fieldTitleText)
+ .at(entryIndex);
});
expect(dt).toHaveLength(1);
@@ -184,7 +191,9 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and
['user.domain', 'user.domain'],
['process.parent.pid', '0'],
['process.hash.md5', 'hash.md5'],
- ['process.args', 'args'],
+ ['process.args', 'args0'],
+ ['process.args', 'args1'],
+ ['process.args', 'args2'],
]);
});
});
diff --git a/x-pack/plugins/security_solution/public/resolver/view/panels/node_detail.tsx b/x-pack/plugins/security_solution/public/resolver/view/panels/node_detail.tsx
index da52994c4e71..ed3507d8f4bc 100644
--- a/x-pack/plugins/security_solution/public/resolver/view/panels/node_detail.tsx
+++ b/x-pack/plugins/security_solution/public/resolver/view/panels/node_detail.tsx
@@ -122,8 +122,12 @@ const NodeDetailView = memo(function ({
description: eventModel.argsForProcess(processEvent),
};
- // This is the data in {title, description} form for the EuiDescriptionList to display
- const processDescriptionListData = [
+ const flattenedEntries: Array<{
+ title: string;
+ description: string | string[] | number | undefined;
+ }> = [];
+
+ const flattenedDescriptionListData = [
createdEntry,
pathEntry,
pidEntry,
@@ -132,7 +136,21 @@ const NodeDetailView = memo(function ({
parentPidEntry,
md5Entry,
commandLineEntry,
- ]
+ ].reduce((flattenedList, entry) => {
+ if (Array.isArray(entry.description)) {
+ return [
+ ...flattenedList,
+ ...entry.description.map((value) => {
+ return { title: entry.title, description: value };
+ }),
+ ];
+ } else {
+ return [...flattenedList, entry];
+ }
+ }, flattenedEntries);
+
+ // This is the data in {title, description} form for the EuiDescriptionList to display
+ const processDescriptionListData = flattenedDescriptionListData
.filter((entry) => {
return entry.description !== undefined;
})
diff --git a/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts b/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts
index f452514cb517..a48811ad7024 100644
--- a/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts
+++ b/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts
@@ -6,6 +6,7 @@
*/
import querystring from 'querystring';
+import url from 'url';
import expect from '@kbn/expect';
import { isEmpty, uniq } from 'lodash';
import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata';
@@ -131,110 +132,127 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext)
expect(environments.has(ENVIRONMENT_NOT_DEFINED)).to.eql(true);
expectSnapshot(body).toMatch();
});
- });
-
- describe('/api/apm/service-map with ML data', () => {
- describe('with the default apm user', () => {
- let response: PromiseReturnType;
- before(async () => {
- response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`);
- });
+ describe('with ML data', () => {
+ describe('with the default apm user', () => {
+ before(async () => {
+ response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`);
+ });
- it('returns service map elements with anomaly stats', () => {
- expect(response.status).to.be(200);
- const dataWithAnomalies = response.body.elements.filter(
- (el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
- );
+ it('returns service map elements with anomaly stats', () => {
+ expect(response.status).to.be(200);
+ const dataWithAnomalies = response.body.elements.filter(
+ (el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
+ );
- expect(dataWithAnomalies).to.not.empty();
+ expect(dataWithAnomalies).to.not.empty();
- dataWithAnomalies.forEach(({ data }: any) => {
- expect(
- Object.values(data.serviceAnomalyStats).filter((value) => isEmpty(value))
- ).to.not.empty();
+ dataWithAnomalies.forEach(({ data }: any) => {
+ expect(
+ Object.values(data.serviceAnomalyStats).filter((value) => isEmpty(value))
+ ).to.not.empty();
+ });
});
- });
- it('returns the correct anomaly stats', () => {
- const dataWithAnomalies = response.body.elements.filter(
- (el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
- );
-
- expectSnapshot(dataWithAnomalies.length).toMatchInline(`8`);
- expectSnapshot(dataWithAnomalies.slice(0, 3)).toMatchInline(`
- Array [
- Object {
- "data": Object {
- "agent.name": "python",
- "id": "opbeans-python",
- "service.name": "opbeans-python",
- "serviceAnomalyStats": Object {
- "actualValue": 24282.2352941176,
- "anomalyScore": 0,
- "healthStatus": "healthy",
- "jobId": "apm-environment_not_defined-5626-high_mean_transaction_duration",
- "serviceName": "opbeans-python",
- "transactionType": "request",
+ it('returns the correct anomaly stats', () => {
+ const dataWithAnomalies = response.body.elements.filter(
+ (el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
+ );
+
+ expectSnapshot(dataWithAnomalies.length).toMatchInline(`8`);
+ expectSnapshot(dataWithAnomalies.slice(0, 3)).toMatchInline(`
+ Array [
+ Object {
+ "data": Object {
+ "agent.name": "python",
+ "id": "opbeans-python",
+ "service.name": "opbeans-python",
+ "serviceAnomalyStats": Object {
+ "actualValue": 24282.2352941176,
+ "anomalyScore": 0,
+ "healthStatus": "healthy",
+ "jobId": "apm-environment_not_defined-5626-high_mean_transaction_duration",
+ "serviceName": "opbeans-python",
+ "transactionType": "request",
+ },
},
},
- },
- Object {
- "data": Object {
- "agent.name": "nodejs",
- "id": "opbeans-node",
- "service.environment": "testing",
- "service.name": "opbeans-node",
- "serviceAnomalyStats": Object {
- "actualValue": 29300.5555555556,
- "anomalyScore": 0,
- "healthStatus": "healthy",
- "jobId": "apm-testing-384f-high_mean_transaction_duration",
- "serviceName": "opbeans-node",
- "transactionType": "request",
+ Object {
+ "data": Object {
+ "agent.name": "nodejs",
+ "id": "opbeans-node",
+ "service.environment": "testing",
+ "service.name": "opbeans-node",
+ "serviceAnomalyStats": Object {
+ "actualValue": 29300.5555555556,
+ "anomalyScore": 0,
+ "healthStatus": "healthy",
+ "jobId": "apm-testing-384f-high_mean_transaction_duration",
+ "serviceName": "opbeans-node",
+ "transactionType": "request",
+ },
},
},
- },
- Object {
- "data": Object {
- "agent.name": "rum-js",
- "id": "opbeans-rum",
- "service.environment": "testing",
- "service.name": "opbeans-rum",
- "serviceAnomalyStats": Object {
- "actualValue": 2386500,
- "anomalyScore": 0,
- "healthStatus": "healthy",
- "jobId": "apm-testing-384f-high_mean_transaction_duration",
- "serviceName": "opbeans-rum",
- "transactionType": "page-load",
+ Object {
+ "data": Object {
+ "agent.name": "rum-js",
+ "id": "opbeans-rum",
+ "service.environment": "testing",
+ "service.name": "opbeans-rum",
+ "serviceAnomalyStats": Object {
+ "actualValue": 2386500,
+ "anomalyScore": 0,
+ "healthStatus": "healthy",
+ "jobId": "apm-testing-384f-high_mean_transaction_duration",
+ "serviceName": "opbeans-rum",
+ "transactionType": "page-load",
+ },
},
},
- },
- ]
- `);
+ ]
+ `);
- expectSnapshot(response.body).toMatch();
+ expectSnapshot(response.body).toMatch();
+ });
});
- });
- describe('with a user that does not have access to ML', () => {
- let response: PromiseReturnType;
+ describe('with a user that does not have access to ML', () => {
+ before(async () => {
+ response = await supertestAsApmReadUserWithoutMlAccess.get(
+ `/api/apm/service-map?start=${start}&end=${end}`
+ );
+ });
- before(async () => {
- response = await supertestAsApmReadUserWithoutMlAccess.get(
- `/api/apm/service-map?start=${start}&end=${end}`
- );
- });
+ it('returns service map elements without anomaly stats', () => {
+ expect(response.status).to.be(200);
- it('returns service map elements without anomaly stats', () => {
- expect(response.status).to.be(200);
+ const dataWithAnomalies = response.body.elements.filter(
+ (el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
+ );
- const dataWithAnomalies = response.body.elements.filter(
- (el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
- );
+ expect(dataWithAnomalies).to.be.empty();
+ });
+ });
+ });
+
+ describe('with a single service', () => {
+ describe('when ENVIRONMENT_ALL is selected', () => {
+ it('returns service map elements', async () => {
+ response = await supertest.get(
+ url.format({
+ pathname: '/api/apm/service-map',
+ query: {
+ environment: 'ENVIRONMENT_ALL',
+ start: metadata.start,
+ end: metadata.end,
+ serviceName: 'opbeans-java',
+ },
+ })
+ );
- expect(dataWithAnomalies).to.be.empty();
+ expect(response.status).to.be(200);
+ expect(response.body.elements.length).to.be.greaterThan(1);
+ });
});
});
});
diff --git a/x-pack/test/lists_api_integration/security_and_spaces/tests/delete_lists.ts b/x-pack/test/lists_api_integration/security_and_spaces/tests/delete_lists.ts
index adba0a2f626e..4ce3c7f0e566 100644
--- a/x-pack/test/lists_api_integration/security_and_spaces/tests/delete_lists.ts
+++ b/x-pack/test/lists_api_integration/security_and_spaces/tests/delete_lists.ts
@@ -63,6 +63,28 @@ export default ({ getService }: FtrProviderContext) => {
expect(bodyToCompare).to.eql(getListResponseMockWithoutAutoGeneratedValues());
});
+ it('should delete a single list with a list id containing non-alphanumeric characters', async () => {
+ // create a list
+ const id = `some""-list-id"(1)`;
+ await supertest
+ .post(LIST_URL)
+ .set('kbn-xsrf', 'true')
+ .send({
+ ...getCreateMinimalListSchemaMock(),
+ id,
+ })
+ .expect(200);
+
+ // delete the list by its list id
+ const { body } = await supertest
+ .delete(`${LIST_URL}?id=${id}`)
+ .set('kbn-xsrf', 'true')
+ .expect(200);
+
+ const bodyToCompare = removeListServerGeneratedProperties(body);
+ expect(bodyToCompare).to.eql(getListResponseMockWithoutAutoGeneratedValues());
+ });
+
it('should delete a single list using an auto generated id', async () => {
// add a list
const { body: bodyWithCreatedList } = await supertest
diff --git a/yarn.lock b/yarn.lock
index bcf5c37f6f91..efe77edbaed8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8443,10 +8443,10 @@ bmp-js@^0.1.0:
resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.1.0.tgz#e05a63f796a6c1ff25f4771ec7adadc148c07233"
integrity sha1-4Fpj95amwf8l9Hcex62twUjAcjM=
-bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
- version "4.11.8"
- resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
- integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
+bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9:
+ version "4.11.9"
+ resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828"
+ integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==
body-parser@1.19.0, body-parser@^1.18.1, body-parser@^1.18.3:
version "1.19.0"
@@ -8586,7 +8586,7 @@ broadcast-channel@^3.0.3:
rimraf "3.0.0"
unload "2.2.0"
-brorand@^1.0.1:
+brorand@^1.0.1, brorand@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
@@ -12353,17 +12353,17 @@ element-resize-detector@^1.1.15:
batch-processor "^1.0.0"
elliptic@^6.0.0:
- version "6.5.3"
- resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6"
- integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==
+ version "6.5.4"
+ resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
+ integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
dependencies:
- bn.js "^4.4.0"
- brorand "^1.0.1"
+ bn.js "^4.11.9"
+ brorand "^1.1.0"
hash.js "^1.0.0"
- hmac-drbg "^1.0.0"
- inherits "^2.0.1"
- minimalistic-assert "^1.0.0"
- minimalistic-crypto-utils "^1.0.0"
+ hmac-drbg "^1.0.1"
+ inherits "^2.0.4"
+ minimalistic-assert "^1.0.1"
+ minimalistic-crypto-utils "^1.0.1"
emittery@^0.7.1:
version "0.7.1"
@@ -15796,7 +15796,7 @@ hjson@3.2.1:
resolved "https://registry.yarnpkg.com/hjson/-/hjson-3.2.1.tgz#20de41dc87fc9a10d1557d0230b0e02afb1b09ac"
integrity sha512-OhhrFMeC7dVuA1xvxuXGTv/yTdhTvbe8hz+3LgVNsfi9+vgz0sF/RrkuX8eegpKaMc9cwYwydImBH6iePoJtdQ==
-hmac-drbg@^1.0.0:
+hmac-drbg@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
@@ -20018,12 +20018,12 @@ mini-css-extract-plugin@0.8.0:
schema-utils "^1.0.0"
webpack-sources "^1.1.0"
-minimalistic-assert@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"
- integrity sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=
+minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
+ integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
-minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
+minimalistic-crypto-utils@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
@@ -20811,9 +20811,9 @@ node-modules-regexp@^1.0.0:
integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
node-notifier@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.0.tgz#a7eee2d51da6d0f7ff5094bc7108c911240c1620"
- integrity sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.1.tgz#f86e89bbc925f2b068784b31f382afdc6ca56be1"
+ integrity sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA==
dependencies:
growly "^1.3.0"
is-wsl "^2.2.0"
@@ -22627,10 +22627,10 @@ printj@~1.1.0:
resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==
-prismjs@1.22.0, prismjs@^1.22.0, prismjs@~1.22.0:
- version "1.22.0"
- resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.22.0.tgz#73c3400afc58a823dd7eed023f8e1ce9fd8977fa"
- integrity sha512-lLJ/Wt9yy0AiSYBf212kK3mM5L8ycwlyTlSxHBAneXLR0nzFMlZ5y7riFPF3E33zXOF2IH95xdY5jIyZbM9z/w==
+prismjs@1.23.0, prismjs@^1.22.0, prismjs@~1.22.0:
+ version "1.23.0"
+ resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.23.0.tgz#d3b3967f7d72440690497652a9d40ff046067f33"
+ integrity sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==
optionalDependencies:
clipboard "^2.0.0"
@@ -27907,9 +27907,9 @@ typescript@4.1.3, typescript@^3.2.2, typescript@^3.3.3333, typescript@^3.5.3, ty
integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
ua-parser-js@^0.7.18:
- version "0.7.23"
- resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.23.tgz#704d67f951e13195fbcd3d78818577f5bc1d547b"
- integrity sha512-m4hvMLxgGHXG3O3fQVAyyAQpZzDOvwnhOTjYz5Xmr7r/+LpkNy3vJXdVRWgd1TkAb7NGROZuSy96CrlNVjA7KA==
+ version "0.7.24"
+ resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.24.tgz#8d3ecea46ed4f1f1d63ec25f17d8568105dc027c"
+ integrity sha512-yo+miGzQx5gakzVK3QFfN0/L9uVhosXBBO7qmnk7c2iw1IhL212wfA3zbnI54B0obGwC/5NWub/iT9sReMx+Fw==
uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.5"
@@ -28492,9 +28492,9 @@ url-parse-lax@^3.0.0:
prepend-http "^2.0.0"
url-parse@^1.4.3, url-parse@^1.4.7:
- version "1.4.7"
- resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
- integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.1.tgz#d5fa9890af8a5e1f274a2c98376510f6425f6e3b"
+ integrity sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==
dependencies:
querystringify "^2.1.1"
requires-port "^1.0.0"