diff --git a/.ci/Dockerfile b/.ci/Dockerfile index fb292e09c3ccb..3165805fe68c1 100644 --- a/.ci/Dockerfile +++ b/.ci/Dockerfile @@ -1,7 +1,7 @@ # NOTE: This Dockerfile is ONLY used to run certain tasks in CI. It is not used to run Kibana or as a distributable. # If you're looking for the Kibana Docker image distributable, please see: src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts -ARG NODE_VERSION=16.20.1 +ARG NODE_VERSION=18.17.0 FROM node:${NODE_VERSION} AS base diff --git a/.node-version b/.node-version index 47979412e93f2..603606bc91118 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -16.20.1 +18.17.0 diff --git a/.nvmrc b/.nvmrc index 47979412e93f2..603606bc91118 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -16.20.1 +18.17.0 diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index f277a78500947..0b5c0d0bc3634 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -22,13 +22,13 @@ load("@build_bazel_rules_nodejs//:index.bzl", "node_repositories", "yarn_install # Setup the Node.js toolchain for the architectures we want to support node_repositories( node_repositories = { - "16.20.1-darwin_amd64": ("node-v16.20.1-darwin-x64.tar.gz", "node-v16.20.1-darwin-x64", "d1f9c2a7c3a0fe09860f701af5fb8ff9ac72d72faa7ebabfeb5794503e79f955"), - "16.20.1-darwin_arm64": ("node-v16.20.1-darwin-arm64.tar.gz", "node-v16.20.1-darwin-arm64", "5f6b31c5a75567d382ba67220f3d7a2d9bb0c03d8af9307cd35a9cb32a6fde9d"), - "16.20.1-linux_arm64": ("node-v16.20.1-linux-arm64.tar.xz", "node-v16.20.1-linux-arm64", "7fce19f3d1c2952599a0b47f9f5d8f497265ad577f37f256a8c6a03be6353234"), - "16.20.1-linux_amd64": ("node-v16.20.1-linux-x64.tar.xz", "node-v16.20.1-linux-x64", "b6c60e1e106ad7d8881e83945a5208c1b1d1b63e6901c04b9dafa607aff3a154"), - "16.20.1-windows_amd64": ("node-v16.20.1-win-x64.zip", "node-v16.20.1-win-x64", "2a7fde996c57a969f0498742f99385a520eb14aac864e0eff9c32e3f3633ff0a"), + "18.17.0-darwin_amd64": ("node-v18.17.0-darwin-x64.tar.gz", "node-v18.17.0-darwin-x64", "2f381442381f7fbde2ca644c3275bec9c9c2a8d361f467b40e39428acdd6ccff"), + "18.17.0-darwin_arm64": ("node-v18.17.0-darwin-arm64.tar.gz", "node-v18.17.0-darwin-arm64", "19731ef427e77ad9c5f476eb62bfb02a7f179d3012feed0bbded62e45f23e679"), + "18.17.0-linux_arm64": ("node-v18.17.0-linux-arm64.tar.xz", "node-v18.17.0-linux-arm64", "fbd2904178ee47da6e0386bc9704a12b1f613da6ad194878a517d4a69ba56544"), + "18.17.0-linux_amd64": ("node-v18.17.0-linux-x64.tar.xz", "node-v18.17.0-linux-x64", "f36facda28c4d5ce76b3a1b4344e688d29d9254943a47f2f1909b1a10acb1959"), + "18.17.0-windows_amd64": ("node-v18.17.0-win-x64.zip", "node-v18.17.0-win-x64", "06e30b4e70b18d794651ef132c39080e5eaaa1187f938721d57edae2824f4e96"), }, - node_version = "16.20.1", + node_version = "18.17.0", node_urls = [ "https://nodejs.org/dist/v{version}/{filename}", ], diff --git a/docs/developer/advanced/upgrading-nodejs.asciidoc b/docs/developer/advanced/upgrading-nodejs.asciidoc index 86eaf039e9938..c2c559c9c380e 100644 --- a/docs/developer/advanced/upgrading-nodejs.asciidoc +++ b/docs/developer/advanced/upgrading-nodejs.asciidoc @@ -17,7 +17,7 @@ These files must be updated when upgrading Node.js: - {kib-repo}blob/{branch}/WORKSPACE.bazel[`WORKSPACE.bazel`] - The version is specified in the `node_version` property. Besides this property, the list of files under `node_repositories` must be updated along with their respective SHA256 hashes. These can be found on the https://nodejs.org[nodejs.org] website. - Example for Node.js v16.20.1: https://nodejs.org/dist/v16.20.1/SHASUMS256.txt.asc + Example for Node.js v18.17.0: https://nodejs.org/dist/v18.17.0/SHASUMS256.txt.asc See PR {kib-repo}pull/128123[#128123] for an example of how the Node.js version has been upgraded previously. @@ -30,6 +30,13 @@ When upgrading to a new major version of Node.js, the following extra steps must You can change which Node.js major version to view, by changing the selected branch. If Node.js has dropped support for platform still supported by Kibana, appropriate steps must be taken as soon as possible to deprecate support for this platform. This way support for it can be dropped before the currently used major version of Node.js https://github.com/nodejs/release#release-schedule[reaches End-of-Life]. +[[custom-nodejs-builds]] +=== Custom builds of Node.js + +Due to Node.js 16 coming to an https://nodejs.org/en/blog/announcements/nodejs16-eol[early End-of-Life] and Node.js 18 no longer supporting the same platforms that {kib} supports (most notably CentOS7/RHEL7), we cannot bundle the official Node.js binaries with the Linux distributable of {kib}. +To keep support for these older platforms, we're bundling the Linux distributable of {kib} with a https://github.com/elastic/kibana-custom-nodejs-builds[custom build of Node.js] with extended backwards compatibility. +The only difference between the offical Node.js build and our custom build, is the version of `glibc` that it's compiled against. + === Backporting The following rules are not set in stone. diff --git a/docs/user/setup.asciidoc b/docs/user/setup.asciidoc index 87c398f1d44e0..981e8651c7f13 100644 --- a/docs/user/setup.asciidoc +++ b/docs/user/setup.asciidoc @@ -21,6 +21,10 @@ Windows. Since Kibana runs on Node.js, we include the necessary Node.js binaries for these platforms. Running Kibana against a separately maintained version of Node.js is not supported. +To support certain older Linux platforms (most notably CentOS7/RHEL7), {kib} +for Linux ships with a custom build of Node.js with glibc 2.17 support. For +details, see <>. + [float] [[elasticsearch-version]] == Elasticsearch version diff --git a/fleet_packages.json b/fleet_packages.json index 65f6969fc2034..c94a6aecf1b41 100644 --- a/fleet_packages.json +++ b/fleet_packages.json @@ -54,7 +54,7 @@ }, { "name": "synthetics", - "version": "1.0.2" + "version": "1.0.3" }, { "name": "security_detection_engine", diff --git a/package.json b/package.json index 47e82a89d274f..3b1ee85678c9e 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "serverless-security": "node scripts/kibana --dev --serverless=security", "spec_to_console": "node scripts/spec_to_console", "start": "node scripts/kibana --dev", - "storybook": "node scripts/storybook", + "storybook": "node --openssl-legacy-provider scripts/storybook", "test:ftr": "node scripts/functional_tests", "test:ftr:runner": "node scripts/functional_test_runner", "test:ftr:server": "node scripts/functional_tests_server", @@ -73,11 +73,11 @@ "url": "https://github.com/elastic/kibana.git" }, "engines": { - "node": "16.20.1", + "node": "18.17.0", "yarn": "^1.22.19" }, "resolutions": { - "**/@types/node": "16.11.68", + "**/@types/node": "18.17.1", "**/chokidar": "^3.5.3", "**/globule/minimatch": "^3.1.2", "**/hoist-non-react-statics": "^3.3.2", @@ -788,7 +788,6 @@ "@turf/length": "^6.0.2", "@xstate/react": "^3.2.2", "JSONStream": "1.3.5", - "abort-controller": "^3.0.0", "adm-zip": "^0.5.9", "ajv": "^8.12.0", "antlr4ts": "^0.5.0-alpha.3", @@ -929,7 +928,7 @@ "query-string": "^6.13.2", "rbush": "^3.0.1", "re-resizable": "^6.9.9", - "re2": "1.17.4", + "re2": "1.17.7", "react": "^17.0.2", "react-ace": "^7.0.5", "react-beautiful-dnd": "^13.1.0", @@ -1298,8 +1297,8 @@ "@types/multistream": "^4.1.0", "@types/mustache": "^0.8.31", "@types/nock": "^10.0.3", - "@types/node": "16.11.68", - "@types/node-fetch": "^2.6.0", + "@types/node": "18.17.1", + "@types/node-fetch": "2.6.4", "@types/node-forge": "^1.3.1", "@types/nodemailer": "^6.4.0", "@types/normalize-path": "^3.0.0", diff --git a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.test.tsx b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.test.tsx index f680a1b5d6ba9..ad9d292144317 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.test.tsx +++ b/packages/core/chrome/core-chrome-browser-internal/src/chrome_service.test.tsx @@ -36,11 +36,14 @@ class FakeApp implements App { const store = new Map(); const originalLocalStorage = window.localStorage; -(window as any).localStorage = { - setItem: (key: string, value: string) => store.set(String(key), String(value)), - getItem: (key: string) => store.get(String(key)), - removeItem: (key: string) => store.delete(String(key)), -}; +Object.defineProperty(window, 'localStorage', { + value: { + setItem: (key: string, value: string) => store.set(String(key), String(value)), + getItem: (key: string) => store.get(String(key)), + removeItem: (key: string) => store.delete(String(key)), + }, + writable: true, +}); function defaultStartDeps(availableApps?: App[]) { const deps = { diff --git a/packages/core/chrome/core-chrome-browser-internal/src/recently_accessed/recently_accessed_service.test.ts b/packages/core/chrome/core-chrome-browser-internal/src/recently_accessed/recently_accessed_service.test.ts index 9bafbe09918eb..20784f0f2ea11 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/recently_accessed/recently_accessed_service.test.ts +++ b/packages/core/chrome/core-chrome-browser-internal/src/recently_accessed/recently_accessed_service.test.ts @@ -44,7 +44,10 @@ describe('RecentlyAccessed#start()', () => { let originalLocalStorage: Storage; beforeAll(() => { originalLocalStorage = window.localStorage; - window.localStorage = new LocalStorageMock(); + Object.defineProperty(window, 'localStorage', { + value: new LocalStorageMock(), + writable: true, + }); }); beforeEach(() => localStorage.clear()); afterAll(() => (window.localStorage = originalLocalStorage)); diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/agent_manager.test.ts b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/agent_manager.test.ts index 448bfe2674e8f..de5c960be35bf 100644 --- a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/agent_manager.test.ts +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/agent_manager.test.ts @@ -16,8 +16,8 @@ import { AgentManager } from './agent_manager'; jest.mock('http'); jest.mock('https'); -const HttpAgentMock = HttpAgent as jest.Mock; -const HttpsAgentMock = HttpsAgent as jest.Mock; +const HttpAgentMock = HttpAgent as unknown as jest.Mock; +const HttpsAgentMock = HttpsAgent as unknown as jest.Mock; describe('AgentManager', () => { let logger: MockedLogger; diff --git a/packages/core/notifications/core-notifications-browser-internal/src/toasts/__snapshots__/deduplicate_toasts.test.tsx.snap b/packages/core/notifications/core-notifications-browser-internal/src/toasts/__snapshots__/deduplicate_toasts.test.tsx.snap new file mode 100644 index 0000000000000..b940ae7a6a178 --- /dev/null +++ b/packages/core/notifications/core-notifications-browser-internal/src/toasts/__snapshots__/deduplicate_toasts.test.tsx.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TitleWithBadge component renders with string titles 1`] = ` + + Welcome! + + + 5 + + +`; diff --git a/packages/core/notifications/core-notifications-browser-internal/src/toasts/__snapshots__/global_toast_list.test.tsx.snap b/packages/core/notifications/core-notifications-browser-internal/src/toasts/__snapshots__/global_toast_list.test.tsx.snap index 558f0f19080e6..d9dc9f6c7b13d 100644 --- a/packages/core/notifications/core-notifications-browser-internal/src/toasts/__snapshots__/global_toast_list.test.tsx.snap +++ b/packages/core/notifications/core-notifications-browser-internal/src/toasts/__snapshots__/global_toast_list.test.tsx.snap @@ -1,5 +1,117 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`global_toast_list with duplicate elements renders the list with a single element 1`] = ` +, + "toastLifeTimeMs": 5000, + }, + ] + } +/> +`; + +exports[`global_toast_list with duplicate elements, using MountPoints renders the all separate elements element: euiToastList 1`] = ` +, + "toastLifeTimeMs": 5000, + }, + Object { + "id": "1", + "text": "You've got mail!", + "title": , + "toastLifeTimeMs": 5000, + }, + Object { + "id": "2", + "text": "You've got mail!", + "title": , + "toastLifeTimeMs": 5000, + }, + Object { + "id": "3", + "text": "You've got mail!", + "title": , + "toastLifeTimeMs": 5000, + }, + ] + } +/> +`; + +exports[`global_toast_list with duplicate elements, using MountPoints renders the all separate elements element: globalToastList 1`] = ` +, + "toastLifeTimeMs": 5000, + }, + Object { + "id": "1", + "text": "You've got mail!", + "title": , + "toastLifeTimeMs": 5000, + }, + Object { + "id": "2", + "text": "You've got mail!", + "title": , + "toastLifeTimeMs": 5000, + }, + Object { + "id": "3", + "text": "You've got mail!", + "title": , + "toastLifeTimeMs": 5000, + }, + ] + } +/> +`; + exports[`renders matching snapshot 1`] = ` () => {}; + +describe('deduplicate toasts', () => { + it('returns an empty list for an empty input', () => { + const toasts: Toast[] = []; + + const { toasts: deduplicatedToastList } = deduplicateToasts(toasts); + + expect(deduplicatedToastList).toHaveLength(0); + }); + + it(`doesn't affect singular notifications`, () => { + const toasts: Toast[] = [ + toast('A', 'B'), // single toast + toast('X', 'Y'), // single toast + ]; + + const { toasts: deduplicatedToastList } = deduplicateToasts(toasts); + + expect(deduplicatedToastList).toHaveLength(toasts.length); + verifyTextAndTitle(deduplicatedToastList[0], 'A', 'B'); + verifyTextAndTitle(deduplicatedToastList[1], 'X', 'Y'); + }); + + it(`doesn't group notifications with MountPoints for title`, () => { + const toasts: Toast[] = [ + toast('A', 'B'), + toast(fakeMountPoint, 'B'), + toast(fakeMountPoint, 'B'), + toast(fakeMountPoint, fakeMountPoint), + toast(fakeMountPoint, fakeMountPoint), + ]; + + const { toasts: deduplicatedToastList } = deduplicateToasts(toasts); + + expect(deduplicatedToastList).toHaveLength(toasts.length); + }); + + it('groups toasts based on title + text', () => { + const toasts: Toast[] = [ + toast('A', 'B'), // 2 of these + toast('X', 'Y'), // 3 of these + toast('A', 'B'), + toast('X', 'Y'), + toast('A', 'C'), // 1 of these + toast('X', 'Y'), + ]; + + const { toasts: deduplicatedToastList } = deduplicateToasts(toasts); + + expect(deduplicatedToastList).toHaveLength(3); + verifyTextAndTitle(deduplicatedToastList[0], 'A 2', 'B'); + verifyTextAndTitle(deduplicatedToastList[1], 'X 3', 'Y'); + verifyTextAndTitle(deduplicatedToastList[2], 'A', 'C'); + }); + + it('groups toasts based on title, when text is not available', () => { + const toasts: Toast[] = [ + toast('A', 'B'), // 2 of these + toast('A', fakeMountPoint), // 2 of these + toast('A', 'C'), // 1 of this + toast('A', 'B'), + toast('A', fakeMountPoint), + toast('A'), // but it doesn't group functions with missing texts + ]; + + const { toasts: deduplicatedToastList } = deduplicateToasts(toasts); + + expect(deduplicatedToastList).toHaveLength(4); + verifyTextAndTitle(deduplicatedToastList[0], 'A 2', 'B'); + verifyTextAndTitle(deduplicatedToastList[1], 'A 2', expect.any(Function)); + verifyTextAndTitle(deduplicatedToastList[2], 'A', 'C'); + verifyTextAndTitle(deduplicatedToastList[3], 'A', undefined); + }); +}); + +describe('TitleWithBadge component', () => { + it('renders with string titles', () => { + const title = 'Welcome!'; + + const titleComponent = ; + const shallowRender = shallow(titleComponent); + const fullRender = mount(titleComponent); + + expect(fullRender.text()).toBe('Welcome! 5'); + expect(shallowRender).toMatchSnapshot(); + }); +}); + +function verifyTextAndTitle( + { text, title }: ToastWithRichTitle, + expectedTitle?: string, + expectedText?: string +) { + expect(getNodeText(title)).toEqual(expectedTitle); + expect(text).toEqual(expectedText); +} + +function getNodeText(node: ReactNode) { + const rendered = render(node as ReactElement); + return rendered.text(); +} diff --git a/packages/core/notifications/core-notifications-browser-internal/src/toasts/deduplicate_toasts.tsx b/packages/core/notifications/core-notifications-browser-internal/src/toasts/deduplicate_toasts.tsx new file mode 100644 index 0000000000000..51a3a8989b7b8 --- /dev/null +++ b/packages/core/notifications/core-notifications-browser-internal/src/toasts/deduplicate_toasts.tsx @@ -0,0 +1,138 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { ReactNode } from 'react'; +import { css } from '@emotion/css'; + +import { EuiNotificationBadge } from '@elastic/eui'; +import { Toast } from '@kbn/core-notifications-browser'; +import { MountPoint } from '@kbn/core-mount-utils-browser'; + +/** + * We can introduce this type within this domain, to allow for react-managed titles + */ +export type ToastWithRichTitle = Omit & { + title?: MountPoint | ReactNode; +}; + +export interface DeduplicateResult { + toasts: ToastWithRichTitle[]; + idToToasts: Record; +} + +interface TitleWithBadgeProps { + title: string | undefined; + counter: number; +} + +/** + * Collects toast messages to groups based on the `getKeyOf` function, + * then represents every group of message with a single toast + * @param allToasts + * @return the deduplicated list of toasts, and a lookup to find toasts represented by their first toast's ID + */ +export function deduplicateToasts(allToasts: Toast[]): DeduplicateResult { + const toastGroups = groupByKey(allToasts); + + const distinctToasts: ToastWithRichTitle[] = []; + const idToToasts: Record = {}; + for (const toastGroup of Object.values(toastGroups)) { + const firstElement = toastGroup[0]; + idToToasts[firstElement.id] = toastGroup; + if (toastGroup.length === 1) { + distinctToasts.push(firstElement); + } else { + // Grouping will only happen for toasts whose titles are strings (or missing) + const title = firstElement.title as string | undefined; + distinctToasts.push({ + ...firstElement, + title: , + }); + } + } + + return { toasts: distinctToasts, idToToasts }; +} + +/** + * Derives a key from a toast object + * these keys decide what makes between different toasts, and which ones should be merged + * These toasts will be merged: + * - where title and text are strings, and the same + * - where titles are the same, and texts are missing + * - where titles are the same, and the text's mount function is the same string + * - where titles are missing, but the texts are the same string + * @param toast The toast whose key we're deriving + */ +function getKeyOf(toast: Toast): string { + if (isString(toast.title) && isString(toast.text)) { + return toast.title + ' ' + toast.text; + } else if (isString(toast.title) && !toast.text) { + return toast.title; + } else if (isString(toast.title) && typeof toast.text === 'function') { + return toast.title + ' ' + djb2Hash(toast.text.toString()); + } else if (isString(toast.text) && !toast.title) { + return toast.text; + } else { + // Either toast or text is a mount function, or both missing + return 'KEY_' + toast.id.toString(); + } +} + +function isString(a: string | any): a is string { + return typeof a === 'string'; +} + +// Based on: https://gist.github.com/eplawless/52813b1d8ad9af510d85 +function djb2Hash(str: string): number { + const len = str.length; + let hash = 5381; + + for (let i = 0; i < len; i++) { + // eslint-disable-next-line no-bitwise + hash = (hash * 33) ^ str.charCodeAt(i); + } + // eslint-disable-next-line no-bitwise + return hash >>> 0; +} + +function groupByKey(allToasts: Toast[]) { + const toastGroups: Record = {}; + for (const toast of allToasts) { + const key = getKeyOf(toast); + + if (!toastGroups[key]) { + toastGroups[key] = [toast]; + } else { + toastGroups[key].push(toast); + } + } + return toastGroups; +} + +const floatTopRight = css` + position: absolute; + top: -8px; + right: -8px; +`; + +/** + * A component that renders a title with a floating counter + * @param title {string} The title string + * @param counter {number} The count of notifications represented + */ +export function TitleWithBadge({ title, counter }: TitleWithBadgeProps) { + return ( + + {title}{' '} + + {counter} + + + ); +} diff --git a/packages/core/notifications/core-notifications-browser-internal/src/toasts/global_toast_list.test.tsx b/packages/core/notifications/core-notifications-browser-internal/src/toasts/global_toast_list.test.tsx index 77430aa951b11..3835dfd24e899 100644 --- a/packages/core/notifications/core-notifications-browser-internal/src/toasts/global_toast_list.test.tsx +++ b/packages/core/notifications/core-notifications-browser-internal/src/toasts/global_toast_list.test.tsx @@ -7,14 +7,17 @@ */ import { EuiGlobalToastList } from '@elastic/eui'; +import { Toast } from '@kbn/core-notifications-browser/src/types'; import { shallow } from 'enzyme'; import React from 'react'; import { Observable, from, EMPTY } from 'rxjs'; import { GlobalToastList } from './global_toast_list'; +const mockDismissToast = jest.fn(); + function render(props: Partial = {}) { - return ; + return ; } it('renders matching snapshot', () => { @@ -52,3 +55,78 @@ it('passes latest value from toasts$ to ', () => { expect(el.find(EuiGlobalToastList).prop('toasts')).toEqual([{ id: '1' }, { id: '2' }]); }); + +describe('global_toast_list with duplicate elements', () => { + const dummyText = `You've got mail!`; + const dummyTitle = `AOL Notifications`; + const toast = (id: any): Toast => ({ + id: id.toString(), + text: dummyText, + title: dummyTitle, + toastLifeTimeMs: 5000, + }); + + const globalToastList = shallow( + render({ + toasts$: from([[toast(0), toast(1), toast(2), toast(3)]]) as any, + }) + ); + + const euiToastList = globalToastList.find(EuiGlobalToastList); + const toastsProp = euiToastList.prop('toasts'); + + it('renders the list with a single element', () => { + expect(toastsProp).toBeDefined(); + expect(toastsProp).toHaveLength(1); + expect(euiToastList).toMatchSnapshot(); + }); + + it('renders the single toast with the common text', () => { + const firstRenderedToast = toastsProp![0]; + expect(firstRenderedToast.text).toBe(dummyText); + }); + + it(`calls all toast's dismiss when closed`, () => { + const firstRenderedToast = toastsProp![0]; + const dismissToast = globalToastList.prop('dismissToast'); + dismissToast(firstRenderedToast); + + expect(mockDismissToast).toHaveBeenCalledTimes(4); + expect(mockDismissToast).toHaveBeenCalledWith('0'); + expect(mockDismissToast).toHaveBeenCalledWith('1'); + expect(mockDismissToast).toHaveBeenCalledWith('2'); + expect(mockDismissToast).toHaveBeenCalledWith('3'); + }); +}); + +describe('global_toast_list with duplicate elements, using MountPoints', () => { + const dummyText = `You've got mail!`; + const toast = (id: any): Toast => ({ + id: id.toString(), + text: dummyText, + title: (element) => { + const a = document.createElement('a'); + a.innerText = 'Click me!'; + a.href = 'https://elastic.co'; + element.appendChild(a); + return () => element.removeChild(a); + }, + toastLifeTimeMs: 5000, + }); + + const globalToastList = shallow( + render({ + toasts$: from([[toast(0), toast(1), toast(2), toast(3)]]) as any, + }) + ); + + const euiToastList = globalToastList.find(EuiGlobalToastList); + const toastsProp = euiToastList.prop('toasts'); + + it('renders the all separate elements element', () => { + expect(toastsProp).toBeDefined(); + expect(toastsProp).toHaveLength(4); + expect(euiToastList).toMatchSnapshot('euiToastList'); + expect(globalToastList).toMatchSnapshot('globalToastList'); + }); +}); diff --git a/packages/core/notifications/core-notifications-browser-internal/src/toasts/global_toast_list.tsx b/packages/core/notifications/core-notifications-browser-internal/src/toasts/global_toast_list.tsx index db700da12cf0a..e0a5d631d3776 100644 --- a/packages/core/notifications/core-notifications-browser-internal/src/toasts/global_toast_list.tsx +++ b/packages/core/notifications/core-notifications-browser-internal/src/toasts/global_toast_list.tsx @@ -13,6 +13,7 @@ import { i18n } from '@kbn/i18n'; import type { Toast } from '@kbn/core-notifications-browser'; import { MountWrapper } from '@kbn/core-mount-utils-browser-internal'; +import { deduplicateToasts, ToastWithRichTitle } from './deduplicate_toasts'; interface Props { toasts$: Observable; @@ -20,25 +21,28 @@ interface Props { } interface State { - toasts: Toast[]; + toasts: ToastWithRichTitle[]; + idToToasts: Record; } -const convertToEui = (toast: Toast): EuiToast => ({ +const convertToEui = (toast: ToastWithRichTitle): EuiToast => ({ ...toast, - title: typeof toast.title === 'function' ? : toast.title, - text: typeof toast.text === 'function' ? : toast.text, + title: toast.title instanceof Function ? : toast.title, + text: toast.text instanceof Function ? : toast.text, }); export class GlobalToastList extends React.Component { public state: State = { toasts: [], + idToToasts: {}, }; private subscription?: Subscription; public componentDidMount() { - this.subscription = this.props.toasts$.subscribe((toasts) => { - this.setState({ toasts }); + this.subscription = this.props.toasts$.subscribe((redundantToastList) => { + const { toasts, idToToasts } = deduplicateToasts(redundantToastList); + this.setState({ toasts, idToToasts }); }); } @@ -48,6 +52,13 @@ export class GlobalToastList extends React.Component { } } + private closeToastsRepresentedById(id: string) { + const representedToasts = this.state.idToToasts[id]; + if (representedToasts) { + representedToasts.forEach((toast) => this.props.dismissToast(toast.id)); + } + } + public render() { return ( { })} data-test-subj="globalToastList" toasts={this.state.toasts.map(convertToEui)} - dismissToast={({ id }) => this.props.dismissToast(id)} + dismissToast={({ id }) => this.closeToastsRepresentedById(id)} /** * This prop is overridden by the individual toasts that are added. * Use `Infinity` here so that it's obvious a timeout hasn't been diff --git a/packages/core/notifications/core-notifications-browser-internal/tsconfig.json b/packages/core/notifications/core-notifications-browser-internal/tsconfig.json index f2828768aa26b..a2cdcd20e4889 100644 --- a/packages/core/notifications/core-notifications-browser-internal/tsconfig.json +++ b/packages/core/notifications/core-notifications-browser-internal/tsconfig.json @@ -28,6 +28,7 @@ "@kbn/test-jest-helpers", "@kbn/core-overlays-browser-mocks", "@kbn/core-theme-browser-mocks", + "@kbn/core-mount-utils-browser", ], "exclude": [ "target/**/*", diff --git a/packages/kbn-es/src/artifact.ts b/packages/kbn-es/src/artifact.ts index 04cde128181b3..57a0e6fd5db06 100644 --- a/packages/kbn-es/src/artifact.ts +++ b/packages/kbn-es/src/artifact.ts @@ -14,7 +14,6 @@ import { pipeline, Transform } from 'stream'; import { setTimeout } from 'timers/promises'; import fetch, { Headers } from 'node-fetch'; -import AbortController from 'abort-controller'; import chalk from 'chalk'; import { ToolingLog } from '@kbn/tooling-log'; diff --git a/packages/kbn-monaco/BUILD.bazel b/packages/kbn-monaco/BUILD.bazel index 8d13702e74588..2ca10b073fd18 100644 --- a/packages/kbn-monaco/BUILD.bazel +++ b/packages/kbn-monaco/BUILD.bazel @@ -56,9 +56,11 @@ webpack_cli( env = select({ "//:dist": { "NODE_ENV": "production", + "NODE_OPTIONS": "--openssl-legacy-provider", }, "//conditions:default": { "NODE_ENV": "development", + "NODE_OPTIONS": "--openssl-legacy-provider", }, }), visibility = ["//visibility:public"], diff --git a/packages/kbn-optimizer/src/optimizer/observe_worker.ts b/packages/kbn-optimizer/src/optimizer/observe_worker.ts index 22674f7ca8699..0ac2dda605e92 100644 --- a/packages/kbn-optimizer/src/optimizer/observe_worker.ts +++ b/packages/kbn-optimizer/src/optimizer/observe_worker.ts @@ -61,6 +61,7 @@ function usingWorkerProc(config: OptimizerConfig, fn: (proc: ChildProcess) => const proc = fork(require.resolve('../worker/run_worker'), [], { execArgv: [ `--require=@kbn/babel-register/install`, + '--openssl-legacy-provider', ...(inspectFlag && config.inspectWorkers ? [`${inspectFlag}=${inspectPortCounter++}`] : []), diff --git a/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts b/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts index 5b6f7404e64a0..e3d1ca81e2c26 100644 --- a/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts +++ b/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts @@ -39,6 +39,9 @@ it('builds a generated plugin into a viable archive', async () => { process.execPath, ['scripts/generate_plugin', '-y', '--name', 'fooTestPlugin'], { + env: { + NODE_OPTIONS: '--openssl-legacy-provider', + }, cwd: REPO_ROOT, all: true, } @@ -61,6 +64,9 @@ it('builds a generated plugin into a viable archive', async () => { process.execPath, ['../../scripts/plugin_helpers', 'build', '--kibana-version', '7.5.0'], { + env: { + NODE_OPTIONS: '--openssl-legacy-provider', + }, cwd: PLUGIN_DIR, all: true, } diff --git a/packages/kbn-ui-shared-deps-npm/BUILD.bazel b/packages/kbn-ui-shared-deps-npm/BUILD.bazel index e20aabc31a025..3b6cf5f0dfeda 100644 --- a/packages/kbn-ui-shared-deps-npm/BUILD.bazel +++ b/packages/kbn-ui-shared-deps-npm/BUILD.bazel @@ -86,9 +86,11 @@ webpack_cli( env = select({ "//:dist": { "NODE_ENV": "production", + "NODE_OPTIONS": "--openssl-legacy-provider", }, "//conditions:default": { "NODE_ENV": "development", + "NODE_OPTIONS": "--openssl-legacy-provider", }, }) ) diff --git a/packages/kbn-ui-shared-deps-src/BUILD.bazel b/packages/kbn-ui-shared-deps-src/BUILD.bazel index 0b350c51331ff..49c2cc62dcfe5 100644 --- a/packages/kbn-ui-shared-deps-src/BUILD.bazel +++ b/packages/kbn-ui-shared-deps-src/BUILD.bazel @@ -45,9 +45,11 @@ webpack_cli( env = select({ "//:dist": { "NODE_ENV": "production", + "NODE_OPTIONS": "--openssl-legacy-provider", }, "//conditions:default": { "NODE_ENV": "development", + "NODE_OPTIONS": "--openssl-legacy-provider", }, }), visibility = ["//visibility:public"], diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts index 2a60484107362..063ed46c443f6 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts @@ -142,7 +142,7 @@ describe('checking migration metadata changes on all registered SO types', () => "spaces-usage-stats": "3abca98713c52af8b30300e386c7779b3025a20e", "synthetics-monitor": "33ddc4b8979f378edf58bcc7ba13c5c5b572f42d", "synthetics-param": "3ebb744e5571de678b1312d5c418c8188002cf5e", - "synthetics-privates-locations": "9cfbd6d1d2e2c559bf96dd6fbc27ff0c47719dd3", + "synthetics-privates-locations": "f53d799d5c9bc8454aaa32c6abc99a899b025d5c", "tag": "e2544392fe6563e215bb677abc8b01c2601ef2dc", "task": "04f30bd7bae923f3a53c31ab3b9745a93872fc02", "telemetry": "7b00bcf1c7b4f6db1192bb7405a6a63e78b699fd", diff --git a/src/dev/build/lib/download.ts b/src/dev/build/lib/download.ts index d39cb7d77f961..ea9f56cb4fe35 100644 --- a/src/dev/build/lib/download.ts +++ b/src/dev/build/lib/download.ts @@ -112,7 +112,7 @@ export async function downloadToDisk({ const downloadedSha = hash.digest('hex'); if (downloadedSha !== shaChecksum) { throw new Error( - `Downloaded checksum ${downloadedSha} does not match the expected ${shaAlgorithm} checksum.` + `Downloaded checksum ${downloadedSha} does not match the expected (${shaAlgorithm}) checksum ${shaChecksum}, for file: ${url}.` ); } } diff --git a/src/dev/build/lib/integration_tests/download.test.ts b/src/dev/build/lib/integration_tests/download.test.ts index 7046a831d84f0..8291427d34e32 100644 --- a/src/dev/build/lib/integration_tests/download.test.ts +++ b/src/dev/build/lib/integration_tests/download.test.ts @@ -113,7 +113,7 @@ describe('downloadToDisk', () => { shaAlgorithm: 'sha256', }); await expect(promise).rejects.toMatchInlineSnapshot( - `[Error: Downloaded checksum 2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae does not match the expected sha256 checksum.]` + `[Error: Downloaded checksum ${FOO_SHA256} does not match the expected (sha256) checksum bar, for file: ${serverUrl}.]` ); try { @@ -175,7 +175,7 @@ describe('downloadToDisk', () => { " info Retrying in 0.1 seconds", " debg [2/3] Attempting download of TEST_SERVER_URL sha256", " debg Downloaded 3 bytes to TMP_DIR/__tmp_download_js_test_file__", - " debg Download failed: Downloaded checksum fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 does not match the expected sha256 checksum.", + " debg Download failed: Downloaded checksum fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 does not match the expected (sha256) checksum 2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae, for file: TEST_SERVER_URL.", " debg Deleting downloaded data at TMP_DIR/__tmp_download_js_test_file__", " info Retrying in 0.2 seconds", " debg [3/3] Attempting download of TEST_SERVER_URL sha256", diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker index d35b39efca4eb..43df58235e68d 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker @@ -307,6 +307,7 @@ kibana_vars=( xpack.observability.unsafe.alertDetails.metrics.enabled xpack.observability.unsafe.alertDetails.logs.enabled xpack.observability.unsafe.alertDetails.uptime.enabled + xpack.observability.unsafe.alertDetails.observability.enabled xpack.observability.unsafe.thresholdRule.enabled xpack.observability.compositeSlo.enabled xpack.reporting.capture.browser.autoDownload diff --git a/src/dev/build/tasks/patch_native_modules_task.ts b/src/dev/build/tasks/patch_native_modules_task.ts index 2c4436f387dfe..f7b323f13efc7 100644 --- a/src/dev/build/tasks/patch_native_modules_task.ts +++ b/src/dev/build/tasks/patch_native_modules_task.ts @@ -41,17 +41,13 @@ interface Package { const packages: Package[] = [ { name: 're2', - version: '1.17.4', + version: '1.17.7', destinationPath: 'node_modules/re2/build/Release/re2.node', extractMethod: 'gunzip', archives: { - 'darwin-x64': { - url: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-re2/uhop/node-re2/releases/download/1.17.4/darwin-x64-93.gz', - sha256: '9558c5cb39622e9b3653203e772b129d6c634e7dbd7af1b244352fc1d704601f', - }, 'linux-x64': { - url: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-re2/uhop/node-re2/releases/download/1.17.4/linux-x64-93.gz', - sha256: '4d06747b266c75b6f7ced93977692c0586ce6a52924cabb569bd966378941aa1', + url: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-re2/uhop/node-re2/releases/download/1.17.7/linux-x64-108.gz', + sha256: 'e0b62ff7c415c95f57232f2726711c0fd71056c848538f095ba3fa1126ef5e31', }, // ARM builds are currently done manually as Github Actions used in upstream project @@ -67,8 +63,13 @@ const packages: Package[] = [ // * capture the sha256 with: `shasum -a 256 linux-arm64-*` // * upload the `linux-arm64-*.gz` artifact to the `yarn-prebuilt-artifacts` bucket in GCS using the correct version number 'linux-arm64': { - url: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-re2/uhop/node-re2/releases/download/1.17.4/linux-arm64-93.gz', - sha256: '25409584f76f3d6ed85463d84adf094eb6e256ed1cb0b754b95bcbda6691fc26', + url: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-re2/uhop/node-re2/releases/download/1.17.7/linux-arm64-108.gz', + sha256: 'e2025ead87be9f1ec4a9d892d1cce69c573101762720d56f52b1d52ed7ae0fef', + }, + + 'darwin-x64': { + url: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-re2/uhop/node-re2/releases/download/1.17.7/darwin-x64-108.gz', + sha256: '4ed378c5a7fe6134b717afe7642254aff1ed7a881cbcaa53a012ac3efab49f99', }, // A similar process is necessary for building on ARM macs: @@ -78,13 +79,13 @@ const packages: Package[] = [ // * capture the sha256 with: `shasum -a 256 darwin-arm64-*` // * upload the `darwin-arm64-*.gz` artifact to the `yarn-prebuilt-artifacts` bucket in GCS using the correct version number 'darwin-arm64': { - url: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-re2/uhop/node-re2/releases/download/1.17.4/darwin-arm64-93.gz', - sha256: 'd4b708749ddef1c87019f6b80e051ed0c29ccd1de34f233c47d8dcaddf803872', + url: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-re2/uhop/node-re2/releases/download/1.17.7/darwin-arm64-108.gz', + sha256: '42afc32137ff5c5bebae5d68347a9786906748c2f28e06194d8950707f2ae90e', }, 'win32-x64': { - url: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-re2/uhop/node-re2/releases/download/1.17.4/win32-x64-93.gz', - sha256: '0320d0c0385432944c6fb3c8c8fcd78d440ce5626f7618f9ec71d88e44820674', + url: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-re2/uhop/node-re2/releases/download/1.17.7/win32-x64-108.gz', + sha256: 'ff72fe02de652262659c8e17e44a932f3c873362233756b40d1a97538d05de92', }, }, }, diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js b/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js index 244092d04ff87..0d04f3b8e372f 100644 --- a/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js +++ b/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js @@ -39,7 +39,10 @@ describe('Editor', () => { oldUrl = global.URL; olldWindow = { ...global.window }; global.URL = URL; - global.window = Object.create(window); + Object.defineProperty(global, 'window', { + value: Object.create(window), + writable: true, + }); Object.defineProperty(window, 'location', { value: { origin: 'http://localhost:5620', diff --git a/src/plugins/kibana_usage_collection/server/collectors/cloud/cloud_provider_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/cloud/cloud_provider_collector.ts index 238462cf863c7..6939b20f4169c 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/cloud/cloud_provider_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/cloud/cloud_provider_collector.ts @@ -7,7 +7,6 @@ */ import { firstValueFrom, type Observable } from 'rxjs'; -import AbortController from 'abort-controller'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { CloudDetector } from './detector'; diff --git a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/aws.ts b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/aws.ts index ca1fe78aab5bf..833548f55b8d6 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/aws.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/aws.ts @@ -9,7 +9,6 @@ import { readFile } from 'fs/promises'; import { get, omit } from 'lodash'; import fetch from 'node-fetch'; -import { AbortSignal } from 'abort-controller'; import { CloudService } from './cloud_service'; import { CloudServiceResponse } from './cloud_response'; diff --git a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/azure.ts b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/azure.ts index 11a84b2e86014..23b86be59a641 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/azure.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/azure.ts @@ -8,7 +8,6 @@ import { get, omit } from 'lodash'; import fetch from 'node-fetch'; -import { AbortSignal } from 'abort-controller'; import { CloudService } from './cloud_service'; import { CloudServiceResponse } from './cloud_response'; diff --git a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/cloud_detector.ts b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/cloud_detector.ts index d3664f8c94daa..7e79f26d23041 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/cloud_detector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/cloud_detector.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { AbortSignal } from 'abort-controller'; import type { CloudService } from './cloud_service'; import type { CloudServiceResponseJson } from './cloud_response'; diff --git a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/cloud_service.ts b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/cloud_service.ts index e6751321528a2..58ab235225390 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/cloud_service.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/cloud_service.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { AbortSignal } from 'abort-controller'; import { isObject, isPlainObject } from 'lodash'; import { CloudServiceResponse } from './cloud_response'; diff --git a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/gcp.ts b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/gcp.ts index 2c73a81fc94da..816354524166b 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/gcp.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/cloud/detector/gcp.ts @@ -7,7 +7,6 @@ */ import fetch, { Response } from 'node-fetch'; -import { AbortSignal } from 'abort-controller'; import { CloudService } from './cloud_service'; import { CloudServiceResponse } from './cloud_response'; diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index d60914578b2f7..4f604e0fad3b8 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -284,6 +284,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.observability.unsafe.alertDetails.metrics.enabled (boolean)', 'xpack.observability.unsafe.alertDetails.logs.enabled (boolean)', 'xpack.observability.unsafe.alertDetails.uptime.enabled (boolean)', + 'xpack.observability.unsafe.alertDetails.observability.enabled (boolean)', 'xpack.observability.unsafe.thresholdRule.enabled (boolean)', 'xpack.observability_onboarding.ui.enabled (boolean)', /** diff --git a/x-pack/README.md b/x-pack/README.md index 9c554c651b41f..ea8777f46b143 100644 --- a/x-pack/README.md +++ b/x-pack/README.md @@ -26,6 +26,12 @@ xpack.observability.unsafe.alertDetails.uptime.enabled: true **[For Uptime rule type]** In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table +```yaml +xpack.observability.unsafe.alertDetails.observability.enabled: true +``` + +**[For Observability Threshold rule type]** In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table + # Development By default, Kibana will run with X-Pack installed as mentioned in the [contributing guide](../CONTRIBUTING.md). diff --git a/x-pack/plugins/actions/server/lib/request_oauth_client_credentials_token.test.ts b/x-pack/plugins/actions/server/lib/request_oauth_client_credentials_token.test.ts index 20896e2691f10..223c8c28b55bc 100644 --- a/x-pack/plugins/actions/server/lib/request_oauth_client_credentials_token.test.ts +++ b/x-pack/plugins/actions/server/lib/request_oauth_client_credentials_token.test.ts @@ -74,6 +74,7 @@ describe('requestOAuthClientCredentialsToken', () => { "maxSockets": Infinity, "maxTotalSockets": Infinity, "options": Object { + "noDelay": true, "path": null, "rejectUnauthorized": true, }, diff --git a/x-pack/plugins/actions/server/lib/request_oauth_jwt_token.test.ts b/x-pack/plugins/actions/server/lib/request_oauth_jwt_token.test.ts index 318775762bbbd..af65bcf67d3db 100644 --- a/x-pack/plugins/actions/server/lib/request_oauth_jwt_token.test.ts +++ b/x-pack/plugins/actions/server/lib/request_oauth_jwt_token.test.ts @@ -75,6 +75,7 @@ describe('requestOAuthJWTToken', () => { "maxSockets": Infinity, "maxTotalSockets": Infinity, "options": Object { + "noDelay": true, "path": null, "rejectUnauthorized": true, }, diff --git a/x-pack/plugins/actions/server/lib/request_oauth_token.test.ts b/x-pack/plugins/actions/server/lib/request_oauth_token.test.ts index cc9ea6a74517a..9843783aadf8d 100644 --- a/x-pack/plugins/actions/server/lib/request_oauth_token.test.ts +++ b/x-pack/plugins/actions/server/lib/request_oauth_token.test.ts @@ -82,6 +82,7 @@ describe('requestOAuthToken', () => { "maxSockets": Infinity, "maxTotalSockets": Infinity, "options": Object { + "noDelay": true, "path": null, "rejectUnauthorized": true, }, diff --git a/x-pack/plugins/apm/public/components/app/storage_explorer/services_table/index.tsx b/x-pack/plugins/apm/public/components/app/storage_explorer/services_table/index.tsx index cbe7d908c8acc..b9ed2e6730275 100644 --- a/x-pack/plugins/apm/public/components/app/storage_explorer/services_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/storage_explorer/services_table/index.tsx @@ -112,12 +112,14 @@ export function ServicesTable() { environment, kuery, indexLifecyclePhase, + start, + end, }, }, }); } }, - [environment, kuery, indexLifecyclePhase, useOptimizedSorting] + [useOptimizedSorting, environment, kuery, indexLifecyclePhase, start, end] ); const serviceStatisticsFetch = useProgressiveFetcher( diff --git a/x-pack/plugins/apm/server/routes/services/get_services/get_service_names_from_terms_enum.ts b/x-pack/plugins/apm/server/routes/services/get_services/get_service_names_from_terms_enum.ts index 0e40a35c1bb6b..1a40ce8ee88e4 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services/get_service_names_from_terms_enum.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/get_service_names_from_terms_enum.ts @@ -15,10 +15,14 @@ export async function getServiceNamesFromTermsEnum({ apmEventClient, environment, maxNumberOfServices, + start, + end, }: { apmEventClient: APMEventClient; environment: Environment; maxNumberOfServices: number; + start: number; + end: number; }) { if (environment !== ENVIRONMENT_ALL.value) { return []; @@ -36,6 +40,15 @@ export async function getServiceNamesFromTermsEnum({ }, size: maxNumberOfServices, field: SERVICE_NAME, + index_filter: { + range: { + ['@timestamp']: { + gte: start, + lte: end, + format: 'epoch_millis', + }, + }, + }, } ); diff --git a/x-pack/plugins/apm/server/routes/storage_explorer/route.ts b/x-pack/plugins/apm/server/routes/storage_explorer/route.ts index 3a862ab90aca4..39eb0f6f65881 100644 --- a/x-pack/plugins/apm/server/routes/storage_explorer/route.ts +++ b/x-pack/plugins/apm/server/routes/storage_explorer/route.ts @@ -323,7 +323,12 @@ const storageExplorerGetServices = createApmServerRoute({ tags: ['access:apm'], }, params: t.type({ - query: t.intersection([indexLifecyclePhaseRt, environmentRt, kueryRt]), + query: t.intersection([ + indexLifecyclePhaseRt, + environmentRt, + kueryRt, + rangeRt, + ]), }), handler: async ( resources @@ -333,7 +338,7 @@ const storageExplorerGetServices = createApmServerRoute({ }>; }> => { const { - query: { environment, kuery, indexLifecyclePhase }, + query: { environment, kuery, indexLifecyclePhase, start, end }, } = resources.params; if ( @@ -352,6 +357,8 @@ const storageExplorerGetServices = createApmServerRoute({ apmEventClient, environment, maxNumberOfServices: 500, + start, + end, }); return { diff --git a/x-pack/plugins/canvas/scripts/shareable_runtime.js b/x-pack/plugins/canvas/scripts/shareable_runtime.js index a0b8421f8da01..f3e1e66c1744a 100644 --- a/x-pack/plugins/canvas/scripts/shareable_runtime.js +++ b/x-pack/plugins/canvas/scripts/shareable_runtime.js @@ -55,6 +55,7 @@ run( execa.sync( process.execPath, [ + '--openssl-legacy-provider', require.resolve('webpack-dev-server/bin/webpack-dev-server'), '--config', webpackConfig, @@ -88,6 +89,7 @@ run( execa.sync( process.execPath, [ + '--openssl-legacy-provider', require.resolve('webpack/bin/webpack'), '--config', webpackConfig, diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts index 7d849d23df80d..16aa1ab0100b9 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts @@ -5,7 +5,6 @@ * 2.0. */ -import AbortController from 'abort-controller'; import fetch from 'node-fetch'; import { KibanaRequest, Logger } from '@kbn/core/server'; diff --git a/x-pack/plugins/lists/public/exceptions/api.test.ts b/x-pack/plugins/lists/public/exceptions/api.test.ts index a0f2bf9c21fe4..318bbde58688d 100644 --- a/x-pack/plugins/lists/public/exceptions/api.test.ts +++ b/x-pack/plugins/lists/public/exceptions/api.test.ts @@ -689,7 +689,7 @@ describe('Exceptions Lists API', () => { stream: jest.fn(), text: jest.fn(), type: 'json', - } as Blob; + } as unknown as Blob; beforeEach(() => { httpMock.fetch.mockResolvedValue(blob); diff --git a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx index 4fd78735bdb68..79d058fb5f632 100644 --- a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx +++ b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx @@ -84,6 +84,7 @@ const withCore = makeDecorator({ logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, + observability: { enabled: false }, }, thresholdRule: { enabled: false }, }, diff --git a/x-pack/plugins/observability/public/pages/rules/rules.test.tsx b/x-pack/plugins/observability/public/pages/rules/rules.test.tsx index 0c5a18c5ac9c7..d0d8678488aa6 100644 --- a/x-pack/plugins/observability/public/pages/rules/rules.test.tsx +++ b/x-pack/plugins/observability/public/pages/rules/rules.test.tsx @@ -40,6 +40,7 @@ jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({ logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, + observability: { enabled: false }, }, thresholdRule: { enabled: false }, }, diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts index 287248538b633..fc6753e5997a8 100644 --- a/x-pack/plugins/observability/public/plugin.ts +++ b/x-pack/plugins/observability/public/plugin.ts @@ -86,6 +86,9 @@ export interface ConfigSchema { uptime: { enabled: boolean; }; + observability: { + enabled: boolean; + }; }; thresholdRule: { enabled: boolean; diff --git a/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts index 6432563897e16..15b9589be60f6 100644 --- a/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts +++ b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts @@ -14,7 +14,7 @@ const ALLOWED_RULE_TYPES = ['apm.transaction_duration']; const isUnsafeAlertDetailsFlag = ( subject: string ): subject is keyof ConfigSchema['unsafe']['alertDetails'] => - ['uptime', 'logs', 'metrics'].includes(subject); + ['uptime', 'logs', 'metrics', 'observability'].includes(subject); // We are mapping the ruleTypeId from the feature flag with the ruleTypeId from the alert // to know whether the feature flag is enabled or not. diff --git a/x-pack/plugins/observability/public/utils/kibana_react.storybook_decorator.tsx b/x-pack/plugins/observability/public/utils/kibana_react.storybook_decorator.tsx index e56487549a689..8a89cb6cf93f2 100644 --- a/x-pack/plugins/observability/public/utils/kibana_react.storybook_decorator.tsx +++ b/x-pack/plugins/observability/public/utils/kibana_react.storybook_decorator.tsx @@ -31,6 +31,7 @@ export function KibanaReactStorybookDecorator(Story: ComponentType) { logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, + observability: { enabled: false }, }, thresholdRule: { enabled: false }, }, diff --git a/x-pack/plugins/observability/public/utils/test_helper.tsx b/x-pack/plugins/observability/public/utils/test_helper.tsx index c979eaef6b879..3b84ffe786f91 100644 --- a/x-pack/plugins/observability/public/utils/test_helper.tsx +++ b/x-pack/plugins/observability/public/utils/test_helper.tsx @@ -35,6 +35,7 @@ const defaultConfig: ConfigSchema = { logs: { enabled: false }, metrics: { enabled: false }, uptime: { enabled: false }, + observability: { enabled: false }, }, thresholdRule: { enabled: false }, }, diff --git a/x-pack/plugins/observability/server/index.ts b/x-pack/plugins/observability/server/index.ts index 1f06f63c5de00..6c6b68981b117 100644 --- a/x-pack/plugins/observability/server/index.ts +++ b/x-pack/plugins/observability/server/index.ts @@ -42,6 +42,9 @@ const configSchema = schema.object({ uptime: schema.object({ enabled: schema.boolean({ defaultValue: false }), }), + observability: schema.object({ + enabled: schema.boolean({ defaultValue: false }), + }), }), thresholdRule: schema.object({ enabled: schema.boolean({ defaultValue: false }), diff --git a/x-pack/plugins/observability_onboarding/public/components/app/custom_logs/wizard/install_elastic_agent.tsx b/x-pack/plugins/observability_onboarding/public/components/app/custom_logs/wizard/install_elastic_agent.tsx index 526f2970c5533..e29a2d84036e9 100644 --- a/x-pack/plugins/observability_onboarding/public/components/app/custom_logs/wizard/install_elastic_agent.tsx +++ b/x-pack/plugins/observability_onboarding/public/components/app/custom_logs/wizard/install_elastic_agent.tsx @@ -8,28 +8,25 @@ import { EuiButton, EuiButtonEmpty, - EuiButtonGroup, - EuiCallOut, - EuiCodeBlock, EuiFlexGroup, EuiFlexItem, - EuiIconTip, - EuiLink, - EuiSkeletonRectangle, EuiSpacer, - EuiSteps, - EuiStepsProps, - EuiSwitch, EuiText, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { Buffer } from 'buffer'; -import { flatten, zip } from 'lodash'; import { default as React, useCallback, useEffect, useState } from 'react'; import { useWizard } from '.'; import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher'; import { useKibanaNavigation } from '../../../../hooks/use_kibana_navigation'; +import { + ElasticAgentPlatform, + getElasticAgentSetupCommand, +} from '../../../shared/get_elastic_agent_setup_command'; +import { + InstallElasticAgentSteps, + ProgressStepId, + EuiStepStatus, +} from '../../../shared/install_elastic_agent_steps'; import { StepPanel, StepPanelContent, @@ -37,9 +34,7 @@ import { } from '../../../shared/step_panel'; import { ApiKeyBanner } from './api_key_banner'; import { BackButton } from './back_button'; -import { StepStatus } from './step_status'; -type ElasticAgentPlatform = 'linux-tar' | 'macos' | 'windows'; export function InstallElasticAgent() { const { navigateToKibanaUrl } = useKibanaNavigation(); const { goBack, goToStep, getState, setState } = useWizard(); @@ -196,56 +191,29 @@ export function InstallElasticAgent() { } }, [progressSucceded, refetchProgress]); - const getStep = useCallback( - ({ id, incompleteTitle, loadingTitle, completedTitle }) => { - const progress = progressData?.progress; - if (progress) { - const stepStatus = progress?.[id] - ?.status as EuiStepsProps['steps'][number]['status']; - const title = - stepStatus === 'loading' - ? loadingTitle - : stepStatus === 'complete' - ? completedTitle - : incompleteTitle; - return { - title, - children: null, - status: stepStatus ?? ('incomplete' as const), - message: progress?.[id]?.message, - }; - } - return { - title: incompleteTitle, - children: null, - status: 'incomplete' as const, - }; - }, - [progressData?.progress] - ); + const getCheckLogsStep = useCallback(() => { + const progress = progressData?.progress; + if (progress) { + const stepStatus = progress?.['logs-ingest']?.status as EuiStepStatus; + const title = + stepStatus === 'loading' + ? CHECK_LOGS_LABELS.loading + : stepStatus === 'complete' + ? CHECK_LOGS_LABELS.completed + : CHECK_LOGS_LABELS.incomplete; + return { title, status: stepStatus }; + } + return { + title: CHECK_LOGS_LABELS.incomplete, + status: 'incomplete' as const, + }; + }, [progressData?.progress]); const isInstallStarted = progressData?.progress['ea-download'] !== undefined; const isInstallCompleted = progressData?.progress?.['ea-status']?.status === 'complete'; - - const autoDownloadConfigStep = getStep({ - id: 'ea-config', - incompleteTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaConfig.incompleteTitle', - { defaultMessage: 'Configure the agent' } - ), - loadingTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaConfig.loadingTitle', - { defaultMessage: 'Downloading Elastic Agent config' } - ), - completedTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaConfig.completedTitle', - { - defaultMessage: 'Elastic Agent config written to {configPath}', - values: { configPath: '/opt/Elastic/Agent/elastic-agent.yml' }, - } - ), - }); + const autoDownloadConfigStatus = (progressData?.progress?.['ea-config'] + ?.status ?? 'incomplete') as EuiStepStatus; return ( - - -

- - {i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.installStep.hostRequirements', - { - defaultMessage: - 'host requirements and other installation options', - } - )} - - ), - }} - /> -

-
- - - - {i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.installStep.autoDownloadConfig', - { - defaultMessage: - "Automatically download the agent's config", - } - )} - - - - - - } - checked={wizardState.autoDownloadConfig} - onChange={onAutoDownloadConfig} - disabled={ - isInstallStarted || - (monitoringRole && !monitoringRole?.hasPrivileges) - } - /> - - {wizardState.autoDownloadConfig && ( - <> - - - - )} - - setElasticAgentPlatform(id as typeof elasticAgentPlatform) - } - /> - - - {getInstallShipperCommand({ - elasticAgentPlatform, - apiKeyEncoded, - apiEndpoint: setup?.apiEndpoint, - scriptDownloadUrl: setup?.scriptDownloadUrl, - elasticAgentVersion: setup?.elasticAgentVersion, - autoDownloadConfig: wizardState.autoDownloadConfig, - onboardingId, - })} - - - {isInstallStarted && ( - <> - - - {[ - { - id: 'ea-download', - incompleteTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaDownload.incompleteTitle', - { defaultMessage: 'Download Elastic Agent' } - ), - loadingTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaDownload.loadingTitle', - { defaultMessage: 'Downloading Elastic Agent' } - ), - completedTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaDownload.completedTitle', - { defaultMessage: 'Elastic Agent downloaded' } - ), - }, - { - id: 'ea-extract', - incompleteTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaExtract.incompleteTitle', - { defaultMessage: 'Extract Elastic Agent' } - ), - loadingTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaExtract.loadingTitle', - { defaultMessage: 'Extracting Elastic Agent' } - ), - completedTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaExtract.completedTitle', - { defaultMessage: 'Elastic Agent extracted' } - ), - }, - { - id: 'ea-install', - incompleteTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaInstall.incompleteTitle', - { defaultMessage: 'Install Elastic Agent' } - ), - loadingTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaInstall.loadingTitle', - { defaultMessage: 'Installing Elastic Agent' } - ), - completedTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaInstall.completedTitle', - { defaultMessage: 'Elastic Agent installed' } - ), - }, - { - id: 'ea-status', - incompleteTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaStatus.incompleteTitle', - { defaultMessage: 'Connect to the Elastic Agent' } - ), - loadingTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaStatus.loadingTitle', - { - defaultMessage: - 'Connecting to the Elastic Agent', - } - ), - completedTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.eaStatus.completedTitle', - { - defaultMessage: - 'Connected to the Elastic Agent', - } - ), - }, - ].map((step, index) => { - const { title, status, message } = getStep(step); - return ( - - ); - })} - - - )} - + label: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.linux', + { defaultMessage: 'Linux' } ), + id: 'linux-tar', }, { - title: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.configureStep.title', - { defaultMessage: 'Configure the Elastic agent' } - ), - status: - yamlConfigStatus === FETCH_STATUS.LOADING - ? 'loading' - : autoDownloadConfigStep.status, - children: ( - <> - -

- {wizardState.autoDownloadConfig - ? i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.configStep.auto.description', - { - defaultMessage: - 'The agent config below will be downloaded by the install script and written to ({configPath}). This will overwrite any existing agent configuration.', - values: { - configPath: - '/opt/Elastic/Agent/elastic-agent.yml', - }, - } - ) - : i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.configStep.manual.description', - { - defaultMessage: - 'Add the following configuration to {configPath} on the host where you installed the Elastic agent.', - values: { - configPath: - '/opt/Elastic/Agent/elastic-agent.yml', - }, - } - )} -

-
- - - - {yamlConfig} - - - - - {i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.configStep.downloadConfigButton', - { defaultMessage: 'Download config file' } - )} - - - - - - + label: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.macOS', + { defaultMessage: 'MacOS' } ), + id: 'macos', }, - getStep({ - id: 'logs-ingest', - incompleteTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.logsIngest.incompleteTitle', - { defaultMessage: 'Ship logs to Elastic Observability' } - ), - loadingTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.logsIngest.loadingTitle', - { defaultMessage: 'Waiting for Logs to be shipped...' } - ), - completedTitle: i18n.translate( - 'xpack.observability_onboarding.installElasticAgent.progress.logsIngest.completedTitle', - { defaultMessage: 'Logs are being shipped!' } + { + label: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.installStep.choosePlatform.windows', + { defaultMessage: 'Windows' } ), - }), + id: 'windows', + isDisabled: true, + }, ]} + onSelectPlatform={(id) => setElasticAgentPlatform(id)} + selectedPlatform={elasticAgentPlatform} + installAgentCommand={getElasticAgentSetupCommand({ + elasticAgentPlatform, + apiKeyEncoded, + apiEndpoint: setup?.apiEndpoint, + scriptDownloadUrl: setup?.scriptDownloadUrl, + elasticAgentVersion: setup?.elasticAgentVersion, + autoDownloadConfig: wizardState.autoDownloadConfig, + onboardingId, + })} + autoDownloadConfig={wizardState.autoDownloadConfig} + onToggleAutoDownloadConfig={onAutoDownloadConfig} + installAgentStatus={ + installShipperSetupStatus === FETCH_STATUS.LOADING + ? 'loading' + : isInstallCompleted + ? 'complete' + : 'current' + } + showInstallProgressSteps={isInstallStarted} + installProgressSteps={ + (progressData?.progress ?? {}) as Partial< + Record< + ProgressStepId, + { status: EuiStepStatus; message?: string } + > + > + } + configureAgentStatus={ + yamlConfigStatus === FETCH_STATUS.LOADING + ? 'loading' + : autoDownloadConfigStatus + } + configureAgentYaml={yamlConfig} + appendedSteps={[getCheckLogsStep()]} />
); } -function getInstallShipperCommand({ - elasticAgentPlatform, - apiKeyEncoded = '$API_KEY', - apiEndpoint = '$API_ENDPOINT', - scriptDownloadUrl = '$SCRIPT_DOWNLOAD_URL', - elasticAgentVersion = '$ELASTIC_AGENT_VERSION', - autoDownloadConfig = false, - onboardingId = '$ONBOARDING_ID', -}: { - elasticAgentPlatform: ElasticAgentPlatform; - apiKeyEncoded: string | undefined; - apiEndpoint: string | undefined; - scriptDownloadUrl: string | undefined; - elasticAgentVersion: string | undefined; - autoDownloadConfig: boolean; - onboardingId: string | undefined; -}) { - const setupScriptFilename = 'standalone_agent_setup.sh'; - const PLATFORM_COMMAND: Record = { - 'linux-tar': oneLine` - curl ${scriptDownloadUrl} -o ${setupScriptFilename} && - sudo bash ${setupScriptFilename} ${apiKeyEncoded} ${apiEndpoint} ${elasticAgentVersion} ${onboardingId} ${ - autoDownloadConfig ? 'autoDownloadConfig=1' : '' - } - `, - macos: oneLine` - curl -O https://elastic.co/agent-setup.sh && - sudo bash agent-setup.sh -- service.name=my-service --url=https://elasticsearch:8220 --enrollment-token=SRSc2ozWUItWXNuWE5oZzdERFU6anJtY0FIzhSRGlzeTJYcUF5UklfUQ== - `, - windows: oneLine` - curl -O https://elastic.co/agent-setup.sh && - sudo bash agent-setup.sh -- service.name=my-service --url=https://elasticsearch:8220 --enrollment-token=SRSc2ozWUItWXNuWE5oZzdERFU6anJtY0FIzhSRGlzeTJYcUF5UklfUQ== - `, - }; - return PLATFORM_COMMAND[elasticAgentPlatform]; -} - -function oneLine(parts: TemplateStringsArray, ...args: string[]) { - const str = flatten(zip(parts, args)).join(''); - return str.replace(/\s+/g, ' ').trim(); -} - type WizardState = ReturnType['getState']>; function hasAlreadySavedFlow({ apiKeyEncoded, onboardingId }: WizardState) { return Boolean(apiKeyEncoded && onboardingId); } + +const CHECK_LOGS_LABELS = { + incomplete: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.logsIngest.incompleteTitle', + { defaultMessage: 'Ship logs to Elastic Observability' } + ), + loading: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.logsIngest.loadingTitle', + { defaultMessage: 'Waiting for Logs to be shipped...' } + ), + completed: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.logsIngest.completedTitle', + { defaultMessage: 'Logs are being shipped!' } + ), +}; diff --git a/x-pack/plugins/observability_onboarding/public/components/shared/get_elastic_agent_setup_command.ts b/x-pack/plugins/observability_onboarding/public/components/shared/get_elastic_agent_setup_command.ts new file mode 100644 index 0000000000000..4bcd9aeeac3d9 --- /dev/null +++ b/x-pack/plugins/observability_onboarding/public/components/shared/get_elastic_agent_setup_command.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { flatten, zip } from 'lodash'; + +export type ElasticAgentPlatform = 'linux-tar' | 'macos' | 'windows'; + +export function getElasticAgentSetupCommand({ + elasticAgentPlatform, + apiKeyEncoded = '$API_KEY', + apiEndpoint = '$API_ENDPOINT', + scriptDownloadUrl = '$SCRIPT_DOWNLOAD_URL', + elasticAgentVersion = '$ELASTIC_AGENT_VERSION', + autoDownloadConfig = false, + onboardingId = '$ONBOARDING_ID', +}: { + elasticAgentPlatform: ElasticAgentPlatform; + apiKeyEncoded: string | undefined; + apiEndpoint: string | undefined; + scriptDownloadUrl: string | undefined; + elasticAgentVersion: string | undefined; + autoDownloadConfig: boolean; + onboardingId: string | undefined; +}) { + const setupScriptFilename = 'standalone_agent_setup.sh'; + const LINUX_MACOS_COMMAND = oneLine` + curl ${scriptDownloadUrl} -o ${setupScriptFilename} && + sudo bash ${setupScriptFilename} ${apiKeyEncoded} ${apiEndpoint} ${elasticAgentVersion} ${onboardingId} ${ + autoDownloadConfig ? `autoDownloadConfig=1` : '' + } + `; + const PLATFORM_COMMAND: Record = { + 'linux-tar': LINUX_MACOS_COMMAND, + macos: LINUX_MACOS_COMMAND, + windows: oneLine` + curl -O https://elastic.co/agent-setup.sh && + sudo bash agent-setup.sh -- service.name=my-service --url=https://elasticsearch:8220 --enrollment-token=SRSc2ozWUItWXNuWE5oZzdERFU6anJtY0FIzhSRGlzeTJYcUF5UklfUQ== + `, + }; + return PLATFORM_COMMAND[elasticAgentPlatform]; +} + +function oneLine(parts: TemplateStringsArray, ...args: string[]) { + const str = flatten(zip(parts, args)).join(''); + return str.replace(/\s+/g, ' ').trim(); +} diff --git a/x-pack/plugins/observability_onboarding/public/components/shared/install_elastic_agent_steps.tsx b/x-pack/plugins/observability_onboarding/public/components/shared/install_elastic_agent_steps.tsx new file mode 100644 index 0000000000000..7eef98b4bc301 --- /dev/null +++ b/x-pack/plugins/observability_onboarding/public/components/shared/install_elastic_agent_steps.tsx @@ -0,0 +1,425 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + EuiButton, + EuiButtonGroup, + EuiCallOut, + EuiCodeBlock, + EuiFlexGroup, + EuiFlexItem, + EuiIconTip, + EuiLink, + EuiSkeletonRectangle, + EuiSpacer, + EuiSteps, + EuiStepsProps, + EuiSwitch, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { Buffer } from 'buffer'; +import React from 'react'; +import { intersection } from 'lodash'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { StepStatus } from './step_status'; + +export type EuiStepStatus = EuiStepsProps['steps'][number]['status']; + +export type ProgressStepId = + | 'ea-download' + | 'ea-extract' + | 'ea-install' + | 'ea-status' + | 'ea-config'; + +interface Props { + installAgentPlatformOptions: Array<{ + label: string; + id: PlatformId; + isDisabled?: boolean; + }>; + onSelectPlatform: (id: PlatformId) => void; + selectedPlatform: PlatformId; + installAgentCommand: string; + autoDownloadConfig: boolean; + onToggleAutoDownloadConfig: () => void; + installAgentStatus: EuiStepStatus; + showInstallProgressSteps: boolean; + installProgressSteps: Partial< + Record + >; + configureAgentStatus: EuiStepStatus; + configureAgentYaml: string; + appendedSteps?: Array>; +} + +export function InstallElasticAgentSteps({ + installAgentPlatformOptions, + onSelectPlatform, + selectedPlatform, + installAgentCommand, + autoDownloadConfig, + onToggleAutoDownloadConfig, + installAgentStatus, + showInstallProgressSteps, + installProgressSteps, + configureAgentStatus, + configureAgentYaml, + appendedSteps = [], +}: Props) { + const isInstallStarted = + intersection( + Object.keys(installProgressSteps), + Object.keys(PROGRESS_STEP_TITLES) + ).length > 0; + const autoDownloadConfigStep = getStep('ea-config', installProgressSteps); + return ( + + +

+ + {i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.installStep.hostRequirements', + { + defaultMessage: + 'host requirements and other installation options', + } + )} + + ), + }} + /> +

+
+ + + + {i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.installStep.autoDownloadConfig', + { + defaultMessage: + "Automatically download the agent's config", + } + )} + + + + + + } + checked={autoDownloadConfig} + onChange={onToggleAutoDownloadConfig} + disabled={isInstallStarted} + /> + + {autoDownloadConfig && ( + <> + + + + )} + ({ + id, + label, + isDisabled, + }) + )} + type="single" + idSelected={selectedPlatform} + onChange={(id: string) => { + onSelectPlatform(id as PlatformId); + }} + isDisabled={isInstallStarted} + /> + + + {installAgentCommand} + + + {showInstallProgressSteps && ( + <> + + + {( + [ + 'ea-download', + 'ea-extract', + 'ea-install', + 'ea-status', + ] as const + ).map((stepId) => { + const { title, status, message } = getStep( + stepId, + installProgressSteps + ); + return ( + + ); + })} + + + )} + + ), + }, + { + title: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.configureStep.title', + { defaultMessage: 'Configure the Elastic agent' } + ), + status: configureAgentStatus, + children: ( + <> + +

+ {autoDownloadConfig + ? i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.configStep.auto.description', + { + defaultMessage: + 'The agent config below will be downloaded by the install script and written to ({configPath}). This will overwrite any existing agent configuration.', + values: { + configPath: '/opt/Elastic/Agent/elastic-agent.yml', + }, + } + ) + : i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.configStep.manual.description', + { + defaultMessage: + 'Add the following configuration to {configPath} on the host where you installed the Elastic agent.', + values: { + configPath: '/opt/Elastic/Agent/elastic-agent.yml', + }, + } + )} +

+
+ + + + {configureAgentYaml} + + + + + {i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.configStep.downloadConfigButton', + { defaultMessage: 'Download config file' } + )} + + {showInstallProgressSteps && autoDownloadConfig ? ( + <> + + + + + + ) : null} + + ), + }, + ...appendedSteps.map((euiStep) => ({ children: null, ...euiStep })), + ]} + /> + ); +} + +function getStep( + id: ProgressStepId, + installProgressSteps: Props['installProgressSteps'] +): { title: string; status: EuiStepStatus; message?: string } { + const { loadingTitle, completedTitle, incompleteTitle } = + PROGRESS_STEP_TITLES[id]; + const stepProgress = installProgressSteps[id]; + if (stepProgress) { + const { status, message } = stepProgress; + const title = + status === 'loading' + ? loadingTitle + : status === 'complete' + ? completedTitle + : incompleteTitle; + return { + title, + status: status ?? ('incomplete' as const), + message, + }; + } + + return { + title: incompleteTitle, + status: 'incomplete' as const, + }; +} + +const PROGRESS_STEP_TITLES: Record< + ProgressStepId, + Record<'incompleteTitle' | 'loadingTitle' | 'completedTitle', string> +> = { + 'ea-download': { + incompleteTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaDownload.incompleteTitle', + { defaultMessage: 'Download Elastic Agent' } + ), + loadingTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaDownload.loadingTitle', + { defaultMessage: 'Downloading Elastic Agent' } + ), + completedTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaDownload.completedTitle', + { defaultMessage: 'Elastic Agent downloaded' } + ), + }, + 'ea-extract': { + incompleteTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaExtract.incompleteTitle', + { defaultMessage: 'Extract Elastic Agent' } + ), + loadingTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaExtract.loadingTitle', + { defaultMessage: 'Extracting Elastic Agent' } + ), + completedTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaExtract.completedTitle', + { defaultMessage: 'Elastic Agent extracted' } + ), + }, + 'ea-install': { + incompleteTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaInstall.incompleteTitle', + { defaultMessage: 'Install Elastic Agent' } + ), + loadingTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaInstall.loadingTitle', + { defaultMessage: 'Installing Elastic Agent' } + ), + completedTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaInstall.completedTitle', + { defaultMessage: 'Elastic Agent installed' } + ), + }, + 'ea-status': { + incompleteTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaStatus.incompleteTitle', + { defaultMessage: 'Connect to the Elastic Agent' } + ), + loadingTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaStatus.loadingTitle', + { + defaultMessage: 'Connecting to the Elastic Agent', + } + ), + completedTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaStatus.completedTitle', + { + defaultMessage: 'Connected to the Elastic Agent', + } + ), + }, + 'ea-config': { + incompleteTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaConfig.incompleteTitle', + { defaultMessage: 'Configure the agent' } + ), + loadingTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaConfig.loadingTitle', + { defaultMessage: 'Downloading Elastic Agent config' } + ), + completedTitle: i18n.translate( + 'xpack.observability_onboarding.installElasticAgent.progress.eaConfig.completedTitle', + { + defaultMessage: 'Elastic Agent config written to {configPath}', + values: { configPath: '/opt/Elastic/Agent/elastic-agent.yml' }, + } + ), + }, +}; diff --git a/x-pack/plugins/observability_onboarding/public/components/app/custom_logs/wizard/step_status.tsx b/x-pack/plugins/observability_onboarding/public/components/shared/step_status.tsx similarity index 100% rename from x-pack/plugins/observability_onboarding/public/components/app/custom_logs/wizard/step_status.tsx rename to x-pack/plugins/observability_onboarding/public/components/shared/step_status.tsx diff --git a/x-pack/plugins/security_solution/public/common/mock/test_providers.tsx b/x-pack/plugins/security_solution/public/common/mock/test_providers.tsx index 9672f2563dc5a..6b662ea9e3cb8 100644 --- a/x-pack/plugins/security_solution/public/common/mock/test_providers.tsx +++ b/x-pack/plugins/security_solution/public/common/mock/test_providers.tsx @@ -61,7 +61,13 @@ export const TestProvidersComponent: React.FC = ({ onDragEnd = jest.fn(), cellActions = [], }) => { - const queryClient = new QueryClient(); + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }); return ( diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts index e43581e5739f4..aad6cf8a04917 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.test.ts @@ -445,7 +445,7 @@ describe('Detections Rules API', () => { slice: jest.fn(), stream: jest.fn(), text: jest.fn(), - } as File; + } as unknown as File; const formData = new FormData(); formData.append('file', fileToImport); @@ -527,7 +527,7 @@ describe('Detections Rules API', () => { slice: jest.fn(), stream: jest.fn(), text: jest.fn(), - } as Blob; + } as unknown as Blob; beforeEach(() => { fetchMock.mockClear(); diff --git a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_data.ts b/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_data.ts index 1485e9434e8bf..8a35bf420a5ba 100644 --- a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_data.ts +++ b/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_data.ts @@ -29,6 +29,7 @@ export const useResponderActionData = ({ tooltip: ReactNode; } => { const showEndpointResponseActionsConsole = useWithShowEndpointResponder(); + const { data: endpointHostInfo, isFetching, @@ -36,15 +37,16 @@ export const useResponderActionData = ({ } = useGetEndpointDetails(endpointId, { enabled: Boolean(endpointId) }); const [isDisabled, tooltip]: [disabled: boolean, tooltip: ReactNode] = useMemo(() => { - if (!endpointId) { - return [true, NOT_FROM_ENDPOINT_HOST_TOOLTIP]; - } - // Still loading Endpoint host info if (isFetching) { return [true, LOADING_ENDPOINT_DATA_TOOLTIP]; } + // if we got an error, and it's a 404 it means the endpoint is not from the endpoint host + if (error && error.body?.statusCode === 404) { + return [true, NOT_FROM_ENDPOINT_HOST_TOOLTIP]; + } + // if we got an error and it's a 400 with unenrolled in the error message (alerts can exist for endpoint that are no longer around) // or, // the Host status is `unenrolled` @@ -61,7 +63,7 @@ export const useResponderActionData = ({ } return [false, undefined]; - }, [endpointHostInfo, endpointId, error, isFetching]); + }, [endpointHostInfo, error, isFetching]); const handleResponseActionsClick = useCallback(() => { if (endpointHostInfo) showEndpointResponseActionsConsole(endpointHostInfo.metadata); diff --git a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_item.tsx b/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_item.tsx index 21a4bebcf4a37..737a862b12809 100644 --- a/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_item.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/endpoint_responder/use_responder_action_item.tsx @@ -9,10 +9,7 @@ import React, { useMemo } from 'react'; import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; import { FormattedMessage } from '@kbn/i18n-react'; import { useUserPrivileges } from '../../../common/components/user_privileges'; -import { - isAlertFromEndpointEvent, - isTimelineEventItemAnAlert, -} from '../../../common/utils/endpoint_alert_check'; +import { isTimelineEventItemAnAlert } from '../../../common/utils/endpoint_alert_check'; import { getFieldValue } from '../host_isolation/helpers'; import type { AlertTableContextMenuItem } from '../alerts_table/types'; import { useResponderActionData } from './use_responder_action_data'; @@ -28,17 +25,13 @@ export const useResponderActionItem = ( return isTimelineEventItemAnAlert(eventDetailsData || []); }, [eventDetailsData]); - const isEndpointAlert = useMemo(() => { - return isAlertFromEndpointEvent({ data: eventDetailsData || [] }); - }, [eventDetailsData]); - const endpointId = useMemo( () => getFieldValue({ category: 'agent', field: 'agent.id' }, eventDetailsData), [eventDetailsData] ); const { handleResponseActionsClick, isDisabled, tooltip } = useResponderActionData({ - endpointId: isEndpointAlert ? endpointId : '', + endpointId, onClick, }); diff --git a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx index b841ae0723eae..d342092dd3d9d 100644 --- a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx @@ -23,8 +23,9 @@ import { mockCasesContract } from '@kbn/cases-plugin/public/mocks'; import { initialUserPrivilegesState as mockInitialUserPrivilegesState } from '../../../common/components/user_privileges/user_privileges_context'; import { useUserPrivileges } from '../../../common/components/user_privileges'; import { - NOT_FROM_ENDPOINT_HOST_TOOLTIP, HOST_ENDPOINT_UNENROLLED_TOOLTIP, + LOADING_ENDPOINT_DATA_TOOLTIP, + NOT_FROM_ENDPOINT_HOST_TOOLTIP, } from '../endpoint_responder/translations'; import { endpointMetadataHttpMocks } from '../../../management/pages/endpoint_hosts/mocks'; import type { HttpSetup } from '@kbn/core/public'; @@ -477,17 +478,45 @@ describe('take action dropdown', () => { expect(findLaunchResponderButton()).toHaveLength(0); }); - it('should disable the button if alert NOT from a host running endpoint', async () => { + it('should enable button for non endpoint event type when defend integration present', async () => { setTypeOnEcsDataWithAgentType('filebeat'); if (defaultProps.detailsData) { defaultProps.detailsData = generateAlertDetailsDataMock() as TimelineEventsDetailsItem[]; } render(); - const consoleButton = findLaunchResponderButton().first(); + expect(findLaunchResponderButton().first().prop('disabled')).toBe(true); + expect(findLaunchResponderButton().first().prop('toolTipContent')).toEqual( + LOADING_ENDPOINT_DATA_TOOLTIP + ); + + await waitFor(() => { + expect(apiMocks.responseProvider.metadataDetails).toHaveBeenCalled(); + wrapper.update(); + + expect(findLaunchResponderButton().first().prop('disabled')).toBe(false); + expect(findLaunchResponderButton().first().prop('toolTipContent')).toEqual(undefined); + }); + }); + + it('should disable the button for non endpoint event type when defend integration not present', async () => { + setAlertDetailsDataMockToEndpointAgent(); + apiMocks.responseProvider.metadataDetails.mockImplementation(() => { + const error: Error & { body?: { statusCode: number } } = new Error(); + error.body = { statusCode: 404 }; + throw error; + }); + render(); + + await waitFor(() => { + expect(apiMocks.responseProvider.metadataDetails).toThrow(); + wrapper.update(); - expect(consoleButton.prop('disabled')).toBe(true); - expect(consoleButton.prop('toolTipContent')).toEqual(NOT_FROM_ENDPOINT_HOST_TOOLTIP); + expect(findLaunchResponderButton().first().prop('disabled')).toBe(true); + expect(findLaunchResponderButton().first().prop('toolTipContent')).toEqual( + NOT_FROM_ENDPOINT_HOST_TOOLTIP + ); + }); }); it('should disable the button if host status is unenrolled', async () => { diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts index fca93d1848f4a..ea788063b572c 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_services.ts @@ -279,7 +279,8 @@ export const getAgentDownloadUrl = async ( ): Promise => { const agentVersion = closestMatch ? await getLatestAgentDownloadVersion(version, log) : version; const downloadArch = - { arm64: 'arm64', x64: 'x86_64' }[process.arch] ?? `UNSUPPORTED_ARCHITECTURE_${process.arch}`; + { arm64: 'arm64', x64: 'x86_64' }[process.arch as string] ?? + `UNSUPPORTED_ARCHITECTURE_${process.arch}`; const agentFile = `elastic-agent-${agentVersion}-linux-${downloadArch}.tar.gz`; const artifactSearchUrl = `https://artifacts-api.elastic.co/v1/search/${agentVersion}/${agentFile}`; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.test.ts index 4ab03837f416b..199681a13e968 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/email/send_email_graph_api.test.ts @@ -90,6 +90,7 @@ describe('sendEmailGraphApi', () => { "maxSockets": Infinity, "maxTotalSockets": Infinity, "options": Object { + "noDelay": true, "path": null, "rejectUnauthorized": true, }, @@ -180,6 +181,7 @@ describe('sendEmailGraphApi', () => { "maxSockets": Infinity, "maxTotalSockets": Infinity, "options": Object { + "noDelay": true, "path": null, "rejectUnauthorized": true, }, @@ -269,6 +271,7 @@ describe('sendEmailGraphApi', () => { "maxSockets": Infinity, "maxTotalSockets": Infinity, "options": Object { + "noDelay": true, "path": null, "rejectUnauthorized": true, }, diff --git a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/synthetics_private_locations.ts b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/synthetics_private_locations.ts index caa3ac686fd61..c0366d8e3935f 100644 --- a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/synthetics_private_locations.ts +++ b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/synthetics_private_locations.ts @@ -18,11 +18,9 @@ export const PrivateLocationCodec = t.intersection([ isServiceManaged: t.boolean, isInvalid: t.boolean, tags: t.array(t.string), - /* Empty Lat lon was accidentally saved as an empty string instead of undefined or null - * Need a migration to fix */ geo: t.interface({ - lat: t.union([t.string, t.number, t.null]), - lon: t.union([t.string, t.number, t.null]), + lat: t.number, + lon: t.number, }), }), ]); diff --git a/x-pack/plugins/synthetics/server/routes/settings/private_locations/helpers.test.ts b/x-pack/plugins/synthetics/server/routes/settings/private_locations/helpers.test.ts index 584cc2a334697..fe08ed89cadac 100644 --- a/x-pack/plugins/synthetics/server/routes/settings/private_locations/helpers.test.ts +++ b/x-pack/plugins/synthetics/server/routes/settings/private_locations/helpers.test.ts @@ -48,7 +48,7 @@ const testLocations2 = { label: 'BEEP', agentPolicyId: 'e3134290-0f73-11ee-ba15-159f4f728dec', id: 'e3134290-0f73-11ee-ba15-159f4f728dec', - geo: { lat: '-10', lon: '20' }, + geo: { lat: -10, lon: 20 }, concurrentMonitors: 1, isInvalid: true, isServiceManaged: true, @@ -113,8 +113,8 @@ describe('toClientContract', () => { agentPolicyId: 'e3134290-0f73-11ee-ba15-159f4f728dec', concurrentMonitors: 1, geo: { - lat: '-10', - lon: '20', + lat: -10, + lon: 20, }, id: 'e3134290-0f73-11ee-ba15-159f4f728dec', isInvalid: true, diff --git a/x-pack/plugins/synthetics/server/routes/settings/private_locations/helpers.ts b/x-pack/plugins/synthetics/server/routes/settings/private_locations/helpers.ts index 42fd6e42c4277..7f64b1bed7425 100644 --- a/x-pack/plugins/synthetics/server/routes/settings/private_locations/helpers.ts +++ b/x-pack/plugins/synthetics/server/routes/settings/private_locations/helpers.ts @@ -25,10 +25,7 @@ export const toClientContract = ( isServiceManaged: false, isInvalid: !Boolean(agentPolicies?.find((policy) => policy.id === location.agentPolicyId)), tags: location.tags, - geo: { - lat: location.geo?.lat ?? null, - lon: location.geo?.lon ?? null, - }, + geo: location.geo, })), }; }; @@ -41,9 +38,6 @@ export const toSavedObjectContract = (location: PrivateLocation): PrivateLocatio concurrentMonitors: location.concurrentMonitors, tags: location.tags, isServiceManaged: false, - geo: { - lat: location.geo?.lat ?? null, - lon: location.geo?.lon ?? null, - }, + geo: location.geo, }; }; diff --git a/x-pack/plugins/synthetics/server/runtime_types/private_locations.ts b/x-pack/plugins/synthetics/server/runtime_types/private_locations.ts index 5b87332c19279..d8b4e41ede17a 100644 --- a/x-pack/plugins/synthetics/server/runtime_types/private_locations.ts +++ b/x-pack/plugins/synthetics/server/runtime_types/private_locations.ts @@ -18,8 +18,8 @@ export const PrivateLocationAttributesCodec = t.intersection([ t.partial({ tags: t.array(t.string), geo: t.interface({ - lat: t.union([t.null, t.number, t.string]), - lon: t.union([t.null, t.number, t.string]), + lat: t.number, + lon: t.number, }), }), ]); diff --git a/x-pack/plugins/synthetics/server/saved_objects/migrations/private_locations/model_version_1.test.ts b/x-pack/plugins/synthetics/server/saved_objects/migrations/private_locations/model_version_1.test.ts new file mode 100644 index 0000000000000..63a9f940143a4 --- /dev/null +++ b/x-pack/plugins/synthetics/server/saved_objects/migrations/private_locations/model_version_1.test.ts @@ -0,0 +1,180 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { transformGeoProperty } from './model_version_1'; +import { privateLocationsSavedObjectName } from '../../../../common/saved_objects/private_locations'; + +describe('model version 1 migration', () => { + const testLocation = { + label: 'us-east-1', + id: 'us-east-1', + geo: { + lat: '40.7128', + lon: '-74.0060', + }, + agentPolicyId: 'agentPolicyId', + concurrentMonitors: 1, + }; + const testObject = { + type: privateLocationsSavedObjectName, + id: 'synthetics-privates-locations-singleton', + attributes: { + locations: [testLocation], + }, + }; + it('should return expected result', function () { + const result = transformGeoProperty(testObject, {} as any); + expect(result.document).toEqual({ + attributes: { + locations: [ + { + agentPolicyId: 'agentPolicyId', + concurrentMonitors: 1, + geo: { + lat: 40.7128, + lon: -74.006, + }, + id: 'us-east-1', + isServiceManaged: false, + label: 'us-east-1', + }, + ], + }, + id: 'synthetics-privates-locations-singleton', + type: 'synthetics-privates-locations', + }); + }); + + it('should return expected result for zero values', function () { + testLocation.geo.lat = '0'; + testLocation.geo.lon = '0'; + const result = transformGeoProperty(testObject, {} as any); + expect(result.document).toEqual({ + attributes: { + locations: [ + { + agentPolicyId: 'agentPolicyId', + concurrentMonitors: 1, + geo: { + lat: 0, + lon: 0, + }, + id: 'us-east-1', + isServiceManaged: false, + label: 'us-east-1', + }, + ], + }, + id: 'synthetics-privates-locations-singleton', + type: 'synthetics-privates-locations', + }); + }); + + it('should return expected result for zero integers', function () { + // @ts-ignore + testLocation.geo.lat = 0; + // @ts-ignore + testLocation.geo.lon = 0; + const result = transformGeoProperty(testObject, {} as any); + expect(result.document).toEqual({ + attributes: { + locations: [ + { + agentPolicyId: 'agentPolicyId', + concurrentMonitors: 1, + geo: { + lat: 0, + lon: 0, + }, + id: 'us-east-1', + isServiceManaged: false, + label: 'us-east-1', + }, + ], + }, + id: 'synthetics-privates-locations-singleton', + type: 'synthetics-privates-locations', + }); + }); + + it('should return expected result for empty values', function () { + // @ts-ignore + testLocation.geo.lat = ''; + // @ts-ignore + testLocation.geo.lon = ''; + const result = transformGeoProperty(testObject, {} as any); + expect(result.document).toEqual({ + attributes: { + locations: [ + { + agentPolicyId: 'agentPolicyId', + concurrentMonitors: 1, + geo: { + lat: 0, + lon: 0, + }, + id: 'us-east-1', + isServiceManaged: false, + label: 'us-east-1', + }, + ], + }, + id: 'synthetics-privates-locations-singleton', + type: 'synthetics-privates-locations', + }); + }); + it('should return expected result for null values', function () { + // @ts-ignore + testLocation.geo.lat = null; + // @ts-ignore + testLocation.geo.lon = null; + const result = transformGeoProperty(testObject, {} as any); + expect(result.document).toEqual({ + attributes: { + locations: [ + { + agentPolicyId: 'agentPolicyId', + concurrentMonitors: 1, + geo: { + lat: 0, + lon: 0, + }, + id: 'us-east-1', + isServiceManaged: false, + label: 'us-east-1', + }, + ], + }, + id: 'synthetics-privates-locations-singleton', + type: 'synthetics-privates-locations', + }); + }); + + it('should return expected result for undefined values', function () { + // @ts-ignore + testLocation.geo = undefined; + const result = transformGeoProperty(testObject, {} as any); + expect(result.document).toEqual({ + attributes: { + locations: [ + { + agentPolicyId: 'agentPolicyId', + concurrentMonitors: 1, + geo: { + lat: 0, + lon: 0, + }, + id: 'us-east-1', + isServiceManaged: false, + label: 'us-east-1', + }, + ], + }, + id: 'synthetics-privates-locations-singleton', + type: 'synthetics-privates-locations', + }); + }); +}); diff --git a/x-pack/plugins/synthetics/server/legacy_uptime/lib/saved_objects/migrations/private_locations/8.10.0.ts b/x-pack/plugins/synthetics/server/saved_objects/migrations/private_locations/model_version_1.ts similarity index 61% rename from x-pack/plugins/synthetics/server/legacy_uptime/lib/saved_objects/migrations/private_locations/8.10.0.ts rename to x-pack/plugins/synthetics/server/saved_objects/migrations/private_locations/model_version_1.ts index 6108abdc638a1..2b7d5be016bf0 100644 --- a/x-pack/plugins/synthetics/server/legacy_uptime/lib/saved_objects/migrations/private_locations/8.10.0.ts +++ b/x-pack/plugins/synthetics/server/saved_objects/migrations/private_locations/model_version_1.ts @@ -5,8 +5,11 @@ * 2.0. */ import * as t from 'io-ts'; -import type { SavedObjectMigrationFn } from '@kbn/core/server'; -import type { SyntheticsPrivateLocationsAttributes } from '../../../../../runtime_types/private_locations'; +import { + SavedObjectModelTransformationFn, + SavedObjectsModelVersion, +} from '@kbn/core-saved-objects-server'; +import { SyntheticsPrivateLocationsAttributes } from '../../../runtime_types/private_locations'; export const PrivateLocationAttributesCodecLegacy = t.intersection([ t.interface({ @@ -29,22 +32,33 @@ export type SyntheticsPrivateLocationsAttributesLegacy = t.TypeOf< typeof SyntheticsPrivateLocationsAttributesCodecLegacy >; -export const migration8100: SavedObjectMigrationFn< +export const transformGeoProperty: SavedObjectModelTransformationFn< SyntheticsPrivateLocationsAttributesLegacy, SyntheticsPrivateLocationsAttributes > = (privateLocationDoc) => { const { locations } = privateLocationDoc.attributes; return { - ...privateLocationDoc, - attributes: { - locations: locations.map((location) => ({ - ...location, - geo: { - lat: location.geo?.lat ? Number(location.geo?.lat) : null, - lon: location.geo?.lon ? Number(location.geo.lon) : null, - }, - isServiceManaged: false, - })), + document: { + ...privateLocationDoc, + attributes: { + locations: locations.map((location) => ({ + ...location, + geo: { + lat: Number(location.geo?.lat ?? 0), + lon: Number(location.geo?.lon ?? 0), + }, + isServiceManaged: false, + })), + }, }, }; }; + +export const modelVersion1: SavedObjectsModelVersion = { + changes: [ + { + type: 'unsafe_transform', + transformFn: transformGeoProperty, + }, + ], +}; diff --git a/x-pack/plugins/synthetics/server/saved_objects/private_locations.ts b/x-pack/plugins/synthetics/server/saved_objects/private_locations.ts index 0585b3a786ef7..ee7426ead23af 100644 --- a/x-pack/plugins/synthetics/server/saved_objects/private_locations.ts +++ b/x-pack/plugins/synthetics/server/saved_objects/private_locations.ts @@ -6,6 +6,7 @@ */ import { SavedObjectsType } from '@kbn/core/server'; +import { modelVersion1 } from './migrations/private_locations/model_version_1'; import { privateLocationsSavedObjectName } from '../../common/saved_objects/private_locations'; export const privateLocationsSavedObjectId = 'synthetics-privates-locations-singleton'; @@ -25,4 +26,7 @@ export const PRIVATE_LOCATIONS_SAVED_OBJECT_TYPE: SavedObjectsType = { management: { importableAndExportable: true, }, + modelVersions: { + 1: modelVersion1, + }, }; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts index bd094c10e9ef8..3c2a019625136 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/service_api_client.test.ts @@ -231,7 +231,7 @@ describe('callAPI', () => { 'x-kibana-version': '8.7.0', }, httpsAgent: expect.objectContaining({ - options: { rejectUnauthorized: true, path: null }, + options: { rejectUnauthorized: true, path: null, noDelay: true }, }), method: 'POST', url: 'https://service.dev/monitors', @@ -251,7 +251,7 @@ describe('callAPI', () => { 'x-kibana-version': '8.7.0', }, httpsAgent: expect.objectContaining({ - options: { rejectUnauthorized: true, path: null }, + options: { rejectUnauthorized: true, path: null, noDelay: true }, }), method: 'POST', url: 'https://qa.service.elstc.co/monitors', @@ -271,7 +271,7 @@ describe('callAPI', () => { 'x-kibana-version': '8.7.0', }, httpsAgent: expect.objectContaining({ - options: { rejectUnauthorized: true, path: null }, + options: { rejectUnauthorized: true, path: null, noDelay: true }, }), method: 'POST', url: 'https://qa.service.stg.co/monitors', @@ -347,6 +347,7 @@ describe('callAPI', () => { options: { rejectUnauthorized: true, path: null, + noDelay: true, cert: 'test-certificate', key: 'test-key', }, @@ -400,6 +401,7 @@ describe('callAPI', () => { options: { rejectUnauthorized: true, path: null, + noDelay: true, cert: 'test-certificate', key: 'test-key', }, @@ -459,6 +461,7 @@ describe('callAPI', () => { options: { rejectUnauthorized: true, path: null, + noDelay: true, cert: 'test-certificate', key: 'test-key', }, diff --git a/x-pack/plugins/uptime/public/legacy_uptime/components/overview/monitor_list/monitor_list.test.tsx b/x-pack/plugins/uptime/public/legacy_uptime/components/overview/monitor_list/monitor_list.test.tsx index 38c3c64dc37da..41278c30863fb 100644 --- a/x-pack/plugins/uptime/public/legacy_uptime/components/overview/monitor_list/monitor_list.test.tsx +++ b/x-pack/plugins/uptime/public/legacy_uptime/components/overview/monitor_list/monitor_list.test.tsx @@ -133,7 +133,10 @@ describe('MonitorList component', () => { setItem: jest.fn(), }; - global.localStorage = localStorageMock; + Object.defineProperty(global, 'localStorage', { + value: localStorageMock, + writable: true, + }); }); it('renders a no items message when no data is provided', async () => { diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/nodes.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/nodes.js index d0603999c1b71..7514d079e5b41 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/nodes.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/nodes.js @@ -17,8 +17,7 @@ export default function ({ getService }) { const { getNodesStats } = initElasticsearchHelpers(getService); const { loadNodes, getNodeDetails } = registerHelpers({ supertest }); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/141134 - describe.skip('nodes', function () { + describe('nodes', function () { // Cloud disallows setting custom node attributes, so we can't use `NODE_CUSTOM_ATTRIBUTE` // to retrieve the IDs we expect. this.tags(['skipCloud']); diff --git a/x-pack/test/apm_api_integration/tests/storage_explorer/get_services.spec.ts b/x-pack/test/apm_api_integration/tests/storage_explorer/get_services.spec.ts index de421ed149827..4a1f59925a018 100644 --- a/x-pack/test/apm_api_integration/tests/storage_explorer/get_services.spec.ts +++ b/x-pack/test/apm_api_integration/tests/storage_explorer/get_services.spec.ts @@ -37,6 +37,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { environment, kuery, indexLifecyclePhase, + start, + end, }, }, }); diff --git a/yarn.lock b/yarn.lock index 80a5baaef5903..3dfd4bedfdf25 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2396,6 +2396,18 @@ resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" integrity sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw== +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b" @@ -6218,6 +6230,13 @@ "@gar/promisify" "^1.1.3" semver "^7.3.5" +"@npmcli/fs@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-3.1.0.tgz#233d43a25a91d68c3a863ba0da6a3f00924a173e" + integrity sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w== + dependencies: + semver "^7.3.5" + "@npmcli/move-file@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.0.1.tgz#de103070dac0f48ce49cf6693c23af59c0f70464" @@ -6635,6 +6654,11 @@ node-addon-api "^3.2.1" node-gyp-build "^4.3.0" +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@pmmmwh/react-refresh-webpack-plugin@^0.5.3": version "0.5.7" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.7.tgz#58f8217ba70069cc6a73f5d7e05e85b458c150e2" @@ -8994,7 +9018,15 @@ dependencies: "@types/node" "*" -"@types/node-fetch@^2.5.7", "@types/node-fetch@^2.6.0": +"@types/node-fetch@2.6.4": + version "2.6.4" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" + integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node-fetch@^2.5.7": version "2.6.2" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== @@ -9016,10 +9048,10 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@16.11.68", "@types/node@>= 8", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=8.9.0", "@types/node@^10.1.0", "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0", "@types/node@^14.14.31": - version "16.11.68" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.68.tgz#30ee923f4d940793e0380f5ce61c0bd4b7196b6c" - integrity sha512-JkRpuVz3xCNCWaeQ5EHLR/6woMbHZz/jZ7Kmc63AkU+1HxnoUugzSWMck7dsR4DvNYX8jp9wTi9K7WvnxOIQZQ== +"@types/node@*", "@types/node@18.17.1", "@types/node@>= 8", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=8.9.0", "@types/node@^10.1.0", "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0", "@types/node@^14.14.31": + version "18.17.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.17.1.tgz#84c32903bf3a09f7878c391d31ff08f6fe7d8335" + integrity sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw== "@types/nodemailer@^6.4.0": version "6.4.0" @@ -10200,18 +10232,11 @@ abab@^2.0.4, abab@^2.0.6: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== -abbrev@1: +abbrev@1, abbrev@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -10482,6 +10507,11 @@ ansi-regex@^5.0.0, ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^2.0.1, ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -10506,6 +10536,11 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + ansi-to-html@^0.6.11: version "0.6.13" resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.13.tgz#c72eae8b63e5ca0643aab11bfc6e6f2217425833" @@ -11918,6 +11953,24 @@ cacache@^16.1.0: tar "^6.1.11" unique-filename "^2.0.0" +cacache@^17.0.0: + version "17.1.3" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-17.1.3.tgz#c6ac23bec56516a7c0c52020fd48b4909d7c7044" + integrity sha512-jAdjGxmPxZh0IipMdR7fK/4sDSrHMLUV0+GvVUsjwyGNKHsh79kW/otg+GkbXwl6Uzvy9wsvHOX4nUoWldeZMg== + dependencies: + "@npmcli/fs" "^3.1.0" + fs-minipass "^3.0.0" + glob "^10.2.2" + lru-cache "^7.7.1" + minipass "^5.0.0" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + p-map "^4.0.0" + ssri "^10.0.0" + tar "^6.1.11" + unique-filename "^3.0.0" + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -14527,6 +14580,11 @@ earcut@^2.2.4: resolved "https://registry.yarnpkg.com/earcut/-/earcut-2.2.4.tgz#6d02fd4d68160c114825d06890a92ecaae60343a" integrity sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ== +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -14733,7 +14791,7 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emoji-regex@^9.0.0: +emoji-regex@^9.0.0, emoji-regex@^9.2.2: version "9.2.2" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== @@ -15612,11 +15670,6 @@ event-emitter@^0.3.5, event-emitter@~0.3.5: d "1" es5-ext "~0.10.14" -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - eventemitter-asyncresource@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz#734ff2e44bf448e627f7748f905d6bdd57bdb65b" @@ -15785,6 +15838,11 @@ expiry-js@0.1.7: resolved "https://registry.yarnpkg.com/expiry-js/-/expiry-js-0.1.7.tgz#76be8c05e572bf936df40c1766448d0b3b2f555f" integrity sha1-dr6MBeVyv5Nt9AwXZkSNCzsvVV8= +exponential-backoff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" + integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== + expose-loader@^0.7.5: version "0.7.5" resolved "https://registry.yarnpkg.com/expose-loader/-/expose-loader-0.7.5.tgz#e29ea2d9aeeed3254a3faa1b35f502db9f9c3f6f" @@ -16361,6 +16419,14 @@ foreground-child@^2.0.0: cross-spawn "^7.0.0" signal-exit "^3.0.2" +foreground-child@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -16560,6 +16626,13 @@ fs-minipass@^2.0.0, fs-minipass@^2.1.0: dependencies: minipass "^3.0.0" +fs-minipass@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.2.tgz#5b383858efa8c1eb8c33b39e994f7e8555b8b3a3" + integrity sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g== + dependencies: + minipass "^5.0.0" + fs-mkdirp-stream@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz#1e82575c4023929ad35cf69269f84f1a8c973aa7" @@ -16899,6 +16972,17 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^10.2.2: + version "10.2.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.2.7.tgz#9dd2828cd5bc7bd861e7738d91e7113dda41d7d8" + integrity sha512-jTKehsravOJo8IJxUGfZILnkvVJM/MOfHRs8QcXolVef2zNI9Tqyy5+SeuOAZd3upViEZQLyFpQhYiHLrMUNmA== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.0.3" + minimatch "^9.0.1" + minipass "^5.0.0 || ^6.0.2" + path-scurry "^1.7.0" + glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0, glob@~7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -17688,7 +17772,7 @@ htmlparser2@^8.0.1: domutils "^3.0.1" entities "^4.4.0" -http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0: +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -18061,7 +18145,7 @@ inquirer@^8.2.3: through "^2.3.6" wrap-ansi "^7.0.0" -install-artifact-from-github@^1.3.0: +install-artifact-from-github@^1.3.1: version "1.3.3" resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.3.3.tgz#57d89bacfa0f47d7307fe41b6247cda9f9a8079c" integrity sha512-x79SL0d8WOi1ZjXSTUqqs0GPQZ92YArJAN9O46wgU9wdH2U9ecyyhB9YGDbPe2OLV4ptmt6AZYRQZ2GydQZosQ== @@ -18907,6 +18991,15 @@ its-name@1.0.0: resolved "https://registry.yarnpkg.com/its-name/-/its-name-1.0.0.tgz#2065f1883ecb568c65f7112ddbf123401fae4af0" integrity sha1-IGXxiD7LVoxl9xEt2/EjQB+uSvA= +jackspeak@^2.0.3: + version "2.2.1" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.2.1.tgz#655e8cf025d872c9c03d3eb63e8f0c024fef16a6" + integrity sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jake@^10.8.5: version "10.8.5" resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46" @@ -20589,6 +20682,11 @@ lru-cache@^7.7.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.14.1.tgz#8da8d2f5f59827edb388e63e459ac23d6d408fea" integrity sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA== +lru-cache@^9.1.1: + version "9.1.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-9.1.2.tgz#255fdbc14b75589d6d0e73644ca167a8db506835" + integrity sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ== + lru-queue@0.1: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" @@ -20665,6 +20763,27 @@ make-fetch-happen@^10.0.4: socks-proxy-agent "^7.0.0" ssri "^9.0.0" +make-fetch-happen@^11.0.3: + version "11.1.1" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz#85ceb98079584a9523d4bf71d32996e7e208549f" + integrity sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w== + dependencies: + agentkeepalive "^4.2.1" + cacache "^17.0.0" + http-cache-semantics "^4.1.1" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + is-lambda "^1.0.1" + lru-cache "^7.7.1" + minipass "^5.0.0" + minipass-fetch "^3.0.0" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.3" + promise-retry "^2.0.1" + socks-proxy-agent "^7.0.0" + ssri "^10.0.0" + make-fetch-happen@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" @@ -21288,6 +21407,13 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.1.tgz#8a555f541cf976c622daf078bb28f29fb927c253" + integrity sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w== + dependencies: + brace-expansion "^2.0.1" + minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -21336,6 +21462,17 @@ minipass-fetch@^2.0.3: optionalDependencies: encoding "^0.1.13" +minipass-fetch@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-3.0.3.tgz#d9df70085609864331b533c960fd4ffaa78d15ce" + integrity sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ== + dependencies: + minipass "^5.0.0" + minipass-sized "^1.0.3" + minizlib "^2.1.2" + optionalDependencies: + encoding "^0.1.13" + minipass-flush@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" @@ -21371,6 +21508,16 @@ minipass@^4.0.0: dependencies: yallist "^4.0.0" +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +"minipass@^5.0.0 || ^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-6.0.2.tgz#542844b6c4ce95b202c0995b0a471f1229de4c81" + integrity sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w== + minizlib@^2.0.0, minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" @@ -21692,7 +21839,7 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.15.0, nan@^2.17.0: +nan@^2.16.0, nan@^2.17.0: version "2.17.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== @@ -21942,6 +22089,23 @@ node-gyp@^8.4.1: tar "^6.1.2" which "^2.0.2" +node-gyp@^9.0.0: + version "9.4.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.4.0.tgz#2a7a91c7cba4eccfd95e949369f27c9ba704f369" + integrity sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg== + dependencies: + env-paths "^2.2.0" + exponential-backoff "^3.1.1" + glob "^7.1.4" + graceful-fs "^4.2.6" + make-fetch-happen "^11.0.3" + nopt "^6.0.0" + npmlog "^6.0.0" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.2" + which "^2.0.2" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -22043,6 +22207,13 @@ nopt@^5.0.0: dependencies: abbrev "1" +nopt@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-6.0.0.tgz#245801d8ebf409c6df22ab9d95b65e1309cdb16d" + integrity sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g== + dependencies: + abbrev "^1.0.0" + normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -22926,6 +23097,14 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-scurry@^1.7.0: + version "1.9.2" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.9.2.tgz#90f9d296ac5e37e608028e28a447b11d385b3f63" + integrity sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg== + dependencies: + lru-cache "^9.1.1" + minipass "^5.0.0 || ^6.0.2" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -24192,14 +24371,14 @@ re-resizable@^6.9.9: resolved "https://registry.yarnpkg.com/re-resizable/-/re-resizable-6.9.9.tgz#99e8b31c67a62115dc9c5394b7e55892265be216" integrity sha512-l+MBlKZffv/SicxDySKEEh42hR6m5bAHfNu3Tvxks2c4Ah+ldnWjfnVRwxo/nxF27SsUsxDS0raAzFuJNKABXA== -re2@1.17.4: - version "1.17.4" - resolved "https://registry.yarnpkg.com/re2/-/re2-1.17.4.tgz#7bf29290bdde963014e77bd2c2e799a6d788386e" - integrity sha512-xyZ4h5PqE8I9tAxTh3G0UttcK5ufrcUxReFjGzfX61vtanNbS1XZHjnwRSyPcLgChI4KLxVgOT/ioZXnUAdoTA== +re2@1.17.7: + version "1.17.7" + resolved "https://registry.yarnpkg.com/re2/-/re2-1.17.7.tgz#e14cab85a177a5534c7215c322d1b043c55aa1e9" + integrity sha512-X8GSuiBoVWwcjuppqSjsIkRxNUKDdjhkO9SBekQbZ2ksqWUReCy7DQPWOVpoTnpdtdz5PIpTTxTFzvJv5UMfjA== dependencies: - install-artifact-from-github "^1.3.0" - nan "^2.15.0" - node-gyp "^8.4.1" + install-artifact-from-github "^1.3.1" + nan "^2.16.0" + node-gyp "^9.0.0" react-ace@^7.0.5: version "7.0.5" @@ -26110,6 +26289,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.0.2.tgz#ff55bb1d9ff2114c13b400688fa544ac63c36967" + integrity sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q== + simple-bin-help@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/simple-bin-help/-/simple-bin-help-1.8.0.tgz#21bb82c6bccd9fa8678f9c0fadf2956b54e2160a" @@ -26616,6 +26800,13 @@ sshpk@^1.14.1: safer-buffer "^2.0.2" tweetnacl "~0.14.0" +ssri@^10.0.0: + version "10.0.4" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.4.tgz#5a20af378be586df139ddb2dfb3bf992cf0daba6" + integrity sha512-12+IR2CB2C28MMAw0Ncqwj5QbTcs0nGIhgJzYWzDkb21vWmfNI83KS4f3Ci6GI98WreIfG7o9UXp3C0qbpA8nQ== + dependencies: + minipass "^5.0.0" + ssri@^6.0.1: version "6.0.2" resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" @@ -26848,6 +27039,15 @@ string-similarity@^4.0.1: resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.3.tgz#ef52d6fc59c8a0fc93b6307fbbc08cc6e18cde21" integrity sha512-QEwJzNFCqq+5AGImk5z4vbsEPTN/+gtyKfXBVLBcbPBRPNganZGfQnIuf9yJ+GiwSnD65sT8xrw/uwU1Q1WmfQ== +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -26857,15 +27057,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -26874,6 +27065,15 @@ string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + "string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.5.tgz#59370644e1db7e4c0c045277690cf7b01203c4da" @@ -26954,6 +27154,13 @@ stringify-entities@^3.0.0, stringify-entities@^3.0.1: is-decimal "^1.0.2" is-hexadecimal "^1.0.0" +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -26975,12 +27182,12 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== dependencies: - ansi-regex "^5.0.1" + ansi-regex "^6.0.1" strip-bom-string@1.X: version "1.0.0" @@ -28227,6 +28434,13 @@ unique-filename@^2.0.0: dependencies: unique-slug "^3.0.0" +unique-filename@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-3.0.0.tgz#48ba7a5a16849f5080d26c760c86cf5cf05770ea" + integrity sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g== + dependencies: + unique-slug "^4.0.0" + unique-slug@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" @@ -28241,6 +28455,13 @@ unique-slug@^3.0.0: dependencies: imurmurhash "^0.1.4" +unique-slug@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-4.0.0.tgz#6bae6bb16be91351badd24cdce741f892a6532e3" + integrity sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ== + dependencies: + imurmurhash "^0.1.4" + unique-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" @@ -29679,6 +29900,15 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" @@ -29704,14 +29934,14 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" wrappy@1: version "1.0.2"