diff --git a/package.json b/package.json index 1354a73ce1ac..6b8c7a6a4fd5 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,6 @@ }, "dependencies": { "@elastic/datemath": "5.0.3", - "@elastic/elasticsearch": "7.10.0-rc.1", "@elastic/eui": "29.3.2", "@elastic/good": "^9.0.1-kibana3", "@elastic/numeral": "^2.5.0", @@ -123,6 +122,7 @@ "@hapi/podium": "^4.1.3", "@hapi/vision": "^6.1.0", "@hapi/wreck": "^17.1.0", + "@opensearch-project/opensearch": "^1.0.2", "@osd/ace": "1.0.0", "@osd/analytics": "1.0.0", "@osd/apm-config-loader": "1.0.0", diff --git a/packages/osd-opensearch/package.json b/packages/osd-opensearch/package.json index e34ec0d626cd..4e30eb6d4d60 100644 --- a/packages/osd-opensearch/package.json +++ b/packages/osd-opensearch/package.json @@ -12,7 +12,7 @@ "osd:watch": "node scripts/build --watch" }, "dependencies": { - "@elastic/elasticsearch": "7.10.0-rc.1", + "@opensearch-project/opensearch": "^1.0.2", "@osd/dev-utils": "1.0.0", "abort-controller": "^3.0.0", "chalk": "^4.1.0", diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index e8e7a32669a4..883b62de50ff 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -5,7 +5,7 @@ ```ts import { Action } from 'history'; -import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; +import { ApiResponse } from '@opensearch-project/opensearch/lib/Transport'; import Boom from '@hapi/boom'; import { ConfigPath } from '@osd/config'; import { EnvironmentMode } from '@osd/config'; @@ -17,7 +17,7 @@ import { ExclusiveUnion } from '@elastic/eui'; import { History } from 'history'; import { Href } from 'history'; import { IconType } from '@elastic/eui'; -import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import { OpenSearchDashboardsClient } from '@opensearch-project/opensearch/api/opensearch_dashboards'; import { Location } from 'history'; import { LocationDescriptorObject } from 'history'; import { Logger } from '@osd/logging'; @@ -33,9 +33,9 @@ import React from 'react'; import { RecursiveReadonly } from '@osd/utility-types'; import * as Rx from 'rxjs'; import { ShallowPromise } from '@osd/utility-types'; -import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import { TransportRequestOptions } from '@opensearch-project/opensearch/lib/Transport'; +import { TransportRequestParams } from '@opensearch-project/opensearch/lib/Transport'; +import { TransportRequestPromise } from '@opensearch-project/opensearch/lib/Transport'; import { Type } from '@osd/config-schema'; import { TypeOf } from '@osd/config-schema'; import { UnregisterCallback } from 'history'; diff --git a/src/core/server/core_usage_data/core_usage_data_service.test.ts b/src/core/server/core_usage_data/core_usage_data_service.test.ts index ca31105a25a3..c51e3bc9a3ee 100644 --- a/src/core/server/core_usage_data/core_usage_data_service.test.ts +++ b/src/core/server/core_usage_data/core_usage_data_service.test.ts @@ -89,7 +89,6 @@ describe('CoreUsageDataService', () => { 'docs.count': 10, 'docs.deleted': 10, 'store.size': 1000, - 'pri.store.size': 2000, }, ], } as any); @@ -98,7 +97,6 @@ describe('CoreUsageDataService', () => { { name: '.kibana_1', 'docs.count': 20, - 'docs.deleted': 20, 'store.size': 2000, 'pri.store.size': 4000, }, @@ -221,13 +219,13 @@ describe('CoreUsageDataService', () => { "alias": ".kibana_task_manager", "docsCount": 10, "docsDeleted": 10, - "primaryStoreSizeBytes": 2000, + "primaryStoreSizeBytes": 0, "storeSizeBytes": 1000, }, Object { "alias": ".kibana_task_manager", "docsCount": 20, - "docsDeleted": 20, + "docsDeleted": 0, "primaryStoreSizeBytes": 4000, "storeSizeBytes": 2000, }, diff --git a/src/core/server/core_usage_data/core_usage_data_service.ts b/src/core/server/core_usage_data/core_usage_data_service.ts index 1fd2adab0445..22259f4d296b 100644 --- a/src/core/server/core_usage_data/core_usage_data_service.ts +++ b/src/core/server/core_usage_data/core_usage_data_service.ts @@ -122,10 +122,12 @@ export class CoreUsageDataService implements CoreService { }); export const MockOpenSearchClient = jest.fn(); -jest.doMock('@elastic/elasticsearch', () => { - const real = jest.requireActual('@elastic/elasticsearch'); +jest.doMock('@opensearch-project/opensearch', () => { + const real = jest.requireActual('@opensearch-project/opensearch'); return { ...real, Client: MockOpenSearchClient, diff --git a/src/core/server/http/integration_tests/core_services.test.ts b/src/core/server/http/integration_tests/core_services.test.ts index 8d6d92571e9b..5d74a059b824 100644 --- a/src/core/server/http/integration_tests/core_services.test.ts +++ b/src/core/server/http/integration_tests/core_services.test.ts @@ -42,7 +42,7 @@ import { errors as opensearchErrors } from 'elasticsearch'; import { LegacyOpenSearchErrorHelpers } from '../../opensearch/legacy'; import { opensearchClientMock } from '../../opensearch/client/mocks'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { ResponseError } from '@opensearch-project/opensearch/lib/errors'; import * as osdTestServer from '../../../test_helpers/osd_server'; import { InternalOpenSearchServiceStart } from '../../opensearch'; diff --git a/src/core/server/index.ts b/src/core/server/index.ts index e3df86ae78c4..670f58bfc1b7 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -307,8 +307,6 @@ export { SavedObjectsRepository, SavedObjectsDeleteByNamespaceOptions, SavedObjectsIncrementCounterOptions, - SavedObjectsComplexFieldMapping, - SavedObjectsCoreFieldMapping, SavedObjectsFieldMapping, SavedObjectsTypeMappingDefinition, SavedObjectsMappingProperties, diff --git a/src/core/server/opensearch/client/client_config.ts b/src/core/server/opensearch/client/client_config.ts index 4e3331314f6c..f76860714393 100644 --- a/src/core/server/opensearch/client/client_config.ts +++ b/src/core/server/opensearch/client/client_config.ts @@ -33,7 +33,7 @@ import { ConnectionOptions as TlsConnectionOptions } from 'tls'; import { URL } from 'url'; import { Duration } from 'moment'; -import { ClientOptions, NodeOptions } from '@elastic/elasticsearch'; +import { ClientOptions, NodeOptions } from '@opensearch-project/opensearch'; import { OpenSearchConfig } from '../opensearch_config'; import { DEFAULT_HEADERS } from '../default_headers'; diff --git a/src/core/server/opensearch/client/cluster_client.ts b/src/core/server/opensearch/client/cluster_client.ts index 23c820da1989..9dfac6daf44b 100644 --- a/src/core/server/opensearch/client/cluster_client.ts +++ b/src/core/server/opensearch/client/cluster_client.ts @@ -30,7 +30,7 @@ * GitHub history for details. */ -import { Client } from '@elastic/elasticsearch'; +import { Client } from '@opensearch-project/opensearch'; import { Logger } from '../../logging'; import { GetAuthHeaders, Headers, isOpenSearchDashboardsRequest, isRealRequest } from '../../http'; import { ensureRawRequest, filterHeaders } from '../../http/router'; diff --git a/src/core/server/opensearch/client/configure_client.test.mocks.ts b/src/core/server/opensearch/client/configure_client.test.mocks.ts index b5362283fe36..e7876b3b96f9 100644 --- a/src/core/server/opensearch/client/configure_client.test.mocks.ts +++ b/src/core/server/opensearch/client/configure_client.test.mocks.ts @@ -36,8 +36,8 @@ jest.doMock('./client_config', () => ({ })); export const ClientMock = jest.fn(); -jest.doMock('@elastic/elasticsearch', () => { - const actual = jest.requireActual('@elastic/elasticsearch'); +jest.doMock('@opensearch-project/opensearch', () => { + const actual = jest.requireActual('@opensearch-project/opensearch'); return { ...actual, Client: ClientMock, diff --git a/src/core/server/opensearch/client/configure_client.test.ts b/src/core/server/opensearch/client/configure_client.test.ts index e7abd46e2f55..9f3ffb713690 100644 --- a/src/core/server/opensearch/client/configure_client.test.ts +++ b/src/core/server/opensearch/client/configure_client.test.ts @@ -32,8 +32,8 @@ import { Buffer } from 'buffer'; import { Readable } from 'stream'; -import { RequestEvent, errors } from '@elastic/elasticsearch'; -import { TransportRequestParams, RequestBody } from '@elastic/elasticsearch/lib/Transport'; +import { RequestEvent, errors } from '@opensearch-project/opensearch'; +import { TransportRequestParams, RequestBody } from '@opensearch-project/opensearch/lib/Transport'; import { parseClientOptionsMock, ClientMock } from './configure_client.test.mocks'; import { loggingSystemMock } from '../../logging/logging_system.mock'; @@ -131,7 +131,7 @@ describe('configureClient', () => { }); describe('Client logging', () => { - it('logs error when the client emits an @elastic/elasticsearch error', () => { + it('logs error when the client emits an @opensearch-project/opensearch error', () => { const client = configureClient(config, { logger, scoped: false }); const response = createApiResponse({ body: {} }); diff --git a/src/core/server/opensearch/client/configure_client.ts b/src/core/server/opensearch/client/configure_client.ts index 8973fbdf2a9b..792daff56cf5 100644 --- a/src/core/server/opensearch/client/configure_client.ts +++ b/src/core/server/opensearch/client/configure_client.ts @@ -31,8 +31,8 @@ */ import { Buffer } from 'buffer'; import { stringify } from 'querystring'; -import { Client } from '@elastic/elasticsearch'; -import { RequestBody } from '@elastic/elasticsearch/lib/Transport'; +import { Client } from '@opensearch-project/opensearch'; +import { RequestBody } from '@opensearch-project/opensearch/lib/Transport'; import { Logger } from '../../logging'; import { parseClientOptions, OpenSearchClientConfig } from './client_config'; diff --git a/src/core/server/opensearch/client/errors.test.ts b/src/core/server/opensearch/client/errors.test.ts index 1e9d385fddf4..ced4b038c014 100644 --- a/src/core/server/opensearch/client/errors.test.ts +++ b/src/core/server/opensearch/client/errors.test.ts @@ -34,8 +34,8 @@ import { ResponseError, ConnectionError, ConfigurationError, -} from '@elastic/elasticsearch/lib/errors'; -import { ApiResponse } from '@elastic/elasticsearch'; +} from '@opensearch-project/opensearch/lib/errors'; +import { ApiResponse } from '@opensearch-project/opensearch'; import { isResponseError, isUnauthorizedError } from './errors'; const createApiResponseError = ({ diff --git a/src/core/server/opensearch/client/errors.ts b/src/core/server/opensearch/client/errors.ts index 0ff37f405882..2793e66a8641 100644 --- a/src/core/server/opensearch/client/errors.ts +++ b/src/core/server/opensearch/client/errors.ts @@ -30,7 +30,7 @@ * GitHub history for details. */ -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { ResponseError } from '@opensearch-project/opensearch/lib/errors'; export type UnauthorizedError = ResponseError & { statusCode: 401; diff --git a/src/core/server/opensearch/client/mocks.test.ts b/src/core/server/opensearch/client/mocks.test.ts index d36b06bf2408..e07ba3b0580a 100644 --- a/src/core/server/opensearch/client/mocks.test.ts +++ b/src/core/server/opensearch/client/mocks.test.ts @@ -54,7 +54,6 @@ describe('Mocked client', () => { }); it('nested level API methods should be mocked', () => { - expectMocked(client.asyncSearch.get); expectMocked(client.nodes.info); }); diff --git a/src/core/server/opensearch/client/mocks.ts b/src/core/server/opensearch/client/mocks.ts index 622d463cb026..11118d8381af 100644 --- a/src/core/server/opensearch/client/mocks.ts +++ b/src/core/server/opensearch/client/mocks.ts @@ -29,8 +29,8 @@ * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. */ -import { Client, ApiResponse } from '@elastic/elasticsearch'; -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import { Client, ApiResponse } from '@opensearch-project/opensearch'; +import { TransportRequestPromise } from '@opensearch-project/opensearch/lib/Transport'; import { OpenSearchClient } from './types'; import { ICustomClusterClient } from './cluster_client'; @@ -63,7 +63,7 @@ const createInternalClientMock = (): DeeplyMockedKeys => { }; const mockify = (obj: Record, omitted: string[] = []) => { - // the @elastic/elasticsearch::Client uses prototypical inheritance + // the @opensearch-project/opensearch::Client uses prototypical inheritance // so we have to crawl up the prototype chain and get all descriptors // to find everything that we should be mocking const descriptors = getAllPropertyDescriptors(obj); @@ -176,9 +176,11 @@ const createErrorTransportRequestPromise = (err: any): MockedTransportRequestPro return promise as MockedTransportRequestPromise; }; -function createApiResponse(opts: Partial = {}): ApiResponse { +function createApiResponse>( + opts: Partial = {} +): ApiResponse { return { - body: {}, + body: {} as any, statusCode: 200, headers: {}, warnings: [], diff --git a/src/core/server/opensearch/client/retry_call_cluster.test.ts b/src/core/server/opensearch/client/retry_call_cluster.test.ts deleted file mode 100644 index ca3a5db32ccd..000000000000 --- a/src/core/server/opensearch/client/retry_call_cluster.test.ts +++ /dev/null @@ -1,313 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - */ - -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* - * Modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -import { errors } from '@elastic/elasticsearch'; -import { opensearchClientMock } from './mocks'; -import { loggingSystemMock } from '../../logging/logging_system.mock'; -import { retryCallCluster, migrationRetryCallCluster } from './retry_call_cluster'; - -const dummyBody = { foo: 'bar' }; -const createErrorReturn = (err: any) => - opensearchClientMock.createErrorTransportRequestPromise(err); - -describe('retryCallCluster', () => { - let client: ReturnType; - - beforeEach(() => { - client = opensearchClientMock.createOpenSearchClient(); - }); - - it('returns response from OpenSearch API call in case of success', async () => { - const successReturn = opensearchClientMock.createSuccessTransportRequestPromise({ - ...dummyBody, - }); - - client.asyncSearch.get.mockReturnValue(successReturn); - - const result = await retryCallCluster(() => client.asyncSearch.get()); - expect(result.body).toEqual(dummyBody); - }); - - it('retries OpenSearch API calls that rejects with `NoLivingConnectionsError`', async () => { - const successReturn = opensearchClientMock.createSuccessTransportRequestPromise({ - ...dummyBody, - }); - - client.asyncSearch.get - .mockImplementationOnce(() => - createErrorReturn(new errors.NoLivingConnectionsError('no living connections', {} as any)) - ) - .mockImplementationOnce(() => successReturn); - - const result = await retryCallCluster(() => client.asyncSearch.get()); - expect(result.body).toEqual(dummyBody); - }); - - it('rejects when OpenSearch API calls reject with other errors', async () => { - client.ping - .mockImplementationOnce(() => createErrorReturn(new Error('unknown error'))) - .mockImplementationOnce(() => - opensearchClientMock.createSuccessTransportRequestPromise({ ...dummyBody }) - ); - - await expect(retryCallCluster(() => client.ping())).rejects.toMatchInlineSnapshot( - `[Error: unknown error]` - ); - }); - - it('stops retrying when OpenSearch API calls reject with other errors', async () => { - client.ping - .mockImplementationOnce(() => - createErrorReturn(new errors.NoLivingConnectionsError('no living connections', {} as any)) - ) - .mockImplementationOnce(() => - createErrorReturn(new errors.NoLivingConnectionsError('no living connections', {} as any)) - ) - .mockImplementationOnce(() => createErrorReturn(new Error('unknown error'))) - .mockImplementationOnce(() => - opensearchClientMock.createSuccessTransportRequestPromise({ ...dummyBody }) - ); - - await expect(retryCallCluster(() => client.ping())).rejects.toMatchInlineSnapshot( - `[Error: unknown error]` - ); - }); -}); - -describe('migrationRetryCallCluster', () => { - let client: ReturnType; - let logger: ReturnType; - - beforeEach(() => { - client = opensearchClientMock.createOpenSearchClient(); - logger = loggingSystemMock.createLogger(); - }); - - const mockClientPingWithErrorBeforeSuccess = (error: any) => { - client.ping - .mockImplementationOnce(() => createErrorReturn(error)) - .mockImplementationOnce(() => createErrorReturn(error)) - .mockImplementationOnce(() => - opensearchClientMock.createSuccessTransportRequestPromise({ ...dummyBody }) - ); - }; - - it('retries OpenSearch API calls that rejects with `NoLivingConnectionsError`', async () => { - mockClientPingWithErrorBeforeSuccess( - new errors.NoLivingConnectionsError('no living connections', {} as any) - ); - - const result = await migrationRetryCallCluster(() => client.ping(), logger, 1); - expect(result.body).toEqual(dummyBody); - }); - - it('retries OpenSearch API calls that rejects with `ConnectionError`', async () => { - mockClientPingWithErrorBeforeSuccess(new errors.ConnectionError('connection error', {} as any)); - - const result = await migrationRetryCallCluster(() => client.ping(), logger, 1); - expect(result.body).toEqual(dummyBody); - }); - - it('retries OpenSearch API calls that rejects with `TimeoutError`', async () => { - mockClientPingWithErrorBeforeSuccess(new errors.TimeoutError('timeout error', {} as any)); - - const result = await migrationRetryCallCluster(() => client.ping(), logger, 1); - expect(result.body).toEqual(dummyBody); - }); - - it('retries OpenSearch API calls that rejects with 503 `ResponseError`', async () => { - mockClientPingWithErrorBeforeSuccess( - new errors.ResponseError({ - statusCode: 503, - } as any) - ); - - const result = await migrationRetryCallCluster(() => client.ping(), logger, 1); - expect(result.body).toEqual(dummyBody); - }); - - it('retries OpenSearch API calls that rejects 401 `ResponseError`', async () => { - mockClientPingWithErrorBeforeSuccess( - new errors.ResponseError({ - statusCode: 401, - } as any) - ); - - const result = await migrationRetryCallCluster(() => client.ping(), logger, 1); - expect(result.body).toEqual(dummyBody); - }); - - it('retries OpenSearch API calls that rejects with 403 `ResponseError`', async () => { - mockClientPingWithErrorBeforeSuccess( - new errors.ResponseError({ - statusCode: 403, - } as any) - ); - - const result = await migrationRetryCallCluster(() => client.ping(), logger, 1); - expect(result.body).toEqual(dummyBody); - }); - - it('retries OpenSearch API calls that rejects with 408 `ResponseError`', async () => { - mockClientPingWithErrorBeforeSuccess( - new errors.ResponseError({ - statusCode: 408, - } as any) - ); - - const result = await migrationRetryCallCluster(() => client.ping(), logger, 1); - expect(result.body).toEqual(dummyBody); - }); - - it('retries OpenSearch API calls that rejects with 410 `ResponseError`', async () => { - mockClientPingWithErrorBeforeSuccess( - new errors.ResponseError({ - statusCode: 410, - } as any) - ); - - const result = await migrationRetryCallCluster(() => client.ping(), logger, 1); - expect(result.body).toEqual(dummyBody); - }); - - it('retries OpenSearch API calls that rejects with `snapshot_in_progress_exception` `ResponseError`', async () => { - mockClientPingWithErrorBeforeSuccess( - new errors.ResponseError({ - statusCode: 500, - body: { - error: { - type: 'snapshot_in_progress_exception', - }, - }, - } as any) - ); - - const result = await migrationRetryCallCluster(() => client.ping(), logger, 1); - expect(result.body).toEqual(dummyBody); - }); - - it('logs only once for each unique error message', async () => { - client.ping - .mockImplementationOnce(() => - createErrorReturn( - new errors.ResponseError({ - statusCode: 503, - } as any) - ) - ) - .mockImplementationOnce(() => - createErrorReturn(new errors.ConnectionError('connection error', {} as any)) - ) - .mockImplementationOnce(() => - createErrorReturn( - new errors.ResponseError({ - statusCode: 503, - } as any) - ) - ) - .mockImplementationOnce(() => - createErrorReturn(new errors.ConnectionError('connection error', {} as any)) - ) - .mockImplementationOnce(() => - createErrorReturn( - new errors.ResponseError({ - statusCode: 500, - body: { - error: { - type: 'snapshot_in_progress_exception', - }, - }, - } as any) - ) - ) - .mockImplementationOnce(() => - opensearchClientMock.createSuccessTransportRequestPromise({ ...dummyBody }) - ); - - await migrationRetryCallCluster(() => client.ping(), logger, 1); - - expect(loggingSystemMock.collect(logger).warn).toMatchInlineSnapshot(` - Array [ - Array [ - "Unable to connect to OpenSearch. Error: Response Error", - ], - Array [ - "Unable to connect to OpenSearch. Error: connection error", - ], - Array [ - "Unable to connect to OpenSearch. Error: snapshot_in_progress_exception", - ], - ] - `); - }); - - it('rejects when OpenSearch API calls reject with other errors', async () => { - client.ping - .mockImplementationOnce(() => - createErrorReturn( - new errors.ResponseError({ - statusCode: 418, - body: { - error: { - type: `I'm a teapot`, - }, - }, - } as any) - ) - ) - .mockImplementationOnce(() => - opensearchClientMock.createSuccessTransportRequestPromise({ ...dummyBody }) - ); - - await expect( - migrationRetryCallCluster(() => client.ping(), logger, 1) - ).rejects.toMatchInlineSnapshot(`[ResponseError: I'm a teapot]`); - }); - - it('stops retrying when OpenSearch API calls reject with other errors', async () => { - client.ping - .mockImplementationOnce(() => - createErrorReturn(new errors.TimeoutError('timeout error', {} as any)) - ) - .mockImplementationOnce(() => - createErrorReturn(new errors.TimeoutError('timeout error', {} as any)) - ) - .mockImplementationOnce(() => createErrorReturn(new Error('unknown error'))) - .mockImplementationOnce(() => - opensearchClientMock.createSuccessTransportRequestPromise({ ...dummyBody }) - ); - - await expect( - migrationRetryCallCluster(() => client.ping(), logger, 1) - ).rejects.toMatchInlineSnapshot(`[Error: unknown error]`); - }); -}); diff --git a/src/core/server/opensearch/client/types.ts b/src/core/server/opensearch/client/types.ts index 3e3d7686aeba..fc0236882d44 100644 --- a/src/core/server/opensearch/client/types.ts +++ b/src/core/server/opensearch/client/types.ts @@ -30,13 +30,13 @@ * GitHub history for details. */ -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { OpenSearchDashboardsClient } from '@opensearch-project/opensearch/api/opensearch_dashboards'; import type { ApiResponse, TransportRequestOptions, TransportRequestParams, TransportRequestPromise, -} from '@elastic/elasticsearch/lib/Transport'; +} from '@opensearch-project/opensearch/lib/Transport'; /** * Client used to query the opensearch cluster. @@ -44,7 +44,7 @@ import type { * @public */ export type OpenSearchClient = Omit< - KibanaClient, + OpenSearchDashboardsClient, 'connectionPool' | 'transport' | 'serializer' | 'extend' | 'child' | 'close' > & { transport: { diff --git a/src/core/server/opensearch/version_check/ensure_opensearch_version.test.ts b/src/core/server/opensearch/version_check/ensure_opensearch_version.test.ts index dbbc0f2236ee..d9435a5cea0c 100644 --- a/src/core/server/opensearch/version_check/ensure_opensearch_version.test.ts +++ b/src/core/server/opensearch/version_check/ensure_opensearch_version.test.ts @@ -169,7 +169,7 @@ describe('pollOpenSearchNodesVersion', () => { internalClient.nodes.info.mockImplementationOnce(() => createOpenSearchError(error)); }; - it('returns iscCompatible=false and keeps polling when a poll request throws', (done) => { + it('returns isCompatible=false and keeps polling when a poll request throws', (done) => { expect.assertions(3); const expectedCompatibilityResults = [false, false, true]; jest.clearAllMocks(); diff --git a/src/core/server/opensearch/version_check/ensure_opensearch_version.ts b/src/core/server/opensearch/version_check/ensure_opensearch_version.ts index 6850f2373b71..9e6811bf2262 100644 --- a/src/core/server/opensearch/version_check/ensure_opensearch_version.ts +++ b/src/core/server/opensearch/version_check/ensure_opensearch_version.ts @@ -38,6 +38,7 @@ import { timer, of, from, Observable } from 'rxjs'; import { map, distinctUntilChanged, catchError, exhaustMap, mergeMap } from 'rxjs/operators'; import { get } from 'lodash'; +import { ApiResponse } from '@opensearch-project/opensearch'; import { opensearchVersionCompatibleWithOpenSearchDashboards, opensearchVersionEqualsOpenSearchDashboards, @@ -61,9 +62,9 @@ export const getNodeId = async ( healthcheckAttributeName: string ): Promise => { try { - const state = await internalClient.cluster.state({ + const state = (await internalClient.cluster.state({ filter_path: [`nodes.*.attributes.${healthcheckAttributeName}`], - }); + })) as ApiResponse; /* Aggregate different cluster_ids from the OpenSearch nodes * if all the nodes have the same cluster_id, retrieve nodes.info from _local node only * Using _cluster/state/nodes to retrieve the cluster_id of each node from master node which is considered to be a lightweight operation @@ -97,7 +98,7 @@ export interface PollOpenSearchNodesVersionOptions { interface NodeInfo { version: string; ip: string; - http: { + http?: { publish_address: string; }; name: string; @@ -115,6 +116,7 @@ export interface NodesVersionCompatibility { incompatibleNodes: NodeInfo[]; warningNodes: NodeInfo[]; opensearchDashboardsVersion: string; + nodesInfoRequestError?: Error; } function getHumanizedNodeName(node: NodeInfo) { @@ -225,8 +227,8 @@ export const pollOpenSearchNodesVersion = ({ }) ).pipe( map(({ body }) => body), - catchError((_err: any) => { - return of({ nodes: {} }); + catchError((nodesInfoRequestError: any) => { + return of({ nodes: {}, nodesInfoRequestError }); }) ) ) @@ -238,8 +240,8 @@ export const pollOpenSearchNodesVersion = ({ }) ).pipe( map(({ body }) => body), - catchError((_err) => { - return of({ nodes: {} }); + catchError((nodesInfoRequestError: any) => { + return of({ nodes: {}, nodesInfoRequestError }); }) ); } diff --git a/src/core/server/saved_objects/index.ts b/src/core/server/saved_objects/index.ts index 6a8ab84e86f6..2ccee2333e99 100644 --- a/src/core/server/saved_objects/index.ts +++ b/src/core/server/saved_objects/index.ts @@ -65,8 +65,6 @@ export { } from './service/lib/repository'; export { - SavedObjectsCoreFieldMapping, - SavedObjectsComplexFieldMapping, SavedObjectsFieldMapping, SavedObjectsMappingProperties, SavedObjectsTypeMappingDefinition, diff --git a/src/core/server/saved_objects/mappings/index.ts b/src/core/server/saved_objects/mappings/index.ts index fe6c38fda5ca..f5400384bbe3 100644 --- a/src/core/server/saved_objects/mappings/index.ts +++ b/src/core/server/saved_objects/mappings/index.ts @@ -31,8 +31,6 @@ */ export { getTypes, getProperty, getRootProperties, getRootPropertiesObjects } from './lib'; export { - SavedObjectsComplexFieldMapping, - SavedObjectsCoreFieldMapping, SavedObjectsTypeMappingDefinition, SavedObjectsTypeMappingDefinitions, SavedObjectsMappingProperties, diff --git a/src/core/server/saved_objects/mappings/lib/get_property.test.ts b/src/core/server/saved_objects/mappings/lib/get_property.test.ts index a05d671f1a9e..d23d64648b20 100644 --- a/src/core/server/saved_objects/mappings/lib/get_property.test.ts +++ b/src/core/server/saved_objects/mappings/lib/get_property.test.ts @@ -53,7 +53,7 @@ const MAPPINGS = { }, }, }, -}; +} as const; function runTest(key: string | string[], mapping: IndexMapping | SavedObjectsFieldMapping) { expect(typeof key === 'string' || Array.isArray(key)).toBeTruthy(); diff --git a/src/core/server/saved_objects/mappings/lib/get_property.ts b/src/core/server/saved_objects/mappings/lib/get_property.ts index 012907dd4d81..03a9ef1a02a5 100644 --- a/src/core/server/saved_objects/mappings/lib/get_property.ts +++ b/src/core/server/saved_objects/mappings/lib/get_property.ts @@ -26,7 +26,7 @@ */ import { toPath } from 'lodash'; -import { SavedObjectsCoreFieldMapping, SavedObjectsFieldMapping, IndexMapping } from '../types'; +import { SavedObjectsFieldMapping, IndexMapping } from '../types'; function getPropertyMappingFromObjectMapping( mapping: IndexMapping | SavedObjectsFieldMapping, @@ -34,7 +34,7 @@ function getPropertyMappingFromObjectMapping( ): SavedObjectsFieldMapping | undefined { const props = (mapping && (mapping as IndexMapping).properties) || - (mapping && (mapping as SavedObjectsCoreFieldMapping).fields); + (mapping && (mapping as SavedObjectsFieldMapping).fields); if (!props) { return undefined; diff --git a/src/core/server/saved_objects/mappings/lib/get_root_properties_objects.test.ts b/src/core/server/saved_objects/mappings/lib/get_root_properties_objects.test.ts index fc4a76164778..00ca1110df2a 100644 --- a/src/core/server/saved_objects/mappings/lib/get_root_properties_objects.test.ts +++ b/src/core/server/saved_objects/mappings/lib/get_root_properties_objects.test.ts @@ -34,7 +34,7 @@ test(`returns single object with properties`, () => { properties: {}, }, }, - }; + } as const; const result = getRootPropertiesObjects(mappings); expect(result).toEqual({ @@ -51,7 +51,7 @@ test(`returns single object with type === 'object'`, () => { type: 'object', }, }, - }; + } as const; const result = getRootPropertiesObjects(mappings); expect(result).toEqual({ @@ -71,7 +71,7 @@ test(`returns two objects with properties`, () => { properties: {}, }, }, - }; + } as const; const result = getRootPropertiesObjects(mappings); expect(result).toEqual({ @@ -94,7 +94,7 @@ test(`returns two objects with type === 'object'`, () => { type: 'object', }, }, - }; + } as const; const result = getRootPropertiesObjects(mappings); expect(result).toEqual({ @@ -114,7 +114,7 @@ test(`excludes objects without properties and type of keyword`, () => { type: 'keyword', }, }, - }; + } as const; const result = getRootPropertiesObjects(mappings); expect(result).toEqual({}); @@ -130,7 +130,7 @@ test(`excludes two objects without properties and type of keyword`, () => { type: 'keyword', }, }, - }; + } as const; const result = getRootPropertiesObjects(mappings); expect(result).toEqual({}); @@ -146,7 +146,7 @@ test(`includes one object with properties and excludes one object without proper type: 'keyword', }, }, - }; + } as const; const result = getRootPropertiesObjects(mappings); expect(result).toEqual({ @@ -166,7 +166,7 @@ test(`includes one object with type === 'object' and excludes one object without type: 'keyword', }, }, - }; + } as const; const result = getRootPropertiesObjects(mappings); expect(result).toEqual({ @@ -189,7 +189,7 @@ test('excludes references and migrationVersion which are part of the blacklist', type: 'object', }, }, - }; + } as const; const result = getRootPropertiesObjects(mappings); expect(result).toEqual({ foo: { diff --git a/src/core/server/saved_objects/mappings/lib/get_root_properties_objects.ts b/src/core/server/saved_objects/mappings/lib/get_root_properties_objects.ts index 30e82c80e92d..c0b8adc5a5ae 100644 --- a/src/core/server/saved_objects/mappings/lib/get_root_properties_objects.ts +++ b/src/core/server/saved_objects/mappings/lib/get_root_properties_objects.ts @@ -25,11 +25,7 @@ * under the License. */ -import { - SavedObjectsComplexFieldMapping, - IndexMapping, - SavedObjectsMappingProperties, -} from '../types'; +import { SavedObjectsFieldMapping, IndexMapping, SavedObjectsMappingProperties } from '../types'; import { getRootProperties } from './get_root_properties'; /** @@ -55,7 +51,7 @@ export function getRootPropertiesObjects(mappings: IndexMapping) { // we consider the existence of the properties or type of object to designate that this is an object datatype if ( !omittedRootProps.includes(key) && - ((value as SavedObjectsComplexFieldMapping).properties || value.type === 'object') + ((value as SavedObjectsFieldMapping).properties || value.type === 'object') ) { acc[key] = value; } diff --git a/src/core/server/saved_objects/mappings/types.ts b/src/core/server/saved_objects/mappings/types.ts index b5fbac25c470..e14b3febb709 100644 --- a/src/core/server/saved_objects/mappings/types.ts +++ b/src/core/server/saved_objects/mappings/types.ts @@ -30,6 +30,8 @@ * GitHub history for details. */ +import type { opensearchtypes } from '@opensearch-project/opensearch'; + /** * Describe a saved object type mapping. * @@ -117,13 +119,21 @@ export interface SavedObjectsMappingProperties { * * @public */ -export type SavedObjectsFieldMapping = - | SavedObjectsCoreFieldMapping - | SavedObjectsComplexFieldMapping; +export type SavedObjectsFieldMapping = opensearchtypes.MappingProperty & { + /** + * The dynamic property of the mapping, either `false` or `'strict'`. If + * unspecified `dynamic: 'strict'` will be inherited from the top-level + * index mappings. + * + * Note: To limit the number of mapping fields Saved Object types should + * *never* use `dynamic: true`. + */ + dynamic?: false | 'strict'; +}; /** @internal */ export interface IndexMapping { - dynamic?: string; + dynamic?: boolean | 'strict'; properties: SavedObjectsMappingProperties; _meta?: IndexMappingMeta; } @@ -135,42 +145,3 @@ export interface IndexMappingMeta { // the md5 hash of that mapping's value when the index was created. migrationMappingPropertyHashes?: { [k: string]: string }; } - -/** - * See {@link SavedObjectsFieldMapping} for documentation. - * - * @public - */ -export interface SavedObjectsCoreFieldMapping { - type: string; - null_value?: number | boolean | string; - index?: boolean; - doc_values?: boolean; - fields?: { - [subfield: string]: { - type: string; - ignore_above?: number; - }; - }; -} - -/** - * See {@link SavedObjectsFieldMapping} for documentation. - * - * @public - */ -export interface SavedObjectsComplexFieldMapping { - /** - * The dynamic property of the mapping, either `false` or `'strict'`. If - * unspecified `dynamic: 'strict'` will be inherited from the top-level - * index mappings. - * - * Note: To limit the number of mapping fields Saved Object types should - * *never* use `dynamic: true`. - */ - dynamic?: false | 'strict'; - enabled?: boolean; - doc_values?: boolean; - type?: string; - properties: SavedObjectsMappingProperties; -} diff --git a/src/core/server/saved_objects/migrations/core/__snapshots__/opensearch_index.test.ts.snap b/src/core/server/saved_objects/migrations/core/__snapshots__/opensearch_index.test.ts.snap index 6bd567be204d..a9fa5ed34ed5 100644 --- a/src/core/server/saved_objects/migrations/core/__snapshots__/opensearch_index.test.ts.snap +++ b/src/core/server/saved_objects/migrations/core/__snapshots__/opensearch_index.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ElasticIndex write writes documents in bulk to the index 1`] = ` +exports[`OpenSearchIndex write writes documents in bulk to the index 1`] = ` Array [ Object { "body": Array [ diff --git a/src/core/server/saved_objects/migrations/core/build_active_mappings.test.ts b/src/core/server/saved_objects/migrations/core/build_active_mappings.test.ts index 81aa395bd702..02b83d16e2fb 100644 --- a/src/core/server/saved_objects/migrations/core/build_active_mappings.test.ts +++ b/src/core/server/saved_objects/migrations/core/build_active_mappings.test.ts @@ -38,19 +38,19 @@ describe('buildActiveMappings', () => { const properties = { aaa: { type: 'text' }, bbb: { type: 'long' }, - }; + } as const; expect(buildActiveMappings(properties)).toMatchSnapshot(); }); test('disallows duplicate mappings', () => { - const properties = { type: { type: 'long' } }; + const properties = { type: { type: 'long' } } as const; expect(() => buildActiveMappings(properties)).toThrow(/Cannot redefine core mapping \"type\"/); }); test('disallows mappings with leading underscore', () => { - const properties = { _hm: { type: 'keyword' } }; + const properties = { _hm: { type: 'keyword' } } as const; expect(() => buildActiveMappings(properties)).toThrow( /Invalid mapping \"_hm\"\. Mappings cannot start with _/ @@ -79,7 +79,7 @@ describe('buildActiveMappings', () => { aaa: { type: 'keyword', fields: { a: { type: 'keyword' }, b: { type: 'text' } } }, bbb: { fields: { b: { type: 'text' }, a: { type: 'keyword' } }, type: 'keyword' }, ccc: { fields: { b: { type: 'text' }, a: { type: 'text' } }, type: 'keyword' }, - }; + } as const; const mappings = buildActiveMappings(properties); const hashes = mappings._meta!.migrationMappingPropertyHashes!; @@ -183,6 +183,7 @@ describe('diffMappings', () => { _meta: { migrationMappingPropertyHashes: { foo: 'bar' }, }, + // @ts-expect-error dynamic accepts boolean | "strict" | undefined. error is expected for test purpose. dynamic: 'abcde', properties: {}, }; diff --git a/src/core/server/saved_objects/migrations/core/build_index_map.test.ts b/src/core/server/saved_objects/migrations/core/build_index_map.test.ts index 64fc54d3640e..eb46066f1864 100644 --- a/src/core/server/saved_objects/migrations/core/build_index_map.test.ts +++ b/src/core/server/saved_objects/migrations/core/build_index_map.test.ts @@ -55,7 +55,7 @@ test('mappings without index pattern goes to default index', () => { type1: { properties: { field1: { - type: 'string', + type: 'text', }, }, }, @@ -67,7 +67,7 @@ test('mappings without index pattern goes to default index', () => { type1: { properties: { field1: { - type: 'string', + type: 'text', }, }, }, @@ -88,7 +88,7 @@ test(`mappings with custom index pattern doesn't go to default index`, () => { type1: { properties: { field1: { - type: 'string', + type: 'text', }, }, }, @@ -100,7 +100,7 @@ test(`mappings with custom index pattern doesn't go to default index`, () => { type1: { properties: { field1: { - type: 'string', + type: 'text', }, }, }, @@ -122,7 +122,7 @@ test('creating a script gets added to the index pattern', () => { type1: { properties: { field1: { - type: 'string', + type: 'text', }, }, }, @@ -135,7 +135,7 @@ test('creating a script gets added to the index pattern', () => { type1: { properties: { field1: { - type: 'string', + type: 'text', }, }, }, @@ -163,18 +163,18 @@ test('throws when two scripts are defined for an index pattern', () => { type1: { properties: { field1: { - type: 'string', + type: 'text', }, }, }, type2: { properties: { field1: { - type: 'string', + type: 'text', }, }, }, - }; + } as const; expect(() => createIndexMap({ opensearchDashboardsIndexName: defaultIndex, diff --git a/src/core/server/saved_objects/migrations/core/call_cluster.ts b/src/core/server/saved_objects/migrations/core/call_cluster.ts index f896da60c005..c3e6a72f937a 100644 --- a/src/core/server/saved_objects/migrations/core/call_cluster.ts +++ b/src/core/server/saved_objects/migrations/core/call_cluster.ts @@ -31,11 +31,15 @@ * funcationality contained here. */ +import { opensearchtypes } from '@opensearch-project/opensearch'; import { IndexMapping } from '../../mappings'; export interface CallCluster { (path: 'bulk', opts: { body: object[] }): Promise; - (path: 'count', opts: CountOpts): Promise<{ count: number; _shards: ShardsInfo }>; + (path: 'count', opts: CountOpts): Promise<{ + count: number; + _shards: opensearchtypes.ShardStatistics; + }>; (path: 'clearScroll', opts: { scrollId: string }): Promise; (path: 'indices.create' | 'indices.delete', opts: IndexCreationOpts): Promise; (path: 'indices.exists', opts: IndexOpts): Promise; @@ -172,14 +176,7 @@ export interface SearchResults { hits: RawDoc[]; }; _scroll_id?: string; - _shards: ShardsInfo; -} - -export interface ShardsInfo { - total: number; - successful: number; - skipped: number; - failed: number; + _shards: opensearchtypes.ShardStatistics; } export interface ErrorResponse { diff --git a/src/core/server/saved_objects/migrations/core/index_migrator.test.ts b/src/core/server/saved_objects/migrations/core/index_migrator.test.ts index 8058f20ce3d2..5cf4e4063808 100644 --- a/src/core/server/saved_objects/migrations/core/index_migrator.test.ts +++ b/src/core/server/saved_objects/migrations/core/index_migrator.test.ts @@ -26,6 +26,7 @@ */ import _ from 'lodash'; +import type { opensearchtypes } from '@opensearch-project/opensearch'; import { opensearchClientMock } from '../../../opensearch/client/mocks'; import { SavedObjectUnsanitizedDoc, SavedObjectsSerializer } from '../../serialization'; import { SavedObjectTypeRegistry } from '../../saved_objects_type_registry'; @@ -454,23 +455,29 @@ function withIndex( opensearchClientMock.createSuccessTransportRequestPromise({ task: 'zeid', _shards: { successful: 1, total: 1 }, - }) + } as opensearchtypes.ReindexResponse) ); client.tasks.get.mockReturnValue( - opensearchClientMock.createSuccessTransportRequestPromise({ completed: true }) + opensearchClientMock.createSuccessTransportRequestPromise({ + completed: true, + } as opensearchtypes.TaskGetResponse) ); client.search.mockReturnValue( - opensearchClientMock.createSuccessTransportRequestPromise(searchResult(0)) + opensearchClientMock.createSuccessTransportRequestPromise(searchResult(0) as any) ); client.bulk.mockReturnValue( - opensearchClientMock.createSuccessTransportRequestPromise({ items: [] }) + opensearchClientMock.createSuccessTransportRequestPromise({ + items: [] as any[], + } as opensearchtypes.BulkResponse) ); client.count.mockReturnValue( opensearchClientMock.createSuccessTransportRequestPromise({ count: numOutOfDate, _shards: { successful: 1, total: 1 }, - }) + } as opensearchtypes.CountResponse) ); + // @ts-expect-error error is due to type {} is not compatible with type 'ScrollResponse' + // this setting is fine for test purpose client.scroll.mockImplementation(() => { if (scrollCallCounter <= docs.length) { const result = searchResult(scrollCallCounter); diff --git a/src/core/server/saved_objects/migrations/core/index_migrator.ts b/src/core/server/saved_objects/migrations/core/index_migrator.ts index 5c6a01246991..17ac3f752917 100644 --- a/src/core/server/saved_objects/migrations/core/index_migrator.ts +++ b/src/core/server/saved_objects/migrations/core/index_migrator.ts @@ -169,7 +169,7 @@ async function deleteIndexTemplates({ client, log, obsoleteIndexTemplatePattern log.info(`Removing index templates: ${templateNames}`); - return Promise.all(templateNames.map((name) => client.indices.deleteTemplate({ name }))); + return Promise.all(templateNames.map((name) => client.indices.deleteTemplate({ name: name! }))); } /** @@ -207,6 +207,7 @@ async function migrateSourceToDest(context: Context) { await Index.write( client, dest.indexName, + // @ts-expect-error @opensearch-project/opensearch _source is optional await migrateRawDocs(serializer, documentMigrator.migrate, docs, log) ); } diff --git a/src/core/server/saved_objects/migrations/core/migration_context.test.ts b/src/core/server/saved_objects/migrations/core/migration_context.test.ts index 43a8ec983533..ce1324183cbe 100644 --- a/src/core/server/saved_objects/migrations/core/migration_context.test.ts +++ b/src/core/server/saved_objects/migrations/core/migration_context.test.ts @@ -50,7 +50,7 @@ describe('disableUnknownTypeMappingFields', () => { }, }, }, - }; + } as const; const activeMappings = { _meta: { migrationMappingPropertyHashes: { @@ -65,7 +65,7 @@ describe('disableUnknownTypeMappingFields', () => { }, }, }, - }; + } as const; const targetMappings = disableUnknownTypeMappingFields(activeMappings, sourceMappings); it('disables complex field mappings from unknown types in the source mappings', () => { diff --git a/src/core/server/saved_objects/migrations/core/migration_opensearch_client.ts b/src/core/server/saved_objects/migrations/core/migration_opensearch_client.ts index 34f0e88ea696..6d481a81435b 100644 --- a/src/core/server/saved_objects/migrations/core/migration_opensearch_client.ts +++ b/src/core/server/saved_objects/migrations/core/migration_opensearch_client.ts @@ -24,7 +24,7 @@ * specific language governing permissions and limitations * under the License. */ -import type { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; +import type { TransportRequestOptions } from '@opensearch-project/opensearch/lib/Transport'; import { get } from 'lodash'; import { set } from '@elastic/safer-lodash-set'; diff --git a/src/core/server/saved_objects/migrations/core/opensearch_index.test.ts b/src/core/server/saved_objects/migrations/core/opensearch_index.test.ts index c5c0473fe6b5..e4bb1a12735e 100644 --- a/src/core/server/saved_objects/migrations/core/opensearch_index.test.ts +++ b/src/core/server/saved_objects/migrations/core/opensearch_index.test.ts @@ -25,11 +25,12 @@ * under the License. */ +import type { opensearchtypes } from '@opensearch-project/opensearch'; import _ from 'lodash'; import { opensearchClientMock } from '../../../opensearch/client/mocks'; import * as Index from './opensearch_index'; -describe('ElasticIndex', () => { +describe('OpenSearchIndex', () => { let client: ReturnType; beforeEach(() => { @@ -61,9 +62,11 @@ describe('ElasticIndex', () => { return opensearchClientMock.createSuccessTransportRequestPromise({ [index]: { aliases: { foo: index }, - mappings: { spock: { dynamic: 'strict', properties: { a: 'b' } } }, + // @ts-expect-error pass unsupported mappings 'spock' for test purpose + mappings: { spock: { dynamic: 'strict', properties: { a: 'b' } as any } }, + settings: {}, }, - }); + } as opensearchtypes.IndicesGetResponse); }); await expect(Index.fetchInfo(client, '.baz')).rejects.toThrow( @@ -78,11 +81,13 @@ describe('ElasticIndex', () => { [index]: { aliases: { foo: index }, mappings: { - doc: { dynamic: 'strict', properties: { a: 'b' } }, - doctor: { dynamic: 'strict', properties: { a: 'b' } }, + // @ts-expect-error pass multiple root types 'doc' and 'doctor' for test purpose + doc: { dynamic: 'strict', properties: { a: 'b' } as any }, + doctor: { dynamic: 'strict', properties: { a: 'b' } as any }, }, + settings: {}, }, - }); + } as opensearchtypes.IndicesGetResponse); }); await expect(Index.fetchInfo(client, '.baz')).rejects.toThrow( @@ -96,9 +101,10 @@ describe('ElasticIndex', () => { return opensearchClientMock.createSuccessTransportRequestPromise({ [index]: { aliases: { foo: index }, - mappings: { dynamic: 'strict', properties: { a: 'b' } }, + mappings: { dynamic: 'strict', properties: { a: 'b' } as any }, + settings: {}, }, - }); + } as opensearchtypes.IndicesGetResponse); }); const info = await Index.fetchInfo(client, '.baz'); @@ -107,6 +113,7 @@ describe('ElasticIndex', () => { mappings: { dynamic: 'strict', properties: { a: 'b' } }, exists: true, indexName: '.baz', + settings: {}, }); }); }); @@ -167,7 +174,7 @@ describe('ElasticIndex', () => { test('removes existing alias', async () => { client.indices.getAlias.mockResolvedValue( opensearchClientMock.createSuccessTransportRequestPromise({ - '.my-fanci-index': '.muchacha', + '.my-fanci-index': { aliases: { '.muchacha': {} } }, }) ); @@ -190,7 +197,7 @@ describe('ElasticIndex', () => { test('allows custom alias actions', async () => { client.indices.getAlias.mockResolvedValue( opensearchClientMock.createSuccessTransportRequestPromise({ - '.my-fanci-index': '.muchacha', + '.my-fanci-index': { aliases: { '.muchacha': {} } }, }) ); @@ -218,14 +225,18 @@ describe('ElasticIndex', () => { test('it creates the destination index, then reindexes to it', async () => { client.indices.getAlias.mockResolvedValue( opensearchClientMock.createSuccessTransportRequestPromise({ - '.my-fanci-index': '.muchacha', + '.my-fanci-index': { aliases: { '.muchacha': {} } }, }) ); client.reindex.mockResolvedValue( - opensearchClientMock.createSuccessTransportRequestPromise({ task: 'abc' }) + opensearchClientMock.createSuccessTransportRequestPromise({ + task: 'abc', + } as opensearchtypes.ReindexResponse) ); client.tasks.get.mockResolvedValue( - opensearchClientMock.createSuccessTransportRequestPromise({ completed: true }) + opensearchClientMock.createSuccessTransportRequestPromise({ + completed: true, + } as opensearchtypes.TaskGetResponse) ); const info = { @@ -233,10 +244,10 @@ describe('ElasticIndex', () => { exists: true, indexName: '.ze-index', mappings: { - dynamic: 'strict', + dynamic: 'strict' as const, properties: { foo: { type: 'keyword' } }, }, - }; + } as const; await Index.convertToAlias( client, @@ -292,13 +303,16 @@ describe('ElasticIndex', () => { test('throws error if re-index task fails', async () => { client.indices.getAlias.mockResolvedValue( opensearchClientMock.createSuccessTransportRequestPromise({ - '.my-fanci-index': '.muchacha', + '.my-fanci-index': { aliases: { '.muchacha': {} } }, }) ); client.reindex.mockResolvedValue( - opensearchClientMock.createSuccessTransportRequestPromise({ task: 'abc' }) + opensearchClientMock.createSuccessTransportRequestPromise({ + task: 'abc', + } as opensearchtypes.ReindexResponse) ); client.tasks.get.mockResolvedValue( + // @ts-expect-error @opensearch-project/opensearch GetTaskResponse requires a `task` property even on errors opensearchClientMock.createSuccessTransportRequestPromise({ completed: true, error: { @@ -306,7 +320,7 @@ describe('ElasticIndex', () => { reason: 'all shards failed', failed_shards: [], }, - }) + } as opensearchtypes.TaskGetResponse) ); const info = { @@ -319,6 +333,7 @@ describe('ElasticIndex', () => { }, }; + // @ts-expect-error dynamic accepts boolean | "strict" | undefined. error is expected for test purpose. await expect(Index.convertToAlias(client, info, '.muchacha', 10)).rejects.toThrow( /Re-index failed \[search_phase_execution_exception\] all shards failed/ ); @@ -352,7 +367,9 @@ describe('ElasticIndex', () => { describe('write', () => { test('writes documents in bulk to the index', async () => { client.bulk.mockResolvedValue( - opensearchClientMock.createSuccessTransportRequestPromise({ items: [] }) + opensearchClientMock.createSuccessTransportRequestPromise({ + items: [] as any[], + } as opensearchtypes.BulkResponse) ); const index = '.myalias'; @@ -389,7 +406,7 @@ describe('ElasticIndex', () => { client.bulk.mockResolvedValue( opensearchClientMock.createSuccessTransportRequestPromise({ items: [{ index: { error: { type: 'shazm', reason: 'dern' } } }], - }) + } as opensearchtypes.BulkResponse) ); const index = '.myalias'; diff --git a/src/core/server/saved_objects/migrations/core/opensearch_index.ts b/src/core/server/saved_objects/migrations/core/opensearch_index.ts index aca47217d68d..dc5d8b507c5b 100644 --- a/src/core/server/saved_objects/migrations/core/opensearch_index.ts +++ b/src/core/server/saved_objects/migrations/core/opensearch_index.ts @@ -31,11 +31,12 @@ */ import _ from 'lodash'; +import { opensearchtypes } from '@opensearch-project/opensearch'; import { MigrationOpenSearchClient } from './migration_opensearch_client'; -import { CountResponse, SearchResponse } from '../../../opensearch'; +import { CountResponse } from '../../../opensearch'; import { IndexMapping } from '../../mappings'; import { SavedObjectsMigrationVersion } from '../../types'; -import { AliasAction, RawDoc, ShardsInfo } from './call_cluster'; +import { AliasAction, RawDoc } from './call_cluster'; import { SavedObjectsRawDocSource } from '../../serialization'; const settings = { number_of_shards: 1, auto_expand_replicas: '0-1' }; @@ -68,6 +69,7 @@ export async function fetchInfo( const [indexName, indexInfo] = Object.entries(body)[0]; + // @ts-expect-error @opensearch-project/opensearch IndexState.alias and IndexState.mappings should be required return assertIsSupportedIndex({ ...indexInfo, exists: true, indexName }); } @@ -91,11 +93,11 @@ export function reader( const nextBatch = () => scrollId !== undefined - ? client.scroll>({ + ? client.scroll({ scroll, scroll_id: scrollId, }) - : client.search>({ + : client.search({ body: { size: batchSize }, index, scroll, @@ -147,7 +149,7 @@ export async function write(client: MigrationOpenSearchClient, index: string, do return; } - const exception: any = new Error(err.index.error!.reason); + const exception: any = new Error(err.index!.error!.reason); exception.detail = err; throw exception; } @@ -319,7 +321,7 @@ function assertIsSupportedIndex(indexInfo: FullIndexInfo) { * Object indices should only ever have a single shard. This is more to handle * instances where customers manually expand the shards of an index. */ -function assertResponseIncludeAllShards({ _shards }: { _shards: ShardsInfo }) { +function assertResponseIncludeAllShards({ _shards }: { _shards: opensearchtypes.ShardStatistics }) { if (!_.has(_shards, 'total') || !_.has(_shards, 'successful')) { return; } @@ -372,7 +374,7 @@ async function reindex( await new Promise((r) => setTimeout(r, pollInterval)); const { body } = await client.tasks.get({ - task_id: task, + task_id: String(task), }); if (body.error) { diff --git a/src/core/server/saved_objects/migrations/opensearch_dashboards/opensearch_dashboards_migrator.test.ts b/src/core/server/saved_objects/migrations/opensearch_dashboards/opensearch_dashboards_migrator.test.ts index e3daad27d6fc..cf3fa5c97670 100644 --- a/src/core/server/saved_objects/migrations/opensearch_dashboards/opensearch_dashboards_migrator.test.ts +++ b/src/core/server/saved_objects/migrations/opensearch_dashboards/opensearch_dashboards_migrator.test.ts @@ -81,7 +81,8 @@ describe('OpenSearchDashboardsMigrator', () => { options.client.cat.templates.mockReturnValue( opensearchClientMock.createSuccessTransportRequestPromise( - { templates: [] }, + // @ts-expect-error assign the type to CatTemplatesResponse for test purpose + { templates: [] } as CatTemplatesResponse, { statusCode: 404 } ) ); @@ -105,7 +106,8 @@ describe('OpenSearchDashboardsMigrator', () => { options.client.cat.templates.mockReturnValue( opensearchClientMock.createSuccessTransportRequestPromise( - { templates: [] }, + // @ts-expect-error assign the type to CatTemplatesResponse for test purpose + { templates: [] } as CatTemplatesResponse, { statusCode: 404 } ) ); diff --git a/src/core/server/saved_objects/saved_objects_service.test.ts b/src/core/server/saved_objects/saved_objects_service.test.ts index eddaf92414c1..54bd2f74f6b2 100644 --- a/src/core/server/saved_objects/saved_objects_service.test.ts +++ b/src/core/server/saved_objects/saved_objects_service.test.ts @@ -38,7 +38,7 @@ import { } from './saved_objects_service.test.mocks'; import { BehaviorSubject } from 'rxjs'; import { ByteSizeValue } from '@osd/config-schema'; -import { errors as opensearchErrors } from '@elastic/elasticsearch'; +import { errors as opensearchErrors } from '@opensearch-project/opensearch'; import { SavedObjectsService } from './saved_objects_service'; import { mockCoreContext } from '../core_context.mock'; diff --git a/src/core/server/saved_objects/saved_objects_type_registry.ts b/src/core/server/saved_objects/saved_objects_type_registry.ts index 599f9eb0cfa6..57a3f9aedb3a 100644 --- a/src/core/server/saved_objects/saved_objects_type_registry.ts +++ b/src/core/server/saved_objects/saved_objects_type_registry.ts @@ -56,7 +56,7 @@ export class SavedObjectTypeRegistry { if (this.types.has(type.name)) { throw new Error(`Type '${type.name}' is already registered`); } - this.types.set(type.name, deepFreeze(type)); + this.types.set(type.name, deepFreeze(type) as SavedObjectsType); } /** diff --git a/src/core/server/saved_objects/service/lib/decorate_opensearch_error.test.ts b/src/core/server/saved_objects/service/lib/decorate_opensearch_error.test.ts index 74eff405b125..35e719c9dc00 100644 --- a/src/core/server/saved_objects/service/lib/decorate_opensearch_error.test.ts +++ b/src/core/server/saved_objects/service/lib/decorate_opensearch_error.test.ts @@ -30,7 +30,7 @@ * GitHub history for details. */ -import { errors as opensearchErrors } from '@elastic/elasticsearch'; +import { errors as opensearchErrors } from '@opensearch-project/opensearch'; import { opensearchClientMock } from '../../../opensearch/client/mocks'; import { decorateOpenSearchError } from './decorate_opensearch_error'; import { SavedObjectsErrorHelpers } from './errors'; diff --git a/src/core/server/saved_objects/service/lib/decorate_opensearch_error.ts b/src/core/server/saved_objects/service/lib/decorate_opensearch_error.ts index c2b6f521d6cc..c28c2f5111c2 100644 --- a/src/core/server/saved_objects/service/lib/decorate_opensearch_error.ts +++ b/src/core/server/saved_objects/service/lib/decorate_opensearch_error.ts @@ -30,7 +30,7 @@ * GitHub history for details. */ -import { errors as opensearchErrors } from '@elastic/elasticsearch'; +import { errors as opensearchErrors } from '@opensearch-project/opensearch'; import { get } from 'lodash'; const responseErrors = { diff --git a/src/core/server/saved_objects/service/lib/filter_utils.test.ts b/src/core/server/saved_objects/service/lib/filter_utils.test.ts index 4e1245e37212..397bac7e37be 100644 --- a/src/core/server/saved_objects/service/lib/filter_utils.test.ts +++ b/src/core/server/saved_objects/service/lib/filter_utils.test.ts @@ -48,7 +48,7 @@ const mockMappings = { type: 'text', }, bytes: { - type: 'number', + type: 'integer', }, }, }, @@ -92,7 +92,7 @@ const mockMappings = { }, }, }, -}; +} as const; describe('Filter Utils', () => { describe('#validateConvertFilterToKueryNode', () => { diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index b2ebc43db362..6c47a91e315e 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -3352,6 +3352,7 @@ describe('SavedObjectsRepository', () => { id: '6.0.0-alpha1', ...mockTimestampFields, version: mockVersion, + references: [], attributes: { buildNum: 8468, defaultIndex: 'logstash-*', diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 01ef8fdb1fd5..123def8d3c31 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -31,13 +31,10 @@ */ import { omit } from 'lodash'; +import type { opensearchtypes } from '@opensearch-project/opensearch'; import uuid from 'uuid'; -import { - OpenSearchClient, - DeleteDocumentResponse, - GetResponse, - SearchResponse, -} from '../../../opensearch/'; +import type { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry'; +import { OpenSearchClient, DeleteDocumentResponse } from '../../../opensearch/'; import { getRootPropertiesObjects, IndexMapping } from '../../mappings'; import { createRepositoryOpenSearchClient, @@ -399,8 +396,8 @@ export class SavedObjectsRepository { return expectedBulkGetResult; } - let savedObjectNamespace; - let savedObjectNamespaces; + let savedObjectNamespace: string | undefined; + let savedObjectNamespaces: string[] | undefined; let versionProperties; const { opensearchRequestIndex, @@ -412,8 +409,9 @@ export class SavedObjectsRepository { const actualResult = indexFound ? bulkGetResponse?.body.docs[opensearchRequestIndex] : undefined; - const docFound = indexFound && actualResult.found === true; - if (docFound && !this.rawDocExistsInNamespace(actualResult, namespace)) { + const docFound = indexFound && actualResult?.found === true; + // @ts-expect-error MultiGetHit._source is optional + if (docFound && !this.rawDocExistsInNamespace(actualResult!, namespace)) { const { id, type } = object; return { tag: 'Left' as 'Left', @@ -428,11 +426,14 @@ export class SavedObjectsRepository { }; } savedObjectNamespaces = - initialNamespaces || getSavedObjectNamespaces(namespace, docFound && actualResult); + initialNamespaces || + // @ts-expect-error MultiGetHit._source is optional + getSavedObjectNamespaces(namespace, docFound ? actualResult : undefined); + // @ts-expect-error MultiGetHit._source is optional versionProperties = getExpectedVersionProperties(version, actualResult); } else { if (this._registry.isSingleNamespace(object.type)) { - savedObjectNamespace = namespace; + savedObjectNamespace = initialNamespaces ? initialNamespaces[0] : namespace; } else if (this._registry.isMultiNamespace(object.type)) { savedObjectNamespaces = initialNamespaces || getSavedObjectNamespaces(namespace); } @@ -486,7 +487,7 @@ export class SavedObjectsRepository { const { requestedId, rawMigratedDoc, opensearchRequestIndex } = expectedResult.value; const { error, ...rawResponse } = Object.values( - bulkResponse?.body.items[opensearchRequestIndex] + bulkResponse?.body.items[opensearchRequestIndex] ?? {} )[0] as any; if (error) { @@ -572,13 +573,14 @@ export class SavedObjectsRepository { const { type, id, opensearchRequestIndex } = expectedResult.value; const doc = bulkGetResponse?.body.docs[opensearchRequestIndex]; - if (doc.found) { + if (doc?.found) { errors.push({ id, type, error: { ...errorContent(SavedObjectsErrorHelpers.createConflictError(type, id)), - ...(!this.rawDocExistsInNamespace(doc, namespace) && { + // @ts-expect-error MultiGetHit._source is optional + ...(!this.rawDocExistsInNamespace(doc!, namespace) && { metadata: { isNotOverwritable: true }, }), }, @@ -813,9 +815,12 @@ export class SavedObjectsRepository { }, }; - const { body, statusCode } = await this.client.search>(opensearchOptions, { - ignore: [404], - }); + const { body, statusCode } = await this.client.search( + opensearchOptions, + { + ignore: [404], + } + ); if (statusCode === 404) { // 404 is only possible here if the index is missing, which // we don't want to leak, see "404s from missing index" above @@ -832,9 +837,12 @@ export class SavedObjectsRepository { per_page: perPage, total: body.hits.total, saved_objects: body.hits.hits.map( - (hit: SavedObjectsRawDoc): SavedObjectsFindResult => ({ + (hit: opensearchtypes.SearchHit): SavedObjectsFindResult => ({ + // @ts-expect-error @opensearch-project/opensearch _source is optional ...this._rawToSavedObject(hit), - score: (hit as any)._score, + score: hit._score!, + // @ts-expect-error @opensearch-project/opensearch _source is optional + sort: hit.sort, }) ), } as SavedObjectsFindResponse; @@ -917,7 +925,8 @@ export class SavedObjectsRepository { const { type, id, opensearchRequestIndex } = expectedResult.value; const doc = bulkGetResponse?.body.docs[opensearchRequestIndex]; - if (!doc.found || !this.rawDocExistsInNamespace(doc, namespace)) { + // @ts-expect-error MultiGetHit._source is optional + if (!doc?.found || !this.rawDocExistsInNamespace(doc, namespace)) { return ({ id, type, @@ -925,25 +934,8 @@ export class SavedObjectsRepository { } as any) as SavedObject; } - const { originId, updated_at: updatedAt } = doc._source; - let namespaces = []; - if (!this._registry.isNamespaceAgnostic(type)) { - namespaces = doc._source.namespaces ?? [ - SavedObjectsUtils.namespaceIdToString(doc._source.namespace), - ]; - } - - return { - id, - type, - namespaces, - ...(originId && { originId }), - ...(updatedAt && { updated_at: updatedAt }), - version: encodeHitVersion(doc), - attributes: doc._source[type], - references: doc._source.references || [], - migrationVersion: doc._source.migrationVersion, - }; + // @ts-expect-error MultiGetHit._source is optional + return getSavedObjectFromSource(this._registry, type, id, doc); }), }; } @@ -968,7 +960,7 @@ export class SavedObjectsRepository { const namespace = normalizeNamespace(options.namespace); - const { body, statusCode } = await this.client.get>( + const { body, statusCode } = await this.client.get( { id: this._serializer.generateRawId(namespace, type, id), index: this.getIndexForType(type), @@ -976,9 +968,12 @@ export class SavedObjectsRepository { { ignore: [404] } ); - const docNotFound = body.found === false; const indexNotFound = statusCode === 404; - if (docNotFound || indexNotFound || !this.rawDocExistsInNamespace(body, namespace)) { + if ( + !isFoundGetResponse(body) || + indexNotFound || + !this.rawDocExistsInNamespace(body, namespace) + ) { // see "404s from missing index" above throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } @@ -1042,7 +1037,7 @@ export class SavedObjectsRepository { ...(Array.isArray(references) && { references }), }; - const { body, statusCode } = await this.client.update( + const { body, statusCode } = await this.client.update( { id: this._serializer.generateRawId(namespace, type, id), index: this.getIndexForType(type), @@ -1062,11 +1057,11 @@ export class SavedObjectsRepository { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } - const { originId } = body.get._source; - let namespaces = []; + const { originId } = body.get?._source ?? {}; + let namespaces: string[] = []; if (!this._registry.isNamespaceAgnostic(type)) { - namespaces = body.get._source.namespaces ?? [ - SavedObjectsUtils.namespaceIdToString(body.get._source.namespace), + namespaces = body.get?._source.namespaces ?? [ + SavedObjectsUtils.namespaceIdToString(body.get?._source.namespace), ]; } @@ -1074,7 +1069,6 @@ export class SavedObjectsRepository { id, type, updated_at: time, - // @ts-expect-error update doesn't have _seq_no, _primary_term as Record / any in LP version: encodeHitVersion(body), namespaces, ...(originId && { originId }), @@ -1368,9 +1362,10 @@ export class SavedObjectsRepository { const actualResult = indexFound ? bulkGetResponse?.body.docs[opensearchRequestIndex] : undefined; - const docFound = indexFound && actualResult.found === true; + const docFound = indexFound && actualResult?.found === true; if ( !docFound || + // @ts-expect-error MultiGetHit is incorrectly missing _id, _source !this.rawDocExistsInNamespace(actualResult, getNamespaceId(objectNamespace)) ) { return { @@ -1382,9 +1377,12 @@ export class SavedObjectsRepository { }, }; } - namespaces = actualResult._source.namespaces ?? [ - SavedObjectsUtils.namespaceIdToString(actualResult._source.namespace), + // @ts-expect-error MultiGetHit is incorrectly missing _id, _source + namespaces = actualResult!._source.namespaces ?? [ + // @ts-expect-error MultiGetHit is incorrectly missing _id, _source + SavedObjectsUtils.namespaceIdToString(actualResult!._source.namespace), ]; + // @ts-expect-error MultiGetHit is incorrectly missing _id, _source versionProperties = getExpectedVersionProperties(version, actualResult); } else { if (this._registry.isSingleNamespace(type)) { @@ -1439,7 +1437,7 @@ export class SavedObjectsRepository { documentToSave, opensearchRequestIndex, } = expectedResult.value; - const response = bulkUpdateResponse?.body.items[opensearchRequestIndex]; + const response = bulkUpdateResponse?.body.items[opensearchRequestIndex] ?? {}; // When a bulk update operation is completed, any fields specified in `_sourceIncludes` will be found in the "get" value of the // returned object. We need to retrieve the `originId` if it exists so we can return it to the consumer. const { error, _seq_no: seqNo, _primary_term: primaryTerm, get } = Object.values( @@ -1522,7 +1520,7 @@ export class SavedObjectsRepository { const raw = this._serializer.savedObjectToRaw(migrated as SavedObjectSanitizedDoc); - const { body } = await this.client.update({ + const { body } = await this.client.update({ id: raw._id, index: this.getIndexForType(type), refresh, @@ -1550,17 +1548,16 @@ export class SavedObjectsRepository { }, }); - const { originId } = body.get._source; + const { originId } = body.get?._source ?? {}; return { id, type, ...(savedObjectNamespaces && { namespaces: savedObjectNamespaces }), ...(originId && { originId }), updated_at: time, - references: body.get._source.references, - // @ts-expect-error + references: body.get?._source.references ?? [], version: encodeHitVersion(body), - attributes: body.get._source[type], + attributes: body.get?._source[type], }; } @@ -1605,7 +1602,7 @@ export class SavedObjectsRepository { * WARNING: This should only be used for documents that were retrieved from OpenSearch. Otherwise, the guarantees of the document ID * format mentioned above do not apply. */ - private rawDocExistsInNamespace(raw: SavedObjectsRawDoc, namespace?: string) { + private rawDocExistsInNamespace(raw: SavedObjectsRawDoc, namespace: string | undefined) { const rawDocType = raw._source.type; // if the type is namespace isolated, or namespace agnostic, we can continue to rely on the guarantees @@ -1638,7 +1635,7 @@ export class SavedObjectsRepository { throw new Error(`Cannot make preflight get request for non-multi-namespace type '${type}'.`); } - const { body, statusCode } = await this.client.get>( + const { body, statusCode } = await this.client.get( { id: this._serializer.generateRawId(undefined, type, id), index: this.getIndexForType(type), @@ -1649,8 +1646,7 @@ export class SavedObjectsRepository { ); const indexFound = statusCode !== 404; - const docFound = indexFound && body.found === true; - if (docFound) { + if (indexFound && isFoundGetResponse(body)) { if (!this.rawDocExistsInNamespace(body, namespace)) { throw SavedObjectsErrorHelpers.createConflictError(type, id); } @@ -1675,7 +1671,7 @@ export class SavedObjectsRepository { } const rawId = this._serializer.generateRawId(undefined, type, id); - const { body, statusCode } = await this.client.get>( + const { body, statusCode } = await this.client.get( { id: rawId, index: this.getIndexForType(type), @@ -1684,11 +1680,14 @@ export class SavedObjectsRepository { ); const indexFound = statusCode !== 404; - const docFound = indexFound && body.found === true; - if (!docFound || !this.rawDocExistsInNamespace(body, namespace)) { + if ( + !indexFound || + !isFoundGetResponse(body) || + !this.rawDocExistsInNamespace(body, namespace) + ) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } - return body as SavedObjectsRawDoc; + return body; } } @@ -1741,6 +1740,44 @@ function getSavedObjectNamespaces( return [SavedObjectsUtils.namespaceIdToString(namespace)]; } +/** + * Gets a saved object from a raw OpenSearch document. + * + * @param registry Registry which holds the registered saved object types information. + * @param type The type of the saved object. + * @param id The ID of the saved object. + * @param doc Doc contains _source and optional _seq_no and _primary_term. + * + * @internal + */ +function getSavedObjectFromSource( + registry: ISavedObjectTypeRegistry, + type: string, + id: string, + doc: { _seq_no?: number; _primary_term?: number; _source: SavedObjectsRawDocSource } +): SavedObject { + const { originId, updated_at: updatedAt } = doc._source; + + let namespaces: string[] = []; + if (!registry.isNamespaceAgnostic(type)) { + namespaces = doc._source.namespaces ?? [ + SavedObjectsUtils.namespaceIdToString(doc._source.namespace), + ]; + } + + return { + id, + type, + namespaces, + ...(originId && { originId }), + ...(updatedAt && { updated_at: updatedAt }), + version: encodeHitVersion(doc), + attributes: doc._source[type], + references: doc._source.references || [], + migrationVersion: doc._source.migrationVersion, + }; +} + /** * Ensure that a namespace is always in its namespace ID representation. * This allows `'default'` to be used interchangeably with `undefined`. @@ -1761,3 +1798,18 @@ const normalizeNamespace = (namespace?: string) => { const errorContent = (error: DecoratedError) => error.output.payload; const unique = (array: string[]) => [...new Set(array)]; + +/** + * Type and type guard function for converting a possibly not existant doc to an existant doc. + */ +type GetResponseFound = opensearchtypes.GetResponse & + Required< + Pick< + opensearchtypes.GetResponse, + '_primary_term' | '_seq_no' | '_version' | '_source' + > + >; + +const isFoundGetResponse = ( + doc: opensearchtypes.GetResponse +): doc is GetResponseFound => doc.found; diff --git a/src/core/server/saved_objects/service/lib/repository_opensearch_client.ts b/src/core/server/saved_objects/service/lib/repository_opensearch_client.ts index 9a9deefb4ae9..ad422e939a74 100644 --- a/src/core/server/saved_objects/service/lib/repository_opensearch_client.ts +++ b/src/core/server/saved_objects/service/lib/repository_opensearch_client.ts @@ -29,7 +29,7 @@ * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. */ -import type { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; +import type { TransportRequestOptions } from '@opensearch-project/opensearch/lib/Transport'; import { OpenSearchClient } from '../../../opensearch/'; import { retryCallCluster } from '../../../opensearch/client/retry_call_cluster'; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.test.ts b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.test.ts index 10038d532143..afef66e5a2f7 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.test.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.test.ts @@ -74,7 +74,7 @@ const MAPPINGS = { }, }, }, -}; +} as const; describe('searchDsl/getSortParams', () => { describe('type, no sortField', () => { diff --git a/src/core/server/saved_objects/version/encode_hit_version.ts b/src/core/server/saved_objects/version/encode_hit_version.ts index 4de5fc4dc99a..f82df69a8153 100644 --- a/src/core/server/saved_objects/version/encode_hit_version.ts +++ b/src/core/server/saved_objects/version/encode_hit_version.ts @@ -31,6 +31,6 @@ import { encodeVersion } from './encode_version'; * Helper for encoding a version from a "hit" (hits.hits[#] from _search) or * "doc" (body from GET, update, etc) object */ -export function encodeHitVersion(response: { _seq_no: number; _primary_term: number }) { +export function encodeHitVersion(response: { _seq_no?: number; _primary_term?: number }) { return encodeVersion(response._seq_no, response._primary_term); } diff --git a/src/core/server/saved_objects/version/encode_version.ts b/src/core/server/saved_objects/version/encode_version.ts index cb9a232dd8f7..c56fd6c9d818 100644 --- a/src/core/server/saved_objects/version/encode_version.ts +++ b/src/core/server/saved_objects/version/encode_version.ts @@ -32,7 +32,7 @@ import { encodeBase64 } from './base64'; * that can be used in the saved object API in place of numeric * version numbers */ -export function encodeVersion(seqNo: number, primaryTerm: number) { +export function encodeVersion(seqNo?: number, primaryTerm?: number) { if (!Number.isInteger(primaryTerm)) { throw new TypeError('_primary_term from opensearch must be an integer'); } diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 918b116ee2cf..6061f78557b5 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -4,7 +4,7 @@ ```ts -import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; +import { ApiResponse } from '@opensearch-project/opensearch/lib/Transport'; import Boom from '@hapi/boom'; import { BulkIndexDocumentsParams } from 'elasticsearch'; import { CatAliasesParams } from 'elasticsearch'; @@ -23,7 +23,7 @@ import { CatThreadPoolParams } from 'elasticsearch'; import { ClearScrollParams } from 'elasticsearch'; import { CliArgs } from '@osd/config'; import { Client } from 'elasticsearch'; -import { ClientOptions } from '@elastic/elasticsearch'; +import { ClientOptions } from '@opensearch-project/opensearch'; import { ClusterAllocationExplainParams } from 'elasticsearch'; import { ClusterGetSettingsParams } from 'elasticsearch'; import { ClusterHealthParams } from 'elasticsearch'; @@ -100,7 +100,7 @@ import { IngestDeletePipelineParams } from 'elasticsearch'; import { IngestGetPipelineParams } from 'elasticsearch'; import { IngestPutPipelineParams } from 'elasticsearch'; import { IngestSimulateParams } from 'elasticsearch'; -import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import { OpenSearchDashboardsClient } from '@opensearch-project/opensearch/api/opensearch_dashboards'; import { Logger } from '@osd/logging'; import { LoggerFactory } from '@osd/logging'; import { LogLevel } from '@osd/logging'; @@ -155,9 +155,9 @@ import { TasksCancelParams } from 'elasticsearch'; import { TasksGetParams } from 'elasticsearch'; import { TasksListParams } from 'elasticsearch'; import { TermvectorsParams } from 'elasticsearch'; -import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import { TransportRequestOptions } from '@opensearch-project/opensearch/lib/Transport'; +import { TransportRequestParams } from '@opensearch-project/opensearch/lib/Transport'; +import { TransportRequestPromise } from '@opensearch-project/opensearch/lib/Transport'; import { Type } from '@osd/config-schema'; import { TypeOf } from '@osd/config-schema'; import { UpdateDocumentByQueryParams } from 'elasticsearch'; @@ -1414,7 +1414,7 @@ export interface OnPreRoutingToolkit { } // @public -export type OpenSearchClient = Omit & { +export type OpenSearchClient = Omit & { transport: { request(params: TransportRequestParams, options?: TransportRequestOptions): TransportRequestPromise; }; @@ -2060,38 +2060,6 @@ export interface SavedObjectsClientWrapperOptions { typeRegistry: ISavedObjectTypeRegistry; } -// @public -export interface SavedObjectsComplexFieldMapping { - // (undocumented) - doc_values?: boolean; - dynamic?: false | 'strict'; - // (undocumented) - enabled?: boolean; - // (undocumented) - properties: SavedObjectsMappingProperties; - // (undocumented) - type?: string; -} - -// @public -export interface SavedObjectsCoreFieldMapping { - // (undocumented) - doc_values?: boolean; - // (undocumented) - fields?: { - [subfield: string]: { - type: string; - ignore_above?: number; - }; - }; - // (undocumented) - index?: boolean; - // (undocumented) - null_value?: number | boolean | string; - // (undocumented) - type: string; -} - // @public (undocumented) export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions { id?: string; @@ -2210,7 +2178,9 @@ export interface SavedObjectsExportResultDetails { } // @public -export type SavedObjectsFieldMapping = SavedObjectsCoreFieldMapping | SavedObjectsComplexFieldMapping; +export type SavedObjectsFieldMapping = opensearchtypes.MappingProperty & { + dynamic?: false | 'strict'; +}; // @public (undocumented) export interface SavedObjectsFindOptions { diff --git a/src/plugins/data/common/search/opensearch_search/types.ts b/src/plugins/data/common/search/opensearch_search/types.ts index 355a3bf0acf9..45507e4b731e 100644 --- a/src/plugins/data/common/search/opensearch_search/types.ts +++ b/src/plugins/data/common/search/opensearch_search/types.ts @@ -30,7 +30,7 @@ * GitHub history for details. */ import { SearchResponse } from 'elasticsearch'; -import { Search } from '@elastic/elasticsearch/api/requestParams'; +import { Search } from '@opensearch-project/opensearch/api/requestParams'; import { IOpenSearchDashboardsSearchRequest, IOpenSearchDashboardsSearchResponse } from '../types'; export const OPENSEARCH_SEARCH_STRATEGY = 'opensearch'; diff --git a/src/plugins/data/common/search/search_source/legacy/types.ts b/src/plugins/data/common/search/search_source/legacy/types.ts index ccc6d87602e0..34c5b02b3480 100644 --- a/src/plugins/data/common/search/search_source/legacy/types.ts +++ b/src/plugins/data/common/search/search_source/legacy/types.ts @@ -31,7 +31,7 @@ */ import { BehaviorSubject } from 'rxjs'; -import { ApiResponse } from '@elastic/elasticsearch'; +import { ApiResponse } from '@opensearch-project/opensearch'; import { SearchResponse } from 'elasticsearch'; import { FetchHandlers, SearchRequest } from '../fetch'; diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index e726f72c70db..0c805b558063 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -6,8 +6,8 @@ import { $Values } from '@osd/utility-types'; import { Action } from 'history'; -import { ApiResponse } from '@elastic/elasticsearch'; -import { ApiResponse as ApiResponse_2 } from '@elastic/elasticsearch/lib/Transport'; +import { ApiResponse } from '@opensearch-project/opensearch'; +import { ApiResponse as ApiResponse_2 } from '@opensearch-project/opensearch/lib/Transport'; import { ApplicationStart } from 'opensearch-dashboards/public'; import { Assign } from '@osd/utility-types'; import { BehaviorSubject } from 'rxjs'; @@ -35,7 +35,7 @@ import { ISearchOptions as ISearchOptions_2 } from 'src/plugins/data/public'; import { ISearchSource as ISearchSource_2 } from 'src/plugins/data/public'; import { IStorageWrapper } from 'src/plugins/opensearch_dashboards_utils/public'; import { IUiSettingsClient } from 'src/core/public'; -import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import { OpenSearchDashboardsClient } from '@opensearch-project/opensearch/api/opensearch_dashboards'; import { Location } from 'history'; import { LocationDescriptorObject } from 'history'; import { Logger } from '@osd/logging'; @@ -66,14 +66,14 @@ import { SavedObject } from 'src/core/server'; import { SavedObject as SavedObject_2 } from 'src/core/public'; import { SavedObjectReference as SavedObjectReference_2 } from 'src/core/types'; import { SavedObjectsClientContract } from 'src/core/public'; -import { Search } from '@elastic/elasticsearch/api/requestParams'; +import { Search } from '@opensearch-project/opensearch/api/requestParams'; import { SearchResponse } from 'elasticsearch'; import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common'; import { ToastInputFields } from 'src/core/public/notifications'; import { ToastsSetup } from 'opensearch-dashboards/public'; -import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import { TransportRequestOptions } from '@opensearch-project/opensearch/lib/Transport'; +import { TransportRequestParams } from '@opensearch-project/opensearch/lib/Transport'; +import { TransportRequestPromise } from '@opensearch-project/opensearch/lib/Transport'; import { TypeOf } from '@osd/config-schema'; import { UiActionsSetup } from 'src/plugins/ui_actions/public'; import { UiActionsStart } from 'src/plugins/ui_actions/public'; diff --git a/src/plugins/data/server/search/opensearch_search/opensearch_search_strategy.ts b/src/plugins/data/server/search/opensearch_search/opensearch_search_strategy.ts index 852742abb989..1c0891b11209 100644 --- a/src/plugins/data/server/search/opensearch_search/opensearch_search_strategy.ts +++ b/src/plugins/data/server/search/opensearch_search/opensearch_search_strategy.ts @@ -33,7 +33,7 @@ import { first } from 'rxjs/operators'; import { SharedGlobalConfig, Logger } from 'opensearch-dashboards/server'; import { SearchResponse } from 'elasticsearch'; import { Observable } from 'rxjs'; -import { ApiResponse } from '@elastic/elasticsearch'; +import { ApiResponse } from '@opensearch-project/opensearch'; import { SearchUsage } from '../collectors/usage'; import { toSnakeCase } from './to_snake_case'; import { diff --git a/src/plugins/data/server/search/opensearch_search/shim_abort_signal.ts b/src/plugins/data/server/search/opensearch_search/shim_abort_signal.ts index b35b29c7147e..cc35986fe37a 100644 --- a/src/plugins/data/server/search/opensearch_search/shim_abort_signal.ts +++ b/src/plugins/data/server/search/opensearch_search/shim_abort_signal.ts @@ -30,7 +30,7 @@ * GitHub history for details. */ -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import { TransportRequestPromise } from '@opensearch-project/opensearch/lib/Transport'; /** * diff --git a/src/plugins/data/server/search/routes/call_msearch.ts b/src/plugins/data/server/search/routes/call_msearch.ts index 19797f7f0272..06cdee7a0730 100644 --- a/src/plugins/data/server/search/routes/call_msearch.ts +++ b/src/plugins/data/server/search/routes/call_msearch.ts @@ -32,7 +32,7 @@ import { Observable } from 'rxjs'; import { first } from 'rxjs/operators'; -import { ApiResponse } from '@elastic/elasticsearch'; +import { ApiResponse } from '@opensearch-project/opensearch'; import { SearchResponse } from 'elasticsearch'; import { IUiSettingsClient, IScopedClusterClient, SharedGlobalConfig } from 'src/core/server'; diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 2c066808b3db..cfa4b319cbfb 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -5,7 +5,7 @@ ```ts import { $Values } from '@osd/utility-types'; -import { ApiResponse } from '@elastic/elasticsearch'; +import { ApiResponse } from '@opensearch-project/opensearch'; import { Assign } from '@osd/utility-types'; import { BehaviorSubject } from 'rxjs'; import { ConfigDeprecationProvider } from '@osd/config'; @@ -42,12 +42,12 @@ import { RequestHandlerContext } from 'src/core/server'; import { RequestStatistics } from 'src/plugins/inspector/common'; import { SavedObject } from 'src/core/server'; import { SavedObjectsClientContract } from 'src/core/server'; -import { Search } from '@elastic/elasticsearch/api/requestParams'; +import { Search } from '@opensearch-project/opensearch/api/requestParams'; import { SearchResponse } from 'elasticsearch'; import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common'; import { ShardsResponse } from 'elasticsearch'; import { ToastInputFields } from 'src/core/public/notifications'; -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import { TransportRequestPromise } from '@opensearch-project/opensearch/lib/Transport'; import { Type } from '@osd/config-schema'; import { TypeOf } from '@osd/config-schema'; import { Unit } from '@elastic/datemath'; diff --git a/src/plugins/embeddable/public/public.api.md b/src/plugins/embeddable/public/public.api.md index 4406dded9854..607652e77a4a 100644 --- a/src/plugins/embeddable/public/public.api.md +++ b/src/plugins/embeddable/public/public.api.md @@ -7,8 +7,8 @@ import { Action } from 'history'; import { Action as Action_3 } from 'src/plugins/ui_actions/public'; import { ActionExecutionContext as ActionExecutionContext_2 } from 'src/plugins/ui_actions/public'; -import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; -import { ApiResponse as ApiResponse_2 } from '@elastic/elasticsearch'; +import { ApiResponse } from '@opensearch-project/opensearch/lib/Transport'; +import { ApiResponse as ApiResponse_2 } from '@opensearch-project/opensearch'; import { ApplicationStart as ApplicationStart_2 } from 'kibana/public'; import { Assign } from '@kbn/utility-types'; import { BehaviorSubject } from 'rxjs'; @@ -38,7 +38,7 @@ import { ISearchOptions } from 'src/plugins/data/public'; import { ISearchSource } from 'src/plugins/data/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { IUiSettingsClient as IUiSettingsClient_2 } from 'src/core/public'; -import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import { OpenSearchDashboardsClient } from '@opensearch-project/opensearch/api/opensearch_dashboards'; import { KibanaConfigType } from 'src/core/server/kibana_config'; import { Location } from 'history'; import { LocationDescriptorObject } from 'history'; @@ -67,7 +67,7 @@ import { SavedObjectAttributes } from 'kibana/server'; import { SavedObjectAttributes as SavedObjectAttributes_2 } from 'src/core/public'; import { SavedObjectAttributes as SavedObjectAttributes_3 } from 'kibana/public'; import { SavedObjectsClientContract as SavedObjectsClientContract_3 } from 'src/core/public'; -import { Search } from '@elastic/elasticsearch/api/requestParams'; +import { Search } from '@opensearch-project/opensearch/api/requestParams'; import { SearchResponse } from 'elasticsearch'; import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common'; import { ShallowPromise } from '@kbn/utility-types'; @@ -75,9 +75,9 @@ import { SimpleSavedObject as SimpleSavedObject_2 } from 'src/core/public'; import { Start as Start_2 } from 'src/plugins/inspector/public'; import { ToastInputFields as ToastInputFields_2 } from 'src/core/public/notifications'; import { ToastsSetup as ToastsSetup_2 } from 'kibana/public'; -import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import { TransportRequestOptions } from '@opensearch-project/opensearch/lib/Transport'; +import { TransportRequestParams } from '@opensearch-project/opensearch/lib/Transport'; +import { TransportRequestPromise } from '@opensearch-project/opensearch/lib/Transport'; import { TypeOf } from '@kbn/config-schema'; import { UiComponent } from 'src/plugins/kibana_utils/public'; import { UnregisterCallback } from 'history'; diff --git a/test/common/services/opensearch.ts b/test/common/services/opensearch.ts index dbf287e63747..de7b03172d9b 100644 --- a/test/common/services/opensearch.ts +++ b/test/common/services/opensearch.ts @@ -32,7 +32,7 @@ import { format as formatUrl } from 'url'; import fs from 'fs'; -import { Client } from '@elastic/elasticsearch'; +import { Client } from '@opensearch-project/opensearch'; import { CA_CERT_PATH } from '@osd/dev-utils'; import { FtrProviderContext } from '../ftr_provider_context'; diff --git a/tsconfig.base.json b/tsconfig.base.json index bda8cd8363e7..a29e73f27e89 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -10,7 +10,8 @@ "test_utils/*": [ "src/test_utils/public/*" ], - "fixtures/*": ["src/fixtures/*"] + "fixtures/*": ["src/fixtures/*"], + "@opensearch-project/opensearch": ["node_modules/@opensearch-project/opensearch/api/new"] }, // Support .tsx files and transform JSX into calls to React.createElement "jsx": "react", diff --git a/yarn.lock b/yarn.lock index b4f74aca8a58..25209c226dde 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1083,18 +1083,6 @@ dependencies: tslib "^1.9.3" -"@elastic/elasticsearch@7.10.0-rc.1": - version "7.10.0-rc.1" - resolved "https://registry.yarnpkg.com/@elastic/elasticsearch/-/elasticsearch-7.10.0-rc.1.tgz#c23fc5cbfdb40cf2ce6f9cd796b75940e8c9dc8a" - integrity sha512-STaBlEwYbT8yT3HJ+mbO1kx+Kb7Ft7Q0xG5GxZbqbAJ7PZvgGgJWwN7jUg4oKJHbTfxV3lPvFa+PaUK2TqGuYg== - dependencies: - debug "^4.1.1" - decompress-response "^4.2.0" - hpagent "^0.1.1" - ms "^2.1.1" - pump "^3.0.0" - secure-json-parse "^2.1.0" - "@elastic/ems-client@7.10.0": version "7.10.0" resolved "https://registry.yarnpkg.com/@elastic/ems-client/-/ems-client-7.10.0.tgz#6d0e12ce99acd122d8066aa0a8685ecfd21637d3" @@ -2213,6 +2201,16 @@ universal-user-agent "^2.0.0" url-template "^2.0.8" +"@opensearch-project/opensearch@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@opensearch-project/opensearch/-/opensearch-1.0.2.tgz#b5946bcd2b6b655b4ae8fbb4562411cf283a7503" + integrity sha512-gQ2CjbS7/pJ4A3IBWd+AD0KbCaAnE1Ur9baRxqM1NMH/7A8GQxwtVxx8raUOf4HZExkZZOUYBMzJgWM1OyELyw== + dependencies: + debug "^4.3.1" + hpagent "^0.1.1" + ms "^2.1.3" + secure-json-parse "^2.4.0" + "@percy/cli-build@1.0.0-beta.74": version "1.0.0-beta.74" resolved "https://registry.yarnpkg.com/@percy/cli-build/-/cli-build-1.0.0-beta.74.tgz#228208ce21bd8c2fa663ebfcaad79a27b57f776e" @@ -6881,7 +6879,7 @@ debug@3.X, debug@^3.1.0, debug@^3.1.1, debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@4, debug@^4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3: +debug@4, debug@^4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== @@ -6930,13 +6928,6 @@ decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" -decompress-response@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.0.tgz#805ca9d1d3cdf17a03951475ad6cdc93115cec3f" - integrity sha512-MHebOkORCgLW1ramLri5vzfR4r7HgXXrVkVr/eaPVRCtYWFUp9hNAuqsBxhpABbpqd7zY2IrjxXfTuaVrW0Z2A== - dependencies: - mimic-response "^2.0.0" - decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" @@ -13240,11 +13231,6 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== -mimic-response@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" - integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== - mimic-response@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" @@ -13508,7 +13494,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3: +ms@2.1.3, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -16666,10 +16652,10 @@ scss-tokenizer@^0.2.3: js-base64 "^2.1.8" source-map "^0.4.2" -secure-json-parse@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.1.0.tgz#ae76f5624256b5c497af887090a5d9e156c9fb20" - integrity sha512-GckO+MS/wT4UogDyoI/H/S1L0MCcKS1XX/vp48wfmU7Nw4woBmb8mIpu4zPBQjKlRT88/bt9xdoV4111jPpNJA== +secure-json-parse@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.4.0.tgz#5aaeaaef85c7a417f76271a4f5b0cc3315ddca85" + integrity sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg== select-hose@^2.0.0: version "2.0.0"