diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index 7f671d9edcd867..1db3bd31bbc9b9 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -114,7 +114,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectsFindResponsePublic](./kibana-plugin-core-public.savedobjectsfindresponsepublic.md) | Return type of the Saved Objects find() method.\*Note\*: this type is different between the Public and Server Saved Objects clients. | | [SavedObjectsImportAmbiguousConflictError](./kibana-plugin-core-public.savedobjectsimportambiguousconflicterror.md) | Represents a failure to import due to a conflict, which can be resolved in different ways with an overwrite. | | [SavedObjectsImportConflictError](./kibana-plugin-core-public.savedobjectsimportconflicterror.md) | Represents a failure to import due to a conflict. | -| [SavedObjectsImportError](./kibana-plugin-core-public.savedobjectsimporterror.md) | Represents a failure to import. | +| [SavedObjectsImportFailure](./kibana-plugin-core-public.savedobjectsimportfailure.md) | Represents a failure to import. | | [SavedObjectsImportMissingReferencesError](./kibana-plugin-core-public.savedobjectsimportmissingreferenceserror.md) | Represents a failure to import due to missing references. | | [SavedObjectsImportResponse](./kibana-plugin-core-public.savedobjectsimportresponse.md) | The response describing the result of an import. | | [SavedObjectsImportRetry](./kibana-plugin-core-public.savedobjectsimportretry.md) | Describes a retry operation for importing a saved object. | diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.id.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.id.md deleted file mode 100644 index 72b9c86348f2e5..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.id.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportError](./kibana-plugin-core-public.savedobjectsimporterror.md) > [id](./kibana-plugin-core-public.savedobjectsimporterror.id.md) - -## SavedObjectsImportError.id property - -Signature: - -```typescript -id: string; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.md deleted file mode 100644 index e12396e9fa7b9d..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.md +++ /dev/null @@ -1,25 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportError](./kibana-plugin-core-public.savedobjectsimporterror.md) - -## SavedObjectsImportError interface - -Represents a failure to import. - -Signature: - -```typescript -export interface SavedObjectsImportError -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [error](./kibana-plugin-core-public.savedobjectsimporterror.error.md) | SavedObjectsImportConflictError | SavedObjectsImportAmbiguousConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError | | -| [id](./kibana-plugin-core-public.savedobjectsimporterror.id.md) | string | | -| [meta](./kibana-plugin-core-public.savedobjectsimporterror.meta.md) | {
title?: string;
icon?: string;
} | | -| [overwrite](./kibana-plugin-core-public.savedobjectsimporterror.overwrite.md) | boolean | If overwrite is specified, an attempt was made to overwrite an existing object. | -| [title](./kibana-plugin-core-public.savedobjectsimporterror.title.md) | string | | -| [type](./kibana-plugin-core-public.savedobjectsimporterror.type.md) | string | | - diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.type.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.type.md deleted file mode 100644 index fee537160a2ad1..00000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.type.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportError](./kibana-plugin-core-public.savedobjectsimporterror.md) > [type](./kibana-plugin-core-public.savedobjectsimporterror.type.md) - -## SavedObjectsImportError.type property - -Signature: - -```typescript -type: string; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.error.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.error.md similarity index 62% rename from docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.error.md rename to docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.error.md index 201f56bf925d1d..16628e83b8af9d 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.error.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.error.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportError](./kibana-plugin-core-public.savedobjectsimporterror.md) > [error](./kibana-plugin-core-public.savedobjectsimporterror.error.md) +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportFailure](./kibana-plugin-core-public.savedobjectsimportfailure.md) > [error](./kibana-plugin-core-public.savedobjectsimportfailure.error.md) -## SavedObjectsImportError.error property +## SavedObjectsImportFailure.error property Signature: diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.id.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.id.md new file mode 100644 index 00000000000000..2279241083241e --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportFailure](./kibana-plugin-core-public.savedobjectsimportfailure.md) > [id](./kibana-plugin-core-public.savedobjectsimportfailure.id.md) + +## SavedObjectsImportFailure.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.md new file mode 100644 index 00000000000000..f9219c9037e0a2 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportFailure](./kibana-plugin-core-public.savedobjectsimportfailure.md) + +## SavedObjectsImportFailure interface + +Represents a failure to import. + +Signature: + +```typescript +export interface SavedObjectsImportFailure +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [error](./kibana-plugin-core-public.savedobjectsimportfailure.error.md) | SavedObjectsImportConflictError | SavedObjectsImportAmbiguousConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError | | +| [id](./kibana-plugin-core-public.savedobjectsimportfailure.id.md) | string | | +| [meta](./kibana-plugin-core-public.savedobjectsimportfailure.meta.md) | {
title?: string;
icon?: string;
} | | +| [overwrite](./kibana-plugin-core-public.savedobjectsimportfailure.overwrite.md) | boolean | If overwrite is specified, an attempt was made to overwrite an existing object. | +| [title](./kibana-plugin-core-public.savedobjectsimportfailure.title.md) | string | | +| [type](./kibana-plugin-core-public.savedobjectsimportfailure.type.md) | string | | + diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.meta.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.meta.md similarity index 51% rename from docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.meta.md rename to docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.meta.md index 97bf3c4cff8eb0..4ea9455098035f 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.meta.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.meta.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportError](./kibana-plugin-core-public.savedobjectsimporterror.md) > [meta](./kibana-plugin-core-public.savedobjectsimporterror.meta.md) +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportFailure](./kibana-plugin-core-public.savedobjectsimportfailure.md) > [meta](./kibana-plugin-core-public.savedobjectsimportfailure.meta.md) -## SavedObjectsImportError.meta property +## SavedObjectsImportFailure.meta property Signature: diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.overwrite.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.overwrite.md similarity index 54% rename from docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.overwrite.md rename to docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.overwrite.md index 69a8726b0588a5..579a16697b4066 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.overwrite.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.overwrite.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportError](./kibana-plugin-core-public.savedobjectsimporterror.md) > [overwrite](./kibana-plugin-core-public.savedobjectsimporterror.overwrite.md) +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportFailure](./kibana-plugin-core-public.savedobjectsimportfailure.md) > [overwrite](./kibana-plugin-core-public.savedobjectsimportfailure.overwrite.md) -## SavedObjectsImportError.overwrite property +## SavedObjectsImportFailure.overwrite property If `overwrite` is specified, an attempt was made to overwrite an existing object. diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.title.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.title.md similarity index 53% rename from docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.title.md rename to docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.title.md index 95eeaaedf94c59..0024358bda0308 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimporterror.title.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.title.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportError](./kibana-plugin-core-public.savedobjectsimporterror.md) > [title](./kibana-plugin-core-public.savedobjectsimporterror.title.md) +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportFailure](./kibana-plugin-core-public.savedobjectsimportfailure.md) > [title](./kibana-plugin-core-public.savedobjectsimportfailure.title.md) -## SavedObjectsImportError.title property +## SavedObjectsImportFailure.title property > Warning: This API is now obsolete. > diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.type.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.type.md new file mode 100644 index 00000000000000..68411093a92cea --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportfailure.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [SavedObjectsImportFailure](./kibana-plugin-core-public.savedobjectsimportfailure.md) > [type](./kibana-plugin-core-public.savedobjectsimportfailure.type.md) + +## SavedObjectsImportFailure.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportresponse.errors.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportresponse.errors.md index 95c831420f3f32..073eac20b04ace 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportresponse.errors.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportresponse.errors.md @@ -7,5 +7,5 @@ Signature: ```typescript -errors?: SavedObjectsImportError[]; +errors?: SavedObjectsImportFailure[]; ``` diff --git a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportresponse.md b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportresponse.md index 0aba4d517e43ab..2c0b691c9d66ea 100644 --- a/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportresponse.md +++ b/docs/development/core/public/kibana-plugin-core-public.savedobjectsimportresponse.md @@ -16,7 +16,7 @@ export interface SavedObjectsImportResponse | Property | Type | Description | | --- | --- | --- | -| [errors](./kibana-plugin-core-public.savedobjectsimportresponse.errors.md) | SavedObjectsImportError[] | | +| [errors](./kibana-plugin-core-public.savedobjectsimportresponse.errors.md) | SavedObjectsImportFailure[] | | | [success](./kibana-plugin-core-public.savedobjectsimportresponse.success.md) | boolean | | | [successCount](./kibana-plugin-core-public.savedobjectsimportresponse.successcount.md) | number | | | [successResults](./kibana-plugin-core-public.savedobjectsimportresponse.successresults.md) | SavedObjectsImportSuccess[] | | diff --git a/docs/development/core/server/kibana-plugin-core-server.exportsavedobjectstostream.md b/docs/development/core/server/kibana-plugin-core-server.exportsavedobjectstostream.md deleted file mode 100644 index f8b5eb3b353932..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.exportsavedobjectstostream.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [exportSavedObjectsToStream](./kibana-plugin-core-server.exportsavedobjectstostream.md) - -## exportSavedObjectsToStream() function - -Generates sorted saved object stream to be used for export. See the [options](./kibana-plugin-core-server.savedobjectsexportoptions.md) for more detailed information. - -Signature: - -```typescript -export declare function exportSavedObjectsToStream({ types, hasReference, objects, search, savedObjectsClient, exportSizeLimit, includeReferencesDeep, excludeExportDetails, namespace, }: SavedObjectsExportOptions): Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| { types, hasReference, objects, search, savedObjectsClient, exportSizeLimit, includeReferencesDeep, excludeExportDetails, namespace, } | SavedObjectsExportOptions | | - -Returns: - -`Promise` - diff --git a/docs/development/core/server/kibana-plugin-core-server.importsavedobjectsfromstream.md b/docs/development/core/server/kibana-plugin-core-server.importsavedobjectsfromstream.md deleted file mode 100644 index cebebbaf94fe68..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.importsavedobjectsfromstream.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [importSavedObjectsFromStream](./kibana-plugin-core-server.importsavedobjectsfromstream.md) - -## importSavedObjectsFromStream() function - -Import saved objects from given stream. See the [options](./kibana-plugin-core-server.savedobjectsimportoptions.md) for more detailed information. - -Signature: - -```typescript -export declare function importSavedObjectsFromStream({ readStream, objectLimit, overwrite, createNewCopies, savedObjectsClient, typeRegistry, namespace, }: SavedObjectsImportOptions): Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| { readStream, objectLimit, overwrite, createNewCopies, savedObjectsClient, typeRegistry, namespace, } | SavedObjectsImportOptions | | - -Returns: - -`Promise` - diff --git a/docs/development/core/server/kibana-plugin-core-server.isavedobjectsexporter.md b/docs/development/core/server/kibana-plugin-core-server.isavedobjectsexporter.md new file mode 100644 index 00000000000000..5c7385ea663d3f --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.isavedobjectsexporter.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ISavedObjectsExporter](./kibana-plugin-core-server.isavedobjectsexporter.md) + +## ISavedObjectsExporter type + + +Signature: + +```typescript +export declare type ISavedObjectsExporter = PublicMethodsOf; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.isavedobjectsimporter.md b/docs/development/core/server/kibana-plugin-core-server.isavedobjectsimporter.md new file mode 100644 index 00000000000000..b6bfe8de31895f --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.isavedobjectsimporter.md @@ -0,0 +1,12 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ISavedObjectsImporter](./kibana-plugin-core-server.isavedobjectsimporter.md) + +## ISavedObjectsImporter type + + +Signature: + +```typescript +export declare type ISavedObjectsImporter = PublicMethodsOf; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index 269db90c4db9bd..36da1b51ee7b09 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -26,6 +26,10 @@ The plugin integrates with the core system via lifecycle events: `setup` | [RouteValidationError](./kibana-plugin-core-server.routevalidationerror.md) | Error to return when the validation is not successful. | | [SavedObjectsClient](./kibana-plugin-core-server.savedobjectsclient.md) | | | [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) | | +| [SavedObjectsExporter](./kibana-plugin-core-server.savedobjectsexporter.md) | | +| [SavedObjectsExportError](./kibana-plugin-core-server.savedobjectsexporterror.md) | | +| [SavedObjectsImporter](./kibana-plugin-core-server.savedobjectsimporter.md) | | +| [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) | | | [SavedObjectsRepository](./kibana-plugin-core-server.savedobjectsrepository.md) | | | [SavedObjectsSerializer](./kibana-plugin-core-server.savedobjectsserializer.md) | A serializer that can be used to manually convert [raw](./kibana-plugin-core-server.savedobjectsrawdoc.md) or [sanitized](./kibana-plugin-core-server.savedobjectsanitizeddoc.md) documents to the other kind. | | [SavedObjectsUtils](./kibana-plugin-core-server.savedobjectsutils.md) | | @@ -38,14 +42,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [AuthResultType](./kibana-plugin-core-server.authresulttype.md) | | | [AuthStatus](./kibana-plugin-core-server.authstatus.md) | Status indicating an outcome of the authentication. | -## Functions - -| Function | Description | -| --- | --- | -| [exportSavedObjectsToStream({ types, hasReference, objects, search, savedObjectsClient, exportSizeLimit, includeReferencesDeep, excludeExportDetails, namespace, })](./kibana-plugin-core-server.exportsavedobjectstostream.md) | Generates sorted saved object stream to be used for export. See the [options](./kibana-plugin-core-server.savedobjectsexportoptions.md) for more detailed information. | -| [importSavedObjectsFromStream({ readStream, objectLimit, overwrite, createNewCopies, savedObjectsClient, typeRegistry, namespace, })](./kibana-plugin-core-server.importsavedobjectsfromstream.md) | Import saved objects from given stream. See the [options](./kibana-plugin-core-server.savedobjectsimportoptions.md) for more detailed information. | -| [resolveSavedObjectsImportErrors({ readStream, objectLimit, retries, savedObjectsClient, typeRegistry, namespace, createNewCopies, })](./kibana-plugin-core-server.resolvesavedobjectsimporterrors.md) | Resolve and return saved object import errors. See the [options](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) for more detailed informations. | - ## Interfaces | Interface | Description | @@ -140,6 +136,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [RouteValidatorOptions](./kibana-plugin-core-server.routevalidatoroptions.md) | Additional options for the RouteValidator class to modify its default behaviour. | | [SavedObject](./kibana-plugin-core-server.savedobject.md) | | | [SavedObjectAttributes](./kibana-plugin-core-server.savedobjectattributes.md) | The data for a Saved Object is stored as an object in the attributes property. | +| [SavedObjectExportBaseOptions](./kibana-plugin-core-server.savedobjectexportbaseoptions.md) | | | [SavedObjectMigrationContext](./kibana-plugin-core-server.savedobjectmigrationcontext.md) | Migration context provided when invoking a [migration handler](./kibana-plugin-core-server.savedobjectmigrationfn.md) | | [SavedObjectMigrationMap](./kibana-plugin-core-server.savedobjectmigrationmap.md) | A map of [migration functions](./kibana-plugin-core-server.savedobjectmigrationfn.md) to be used for a given type. The map's keys must be valid semver versions.For a given document, only migrations with a higher version number than that of the document will be applied. Migrations are executed in order, starting from the lowest version and ending with the highest one. | | [SavedObjectReference](./kibana-plugin-core-server.savedobjectreference.md) | A reference to another saved object. | @@ -163,7 +160,8 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectsDeleteFromNamespacesOptions](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesoptions.md) | | | [SavedObjectsDeleteFromNamespacesResponse](./kibana-plugin-core-server.savedobjectsdeletefromnamespacesresponse.md) | | | [SavedObjectsDeleteOptions](./kibana-plugin-core-server.savedobjectsdeleteoptions.md) | | -| [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) | Options controlling the export operation. | +| [SavedObjectsExportByObjectOptions](./kibana-plugin-core-server.savedobjectsexportbyobjectoptions.md) | Options for the [export by objects API](./kibana-plugin-core-server.savedobjectsexporter.exportbyobjects.md) | +| [SavedObjectsExportByTypeOptions](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.md) | Options for the [export by type API](./kibana-plugin-core-server.savedobjectsexporter.exportbytypes.md) | | [SavedObjectsExportResultDetails](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) | Structure of the export result details entry | | [SavedObjectsFindOptions](./kibana-plugin-core-server.savedobjectsfindoptions.md) | | | [SavedObjectsFindOptionsReference](./kibana-plugin-core-server.savedobjectsfindoptionsreference.md) | | @@ -171,7 +169,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectsFindResult](./kibana-plugin-core-server.savedobjectsfindresult.md) | | | [SavedObjectsImportAmbiguousConflictError](./kibana-plugin-core-server.savedobjectsimportambiguousconflicterror.md) | Represents a failure to import due to a conflict, which can be resolved in different ways with an overwrite. | | [SavedObjectsImportConflictError](./kibana-plugin-core-server.savedobjectsimportconflicterror.md) | Represents a failure to import due to a conflict. | -| [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) | Represents a failure to import. | +| [SavedObjectsImportFailure](./kibana-plugin-core-server.savedobjectsimportfailure.md) | Represents a failure to import. | | [SavedObjectsImportMissingReferencesError](./kibana-plugin-core-server.savedobjectsimportmissingreferenceserror.md) | Represents a failure to import due to missing references. | | [SavedObjectsImportOptions](./kibana-plugin-core-server.savedobjectsimportoptions.md) | Options to control the import operation. | | [SavedObjectsImportResponse](./kibana-plugin-core-server.savedobjectsimportresponse.md) | The response describing the result of an import. | @@ -249,6 +247,8 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ILegacyCustomClusterClient](./kibana-plugin-core-server.ilegacycustomclusterclient.md) | Represents an Elasticsearch cluster API client created by a plugin. It allows to call API on behalf of the internal Kibana user and the actual user that is derived from the request headers (via asScoped(...)).See [LegacyClusterClient](./kibana-plugin-core-server.legacyclusterclient.md). | | [ILegacyScopedClusterClient](./kibana-plugin-core-server.ilegacyscopedclusterclient.md) | Serves the same purpose as "normal" ClusterClient but exposes additional callAsCurrentUser method that doesn't use credentials of the Kibana internal user (as callAsInternalUser does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API.See [LegacyScopedClusterClient](./kibana-plugin-core-server.legacyscopedclusterclient.md). | | [IsAuthenticated](./kibana-plugin-core-server.isauthenticated.md) | Returns authentication status for a request. | +| [ISavedObjectsExporter](./kibana-plugin-core-server.isavedobjectsexporter.md) | | +| [ISavedObjectsImporter](./kibana-plugin-core-server.isavedobjectsimporter.md) | | | [ISavedObjectsRepository](./kibana-plugin-core-server.isavedobjectsrepository.md) | See [SavedObjectsRepository](./kibana-plugin-core-server.savedobjectsrepository.md) | | [ISavedObjectTypeRegistry](./kibana-plugin-core-server.isavedobjecttyperegistry.md) | See [SavedObjectTypeRegistry](./kibana-plugin-core-server.savedobjecttyperegistry.md) for documentation. | | [KibanaRequestRouteOptions](./kibana-plugin-core-server.kibanarequestrouteoptions.md) | Route options: If 'GET' or 'OPTIONS' method, body options won't be returned. | diff --git a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md index b195e979891624..3a5e84ffdc3724 100644 --- a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md +++ b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.core.md @@ -11,6 +11,8 @@ core: { savedObjects: { client: SavedObjectsClientContract; typeRegistry: ISavedObjectTypeRegistry; + exporter: ISavedObjectsExporter; + importer: ISavedObjectsImporter; }; elasticsearch: { client: IScopedClusterClient; diff --git a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md index 1de7313f2c40e4..5300c85cf94064 100644 --- a/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md +++ b/docs/development/core/server/kibana-plugin-core-server.requesthandlercontext.md @@ -18,5 +18,5 @@ export interface RequestHandlerContext | Property | Type | Description | | --- | --- | --- | -| [core](./kibana-plugin-core-server.requesthandlercontext.core.md) | {
savedObjects: {
client: SavedObjectsClientContract;
typeRegistry: ISavedObjectTypeRegistry;
};
elasticsearch: {
client: IScopedClusterClient;
legacy: {
client: ILegacyScopedClusterClient;
};
};
uiSettings: {
client: IUiSettingsClient;
};
} | | +| [core](./kibana-plugin-core-server.requesthandlercontext.core.md) | {
savedObjects: {
client: SavedObjectsClientContract;
typeRegistry: ISavedObjectTypeRegistry;
exporter: ISavedObjectsExporter;
importer: ISavedObjectsImporter;
};
elasticsearch: {
client: IScopedClusterClient;
legacy: {
client: ILegacyScopedClusterClient;
};
};
uiSettings: {
client: IUiSettingsClient;
};
} | | diff --git a/docs/development/core/server/kibana-plugin-core-server.resolvesavedobjectsimporterrors.md b/docs/development/core/server/kibana-plugin-core-server.resolvesavedobjectsimporterrors.md deleted file mode 100644 index a2255613e0f6c4..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.resolvesavedobjectsimporterrors.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [resolveSavedObjectsImportErrors](./kibana-plugin-core-server.resolvesavedobjectsimporterrors.md) - -## resolveSavedObjectsImportErrors() function - -Resolve and return saved object import errors. See the [options](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) for more detailed informations. - -Signature: - -```typescript -export declare function resolveSavedObjectsImportErrors({ readStream, objectLimit, retries, savedObjectsClient, typeRegistry, namespace, createNewCopies, }: SavedObjectsResolveImportErrorsOptions): Promise; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| { readStream, objectLimit, retries, savedObjectsClient, typeRegistry, namespace, createNewCopies, } | SavedObjectsResolveImportErrorsOptions | | - -Returns: - -`Promise` - diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.excludeexportdetails.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectexportbaseoptions.excludeexportdetails.md similarity index 54% rename from docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.excludeexportdetails.md rename to docs/development/core/server/kibana-plugin-core-server.savedobjectexportbaseoptions.excludeexportdetails.md index cd2f9815c631d7..0972d82987f51f 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.excludeexportdetails.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectexportbaseoptions.excludeexportdetails.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) > [excludeExportDetails](./kibana-plugin-core-server.savedobjectsexportoptions.excludeexportdetails.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectExportBaseOptions](./kibana-plugin-core-server.savedobjectexportbaseoptions.md) > [excludeExportDetails](./kibana-plugin-core-server.savedobjectexportbaseoptions.excludeexportdetails.md) -## SavedObjectsExportOptions.excludeExportDetails property +## SavedObjectExportBaseOptions.excludeExportDetails property flag to not append [export details](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) to the end of the export stream. diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectexportbaseoptions.includereferencesdeep.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectexportbaseoptions.includereferencesdeep.md new file mode 100644 index 00000000000000..6a7c86c1af8601 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectexportbaseoptions.includereferencesdeep.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectExportBaseOptions](./kibana-plugin-core-server.savedobjectexportbaseoptions.md) > [includeReferencesDeep](./kibana-plugin-core-server.savedobjectexportbaseoptions.includereferencesdeep.md) + +## SavedObjectExportBaseOptions.includeReferencesDeep property + +flag to also include all related saved objects in the export stream. + +Signature: + +```typescript +includeReferencesDeep?: boolean; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectexportbaseoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectexportbaseoptions.md new file mode 100644 index 00000000000000..eb35bb6a4ea5c0 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectexportbaseoptions.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectExportBaseOptions](./kibana-plugin-core-server.savedobjectexportbaseoptions.md) + +## SavedObjectExportBaseOptions interface + + +Signature: + +```typescript +export interface SavedObjectExportBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [excludeExportDetails](./kibana-plugin-core-server.savedobjectexportbaseoptions.excludeexportdetails.md) | boolean | flag to not append [export details](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) to the end of the export stream. | +| [includeReferencesDeep](./kibana-plugin-core-server.savedobjectexportbaseoptions.includereferencesdeep.md) | boolean | flag to also include all related saved objects in the export stream. | +| [namespace](./kibana-plugin-core-server.savedobjectexportbaseoptions.namespace.md) | string | optional namespace to override the namespace used by the savedObjectsClient. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.namespace.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectexportbaseoptions.namespace.md similarity index 52% rename from docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.namespace.md rename to docs/development/core/server/kibana-plugin-core-server.savedobjectexportbaseoptions.namespace.md index 0a0d684da2e42f..9a8dad24ac18e8 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.namespace.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectexportbaseoptions.namespace.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) > [namespace](./kibana-plugin-core-server.savedobjectsexportoptions.namespace.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectExportBaseOptions](./kibana-plugin-core-server.savedobjectexportbaseoptions.md) > [namespace](./kibana-plugin-core-server.savedobjectexportbaseoptions.namespace.md) -## SavedObjectsExportOptions.namespace property +## SavedObjectExportBaseOptions.namespace property optional namespace to override the namespace used by the savedObjectsClient. diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbyobjectoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbyobjectoptions.md new file mode 100644 index 00000000000000..cb20fc54001257 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbyobjectoptions.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportByObjectOptions](./kibana-plugin-core-server.savedobjectsexportbyobjectoptions.md) + +## SavedObjectsExportByObjectOptions interface + +Options for the [export by objects API](./kibana-plugin-core-server.savedobjectsexporter.exportbyobjects.md) + +Signature: + +```typescript +export interface SavedObjectsExportByObjectOptions extends SavedObjectExportBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [objects](./kibana-plugin-core-server.savedobjectsexportbyobjectoptions.objects.md) | Array<{
id: string;
type: string;
}> | optional array of objects to export. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbyobjectoptions.objects.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbyobjectoptions.objects.md new file mode 100644 index 00000000000000..a821ffee153be6 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbyobjectoptions.objects.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportByObjectOptions](./kibana-plugin-core-server.savedobjectsexportbyobjectoptions.md) > [objects](./kibana-plugin-core-server.savedobjectsexportbyobjectoptions.objects.md) + +## SavedObjectsExportByObjectOptions.objects property + +optional array of objects to export. + +Signature: + +```typescript +objects: Array<{ + id: string; + type: string; + }>; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbytypeoptions.hasreference.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbytypeoptions.hasreference.md new file mode 100644 index 00000000000000..a58818e27328a3 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbytypeoptions.hasreference.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportByTypeOptions](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.md) > [hasReference](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.hasreference.md) + +## SavedObjectsExportByTypeOptions.hasReference property + +optional array of references to search object for. + +Signature: + +```typescript +hasReference?: SavedObjectsFindOptionsReference[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbytypeoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbytypeoptions.md new file mode 100644 index 00000000000000..26ebfd658f19bb --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbytypeoptions.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportByTypeOptions](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.md) + +## SavedObjectsExportByTypeOptions interface + +Options for the [export by type API](./kibana-plugin-core-server.savedobjectsexporter.exportbytypes.md) + +Signature: + +```typescript +export interface SavedObjectsExportByTypeOptions extends SavedObjectExportBaseOptions +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [hasReference](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.hasreference.md) | SavedObjectsFindOptionsReference[] | optional array of references to search object for. | +| [search](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.search.md) | string | optional query string to filter exported objects. | +| [types](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.types.md) | string[] | array of saved object types. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbytypeoptions.search.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbytypeoptions.search.md new file mode 100644 index 00000000000000..ce8c2c87ddaf71 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbytypeoptions.search.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportByTypeOptions](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.md) > [search](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.search.md) + +## SavedObjectsExportByTypeOptions.search property + +optional query string to filter exported objects. + +Signature: + +```typescript +search?: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbytypeoptions.types.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbytypeoptions.types.md new file mode 100644 index 00000000000000..eed71d7f39d235 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportbytypeoptions.types.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportByTypeOptions](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.md) > [types](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.types.md) + +## SavedObjectsExportByTypeOptions.types property + +array of saved object types. + +Signature: + +```typescript +types: string[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter.__private_.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter.__private_.md new file mode 100644 index 00000000000000..23f49a703814f6 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter.__private_.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExporter](./kibana-plugin-core-server.savedobjectsexporter.md) > ["\#private"](./kibana-plugin-core-server.savedobjectsexporter.__private_.md) + +## SavedObjectsExporter."\#private" property + +Signature: + +```typescript +#private; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter._constructor_.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter._constructor_.md new file mode 100644 index 00000000000000..cc192b03ca7c2b --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter._constructor_.md @@ -0,0 +1,23 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExporter](./kibana-plugin-core-server.savedobjectsexporter.md) > [(constructor)](./kibana-plugin-core-server.savedobjectsexporter._constructor_.md) + +## SavedObjectsExporter.(constructor) + +Constructs a new instance of the `SavedObjectsExporter` class + +Signature: + +```typescript +constructor({ savedObjectsClient, exportSizeLimit, }: { + savedObjectsClient: SavedObjectsClientContract; + exportSizeLimit: number; + }); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { savedObjectsClient, exportSizeLimit, } | {
savedObjectsClient: SavedObjectsClientContract;
exportSizeLimit: number;
} | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter.exportbyobjects.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter.exportbyobjects.md new file mode 100644 index 00000000000000..a7dc5a71b835d5 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter.exportbyobjects.md @@ -0,0 +1,30 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExporter](./kibana-plugin-core-server.savedobjectsexporter.md) > [exportByObjects](./kibana-plugin-core-server.savedobjectsexporter.exportbyobjects.md) + +## SavedObjectsExporter.exportByObjects() method + +Generates an export stream for given object references. + +See the [options](./kibana-plugin-core-server.savedobjectsexportbyobjectoptions.md) for more detailed information. + +Signature: + +```typescript +exportByObjects(options: SavedObjectsExportByObjectOptions): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | SavedObjectsExportByObjectOptions | | + +Returns: + +`Promise` + +## Exceptions + +SavedObjectsExportError + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter.exportbytypes.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter.exportbytypes.md new file mode 100644 index 00000000000000..83da41bad7fe01 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter.exportbytypes.md @@ -0,0 +1,30 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExporter](./kibana-plugin-core-server.savedobjectsexporter.md) > [exportByTypes](./kibana-plugin-core-server.savedobjectsexporter.exportbytypes.md) + +## SavedObjectsExporter.exportByTypes() method + +Generates an export stream for given types. + +See the [options](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.md) for more detailed information. + +Signature: + +```typescript +exportByTypes(options: SavedObjectsExportByTypeOptions): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| options | SavedObjectsExportByTypeOptions | | + +Returns: + +`Promise` + +## Exceptions + +SavedObjectsExportError + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter.md new file mode 100644 index 00000000000000..d8d9248f34af63 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporter.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExporter](./kibana-plugin-core-server.savedobjectsexporter.md) + +## SavedObjectsExporter class + + +Signature: + +```typescript +export declare class SavedObjectsExporter +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)({ savedObjectsClient, exportSizeLimit, })](./kibana-plugin-core-server.savedobjectsexporter._constructor_.md) | | Constructs a new instance of the SavedObjectsExporter class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| ["\#private"](./kibana-plugin-core-server.savedobjectsexporter.__private_.md) | | | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [exportByObjects(options)](./kibana-plugin-core-server.savedobjectsexporter.exportbyobjects.md) | | Generates an export stream for given object references.See the [options](./kibana-plugin-core-server.savedobjectsexportbyobjectoptions.md) for more detailed information. | +| [exportByTypes(options)](./kibana-plugin-core-server.savedobjectsexporter.exportbytypes.md) | | Generates an export stream for given types.See the [options](./kibana-plugin-core-server.savedobjectsexportbytypeoptions.md) for more detailed information. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror._constructor_.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror._constructor_.md new file mode 100644 index 00000000000000..33bc6113d56e15 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror._constructor_.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportError](./kibana-plugin-core-server.savedobjectsexporterror.md) > [(constructor)](./kibana-plugin-core-server.savedobjectsexporterror._constructor_.md) + +## SavedObjectsExportError.(constructor) + +Constructs a new instance of the `SavedObjectsExportError` class + +Signature: + +```typescript +constructor(type: string, message: string, attributes?: Record | undefined); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| type | string | | +| message | string | | +| attributes | Record<string, any> | undefined | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.attributes.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.attributes.md new file mode 100644 index 00000000000000..9061399eab1f00 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.attributes.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportError](./kibana-plugin-core-server.savedobjectsexporterror.md) > [attributes](./kibana-plugin-core-server.savedobjectsexporterror.attributes.md) + +## SavedObjectsExportError.attributes property + +Signature: + +```typescript +readonly attributes?: Record | undefined; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.exportsizeexceeded.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.exportsizeexceeded.md new file mode 100644 index 00000000000000..c4097724b193dd --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.exportsizeexceeded.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportError](./kibana-plugin-core-server.savedobjectsexporterror.md) > [exportSizeExceeded](./kibana-plugin-core-server.savedobjectsexporterror.exportsizeexceeded.md) + +## SavedObjectsExportError.exportSizeExceeded() method + +Signature: + +```typescript +static exportSizeExceeded(limit: number): SavedObjectsExportError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| limit | number | | + +Returns: + +`SavedObjectsExportError` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.md new file mode 100644 index 00000000000000..bfeaa03a947002 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.md @@ -0,0 +1,33 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportError](./kibana-plugin-core-server.savedobjectsexporterror.md) + +## SavedObjectsExportError class + + +Signature: + +```typescript +export declare class SavedObjectsExportError extends Error +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)(type, message, attributes)](./kibana-plugin-core-server.savedobjectsexporterror._constructor_.md) | | Constructs a new instance of the SavedObjectsExportError class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [attributes](./kibana-plugin-core-server.savedobjectsexporterror.attributes.md) | | Record<string, any> | undefined | | +| [type](./kibana-plugin-core-server.savedobjectsexporterror.type.md) | | string | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [exportSizeExceeded(limit)](./kibana-plugin-core-server.savedobjectsexporterror.exportsizeexceeded.md) | static | | +| [objectFetchError(objects)](./kibana-plugin-core-server.savedobjectsexporterror.objectfetcherror.md) | static | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.objectfetcherror.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.objectfetcherror.md new file mode 100644 index 00000000000000..afaa4693f3c703 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.objectfetcherror.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportError](./kibana-plugin-core-server.savedobjectsexporterror.md) > [objectFetchError](./kibana-plugin-core-server.savedobjectsexporterror.objectfetcherror.md) + +## SavedObjectsExportError.objectFetchError() method + +Signature: + +```typescript +static objectFetchError(objects: SavedObject[]): SavedObjectsExportError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| objects | SavedObject[] | | + +Returns: + +`SavedObjectsExportError` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.type.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.type.md new file mode 100644 index 00000000000000..0c1cda48246ad3 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexporterror.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportError](./kibana-plugin-core-server.savedobjectsexporterror.md) > [type](./kibana-plugin-core-server.savedobjectsexporterror.type.md) + +## SavedObjectsExportError.type property + +Signature: + +```typescript +readonly type: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.exportsizelimit.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.exportsizelimit.md deleted file mode 100644 index f1a71eefa8ca70..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.exportsizelimit.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) > [exportSizeLimit](./kibana-plugin-core-server.savedobjectsexportoptions.exportsizelimit.md) - -## SavedObjectsExportOptions.exportSizeLimit property - -the maximum number of objects to export. - -Signature: - -```typescript -exportSizeLimit: number; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.hasreference.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.hasreference.md deleted file mode 100644 index 9ea9fb2e7fba2a..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.hasreference.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) > [hasReference](./kibana-plugin-core-server.savedobjectsexportoptions.hasreference.md) - -## SavedObjectsExportOptions.hasReference property - -optional array of references to search object for when exporting by types - -Signature: - -```typescript -hasReference?: SavedObjectsFindOptionsReference[]; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.includereferencesdeep.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.includereferencesdeep.md deleted file mode 100644 index a45ca30b3cd460..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.includereferencesdeep.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) > [includeReferencesDeep](./kibana-plugin-core-server.savedobjectsexportoptions.includereferencesdeep.md) - -## SavedObjectsExportOptions.includeReferencesDeep property - -flag to also include all related saved objects in the export stream. - -Signature: - -```typescript -includeReferencesDeep?: boolean; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.md deleted file mode 100644 index b1b51a123696c0..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.md +++ /dev/null @@ -1,28 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) - -## SavedObjectsExportOptions interface - -Options controlling the export operation. - -Signature: - -```typescript -export interface SavedObjectsExportOptions -``` - -## Properties - -| Property | Type | Description | -| --- | --- | --- | -| [excludeExportDetails](./kibana-plugin-core-server.savedobjectsexportoptions.excludeexportdetails.md) | boolean | flag to not append [export details](./kibana-plugin-core-server.savedobjectsexportresultdetails.md) to the end of the export stream. | -| [exportSizeLimit](./kibana-plugin-core-server.savedobjectsexportoptions.exportsizelimit.md) | number | the maximum number of objects to export. | -| [hasReference](./kibana-plugin-core-server.savedobjectsexportoptions.hasreference.md) | SavedObjectsFindOptionsReference[] | optional array of references to search object for when exporting by types | -| [includeReferencesDeep](./kibana-plugin-core-server.savedobjectsexportoptions.includereferencesdeep.md) | boolean | flag to also include all related saved objects in the export stream. | -| [namespace](./kibana-plugin-core-server.savedobjectsexportoptions.namespace.md) | string | optional namespace to override the namespace used by the savedObjectsClient. | -| [objects](./kibana-plugin-core-server.savedobjectsexportoptions.objects.md) | Array<{
id: string;
type: string;
}> | optional array of objects to export. | -| [savedObjectsClient](./kibana-plugin-core-server.savedobjectsexportoptions.savedobjectsclient.md) | SavedObjectsClientContract | an instance of the SavedObjectsClient. | -| [search](./kibana-plugin-core-server.savedobjectsexportoptions.search.md) | string | optional query string to filter exported objects. | -| [types](./kibana-plugin-core-server.savedobjectsexportoptions.types.md) | string[] | optional array of saved object types. | - diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.objects.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.objects.md deleted file mode 100644 index b27fe2169e2d3a..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.objects.md +++ /dev/null @@ -1,16 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) > [objects](./kibana-plugin-core-server.savedobjectsexportoptions.objects.md) - -## SavedObjectsExportOptions.objects property - -optional array of objects to export. - -Signature: - -```typescript -objects?: Array<{ - id: string; - type: string; - }>; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.savedobjectsclient.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.savedobjectsclient.md deleted file mode 100644 index 64f3968fa201e1..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.savedobjectsclient.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) > [savedObjectsClient](./kibana-plugin-core-server.savedobjectsexportoptions.savedobjectsclient.md) - -## SavedObjectsExportOptions.savedObjectsClient property - -an instance of the SavedObjectsClient. - -Signature: - -```typescript -savedObjectsClient: SavedObjectsClientContract; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.search.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.search.md deleted file mode 100644 index 0a888d96180128..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.search.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) > [search](./kibana-plugin-core-server.savedobjectsexportoptions.search.md) - -## SavedObjectsExportOptions.search property - -optional query string to filter exported objects. - -Signature: - -```typescript -search?: string; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.types.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.types.md deleted file mode 100644 index d04ff5fc0aa72a..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsexportoptions.types.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsExportOptions](./kibana-plugin-core-server.savedobjectsexportoptions.md) > [types](./kibana-plugin-core-server.savedobjectsexportoptions.types.md) - -## SavedObjectsExportOptions.types property - -optional array of saved object types. - -Signature: - -```typescript -types?: string[]; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter.__private_.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter.__private_.md new file mode 100644 index 00000000000000..2d780a957e0871 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter.__private_.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImporter](./kibana-plugin-core-server.savedobjectsimporter.md) > ["\#private"](./kibana-plugin-core-server.savedobjectsimporter.__private_.md) + +## SavedObjectsImporter."\#private" property + +Signature: + +```typescript +#private; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter._constructor_.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter._constructor_.md new file mode 100644 index 00000000000000..67df4dbf09ad69 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter._constructor_.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImporter](./kibana-plugin-core-server.savedobjectsimporter.md) > [(constructor)](./kibana-plugin-core-server.savedobjectsimporter._constructor_.md) + +## SavedObjectsImporter.(constructor) + +Constructs a new instance of the `SavedObjectsImporter` class + +Signature: + +```typescript +constructor({ savedObjectsClient, typeRegistry, importSizeLimit, }: { + savedObjectsClient: SavedObjectsClientContract; + typeRegistry: ISavedObjectTypeRegistry; + importSizeLimit: number; + }); +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { savedObjectsClient, typeRegistry, importSizeLimit, } | {
savedObjectsClient: SavedObjectsClientContract;
typeRegistry: ISavedObjectTypeRegistry;
importSizeLimit: number;
} | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter.import.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter.import.md new file mode 100644 index 00000000000000..5b1b2d733fa0e8 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter.import.md @@ -0,0 +1,28 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImporter](./kibana-plugin-core-server.savedobjectsimporter.md) > [import](./kibana-plugin-core-server.savedobjectsimporter.import.md) + +## SavedObjectsImporter.import() method + +Import saved objects from given stream. See the [options](./kibana-plugin-core-server.savedobjectsimportoptions.md) for more detailed information. + +Signature: + +```typescript +import({ readStream, createNewCopies, namespace, overwrite, }: SavedObjectsImportOptions): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { readStream, createNewCopies, namespace, overwrite, } | SavedObjectsImportOptions | | + +Returns: + +`Promise` + +## Exceptions + +SavedObjectsImportError + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter.md new file mode 100644 index 00000000000000..ad07c23ae70343 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter.md @@ -0,0 +1,32 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImporter](./kibana-plugin-core-server.savedobjectsimporter.md) + +## SavedObjectsImporter class + + +Signature: + +```typescript +export declare class SavedObjectsImporter +``` + +## Constructors + +| Constructor | Modifiers | Description | +| --- | --- | --- | +| [(constructor)({ savedObjectsClient, typeRegistry, importSizeLimit, })](./kibana-plugin-core-server.savedobjectsimporter._constructor_.md) | | Constructs a new instance of the SavedObjectsImporter class | + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| ["\#private"](./kibana-plugin-core-server.savedobjectsimporter.__private_.md) | | | | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [import({ readStream, createNewCopies, namespace, overwrite, })](./kibana-plugin-core-server.savedobjectsimporter.import.md) | | Import saved objects from given stream. See the [options](./kibana-plugin-core-server.savedobjectsimportoptions.md) for more detailed information. | +| [resolveImportErrors({ readStream, createNewCopies, namespace, retries, })](./kibana-plugin-core-server.savedobjectsimporter.resolveimporterrors.md) | | Resolve and return saved object import errors. See the [options](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) for more detailed informations. | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter.resolveimporterrors.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter.resolveimporterrors.md new file mode 100644 index 00000000000000..c4ea529d30eff7 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporter.resolveimporterrors.md @@ -0,0 +1,28 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImporter](./kibana-plugin-core-server.savedobjectsimporter.md) > [resolveImportErrors](./kibana-plugin-core-server.savedobjectsimporter.resolveimporterrors.md) + +## SavedObjectsImporter.resolveImportErrors() method + +Resolve and return saved object import errors. See the [options](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) for more detailed informations. + +Signature: + +```typescript +resolveImportErrors({ readStream, createNewCopies, namespace, retries, }: SavedObjectsResolveImportErrorsOptions): Promise; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| { readStream, createNewCopies, namespace, retries, } | SavedObjectsResolveImportErrorsOptions | | + +Returns: + +`Promise` + +## Exceptions + +SavedObjectsImportError + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.id.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.attributes.md similarity index 51% rename from docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.id.md rename to docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.attributes.md index 8ae9f9c377b4ec..6d09d4cb881201 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.id.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.attributes.md @@ -1,11 +1,11 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) > [id](./kibana-plugin-core-server.savedobjectsimporterror.id.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) > [attributes](./kibana-plugin-core-server.savedobjectsimporterror.attributes.md) -## SavedObjectsImportError.id property +## SavedObjectsImportError.attributes property Signature: ```typescript -id: string; +readonly attributes?: Record | undefined; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.importsizeexceeded.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.importsizeexceeded.md new file mode 100644 index 00000000000000..9dcc43633d9eb2 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.importsizeexceeded.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) > [importSizeExceeded](./kibana-plugin-core-server.savedobjectsimporterror.importsizeexceeded.md) + +## SavedObjectsImportError.importSizeExceeded() method + +Signature: + +```typescript +static importSizeExceeded(limit: number): SavedObjectsImportError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| limit | number | | + +Returns: + +`SavedObjectsImportError` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.md index 713e23edef081a..b37b6143e7b73a 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.md @@ -2,24 +2,29 @@ [Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) -## SavedObjectsImportError interface +## SavedObjectsImportError class -Represents a failure to import. Signature: ```typescript -export interface SavedObjectsImportError +export declare class SavedObjectsImportError extends Error ``` ## Properties -| Property | Type | Description | +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [attributes](./kibana-plugin-core-server.savedobjectsimporterror.attributes.md) | | Record<string, any> | undefined | | +| [type](./kibana-plugin-core-server.savedobjectsimporterror.type.md) | | string | | + +## Methods + +| Method | Modifiers | Description | | --- | --- | --- | -| [error](./kibana-plugin-core-server.savedobjectsimporterror.error.md) | SavedObjectsImportConflictError | SavedObjectsImportAmbiguousConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError | | -| [id](./kibana-plugin-core-server.savedobjectsimporterror.id.md) | string | | -| [meta](./kibana-plugin-core-server.savedobjectsimporterror.meta.md) | {
title?: string;
icon?: string;
} | | -| [overwrite](./kibana-plugin-core-server.savedobjectsimporterror.overwrite.md) | boolean | If overwrite is specified, an attempt was made to overwrite an existing object. | -| [title](./kibana-plugin-core-server.savedobjectsimporterror.title.md) | string | | -| [type](./kibana-plugin-core-server.savedobjectsimporterror.type.md) | string | | +| [importSizeExceeded(limit)](./kibana-plugin-core-server.savedobjectsimporterror.importsizeexceeded.md) | static | | +| [nonUniqueImportObjects(nonUniqueEntries)](./kibana-plugin-core-server.savedobjectsimporterror.nonuniqueimportobjects.md) | static | | +| [nonUniqueRetryDestinations(nonUniqueRetryDestinations)](./kibana-plugin-core-server.savedobjectsimporterror.nonuniqueretrydestinations.md) | static | | +| [nonUniqueRetryObjects(nonUniqueRetryObjects)](./kibana-plugin-core-server.savedobjectsimporterror.nonuniqueretryobjects.md) | static | | +| [referencesFetchError(objects)](./kibana-plugin-core-server.savedobjectsimporterror.referencesfetcherror.md) | static | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.nonuniqueimportobjects.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.nonuniqueimportobjects.md new file mode 100644 index 00000000000000..a4a1975af0b4c4 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.nonuniqueimportobjects.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) > [nonUniqueImportObjects](./kibana-plugin-core-server.savedobjectsimporterror.nonuniqueimportobjects.md) + +## SavedObjectsImportError.nonUniqueImportObjects() method + +Signature: + +```typescript +static nonUniqueImportObjects(nonUniqueEntries: string[]): SavedObjectsImportError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| nonUniqueEntries | string[] | | + +Returns: + +`SavedObjectsImportError` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.nonuniqueretrydestinations.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.nonuniqueretrydestinations.md new file mode 100644 index 00000000000000..a60f6c34cb7e25 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.nonuniqueretrydestinations.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) > [nonUniqueRetryDestinations](./kibana-plugin-core-server.savedobjectsimporterror.nonuniqueretrydestinations.md) + +## SavedObjectsImportError.nonUniqueRetryDestinations() method + +Signature: + +```typescript +static nonUniqueRetryDestinations(nonUniqueRetryDestinations: string[]): SavedObjectsImportError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| nonUniqueRetryDestinations | string[] | | + +Returns: + +`SavedObjectsImportError` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.nonuniqueretryobjects.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.nonuniqueretryobjects.md new file mode 100644 index 00000000000000..187904ccf59a23 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.nonuniqueretryobjects.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) > [nonUniqueRetryObjects](./kibana-plugin-core-server.savedobjectsimporterror.nonuniqueretryobjects.md) + +## SavedObjectsImportError.nonUniqueRetryObjects() method + +Signature: + +```typescript +static nonUniqueRetryObjects(nonUniqueRetryObjects: string[]): SavedObjectsImportError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| nonUniqueRetryObjects | string[] | | + +Returns: + +`SavedObjectsImportError` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.referencesfetcherror.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.referencesfetcherror.md new file mode 100644 index 00000000000000..c9392739838dc2 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.referencesfetcherror.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) > [referencesFetchError](./kibana-plugin-core-server.savedobjectsimporterror.referencesfetcherror.md) + +## SavedObjectsImportError.referencesFetchError() method + +Signature: + +```typescript +static referencesFetchError(objects: SavedObject[]): SavedObjectsImportError; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| objects | SavedObject[] | | + +Returns: + +`SavedObjectsImportError` + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.type.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.type.md index e4484bbbe85782..db655f8cfa1294 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.type.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.type.md @@ -7,5 +7,5 @@ Signature: ```typescript -type: string; +readonly type: string; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.error.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.error.md similarity index 62% rename from docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.error.md rename to docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.error.md index 6fc0c86b2fafc4..40c9fa1fefa911 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.error.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.error.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) > [error](./kibana-plugin-core-server.savedobjectsimporterror.error.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportFailure](./kibana-plugin-core-server.savedobjectsimportfailure.md) > [error](./kibana-plugin-core-server.savedobjectsimportfailure.error.md) -## SavedObjectsImportError.error property +## SavedObjectsImportFailure.error property Signature: diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.id.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.id.md new file mode 100644 index 00000000000000..a58183b84e4018 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.id.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportFailure](./kibana-plugin-core-server.savedobjectsimportfailure.md) > [id](./kibana-plugin-core-server.savedobjectsimportfailure.id.md) + +## SavedObjectsImportFailure.id property + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.md new file mode 100644 index 00000000000000..536f48f45e0c5d --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.md @@ -0,0 +1,25 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportFailure](./kibana-plugin-core-server.savedobjectsimportfailure.md) + +## SavedObjectsImportFailure interface + +Represents a failure to import. + +Signature: + +```typescript +export interface SavedObjectsImportFailure +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [error](./kibana-plugin-core-server.savedobjectsimportfailure.error.md) | SavedObjectsImportConflictError | SavedObjectsImportAmbiguousConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError | | +| [id](./kibana-plugin-core-server.savedobjectsimportfailure.id.md) | string | | +| [meta](./kibana-plugin-core-server.savedobjectsimportfailure.meta.md) | {
title?: string;
icon?: string;
} | | +| [overwrite](./kibana-plugin-core-server.savedobjectsimportfailure.overwrite.md) | boolean | If overwrite is specified, an attempt was made to overwrite an existing object. | +| [title](./kibana-plugin-core-server.savedobjectsimportfailure.title.md) | string | | +| [type](./kibana-plugin-core-server.savedobjectsimportfailure.type.md) | string | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.meta.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.meta.md similarity index 51% rename from docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.meta.md rename to docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.meta.md index 8d88bf1e375d4f..c345ebe28b9452 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.meta.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.meta.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) > [meta](./kibana-plugin-core-server.savedobjectsimporterror.meta.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportFailure](./kibana-plugin-core-server.savedobjectsimportfailure.md) > [meta](./kibana-plugin-core-server.savedobjectsimportfailure.meta.md) -## SavedObjectsImportError.meta property +## SavedObjectsImportFailure.meta property Signature: diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.overwrite.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.overwrite.md similarity index 54% rename from docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.overwrite.md rename to docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.overwrite.md index f706f921cf052c..0bd3f1c1d72e81 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.overwrite.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.overwrite.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) > [overwrite](./kibana-plugin-core-server.savedobjectsimporterror.overwrite.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportFailure](./kibana-plugin-core-server.savedobjectsimportfailure.md) > [overwrite](./kibana-plugin-core-server.savedobjectsimportfailure.overwrite.md) -## SavedObjectsImportError.overwrite property +## SavedObjectsImportFailure.overwrite property If `overwrite` is specified, an attempt was made to overwrite an existing object. diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.title.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.title.md similarity index 53% rename from docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.title.md rename to docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.title.md index 3d787cbe20bb42..12326e6b0e4bb1 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimporterror.title.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.title.md @@ -1,8 +1,8 @@ -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportError](./kibana-plugin-core-server.savedobjectsimporterror.md) > [title](./kibana-plugin-core-server.savedobjectsimporterror.title.md) +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportFailure](./kibana-plugin-core-server.savedobjectsimportfailure.md) > [title](./kibana-plugin-core-server.savedobjectsimportfailure.title.md) -## SavedObjectsImportError.title property +## SavedObjectsImportFailure.title property > Warning: This API is now obsolete. > diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.type.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.type.md new file mode 100644 index 00000000000000..ff1529eb8db7aa --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportfailure.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportFailure](./kibana-plugin-core-server.savedobjectsimportfailure.md) > [type](./kibana-plugin-core-server.savedobjectsimportfailure.type.md) + +## SavedObjectsImportFailure.type property + +Signature: + +```typescript +type: string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.md index 6578b01ffa6094..ddda72938b13aa 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.md @@ -18,9 +18,6 @@ export interface SavedObjectsImportOptions | --- | --- | --- | | [createNewCopies](./kibana-plugin-core-server.savedobjectsimportoptions.createnewcopies.md) | boolean | If true, will create new copies of import objects, each with a random id and undefined originId. | | [namespace](./kibana-plugin-core-server.savedobjectsimportoptions.namespace.md) | string | if specified, will import in given namespace, else will import as global object | -| [objectLimit](./kibana-plugin-core-server.savedobjectsimportoptions.objectlimit.md) | number | The maximum number of object to import | | [overwrite](./kibana-plugin-core-server.savedobjectsimportoptions.overwrite.md) | boolean | If true, will override existing object if present. Note: this has no effect when used with the createNewCopies option. | | [readStream](./kibana-plugin-core-server.savedobjectsimportoptions.readstream.md) | Readable | The stream of [saved objects](./kibana-plugin-core-server.savedobject.md) to import | -| [savedObjectsClient](./kibana-plugin-core-server.savedobjectsimportoptions.savedobjectsclient.md) | SavedObjectsClientContract | [client](./kibana-plugin-core-server.savedobjectsclientcontract.md) to use to perform the import operation | -| [typeRegistry](./kibana-plugin-core-server.savedobjectsimportoptions.typeregistry.md) | ISavedObjectTypeRegistry | The registry of all known saved object types | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.objectlimit.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.objectlimit.md deleted file mode 100644 index 21b86d825502c8..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.objectlimit.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportOptions](./kibana-plugin-core-server.savedobjectsimportoptions.md) > [objectLimit](./kibana-plugin-core-server.savedobjectsimportoptions.objectlimit.md) - -## SavedObjectsImportOptions.objectLimit property - -The maximum number of object to import - -Signature: - -```typescript -objectLimit: number; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.savedobjectsclient.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.savedobjectsclient.md deleted file mode 100644 index 2ae7c350d188bf..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.savedobjectsclient.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportOptions](./kibana-plugin-core-server.savedobjectsimportoptions.md) > [savedObjectsClient](./kibana-plugin-core-server.savedobjectsimportoptions.savedobjectsclient.md) - -## SavedObjectsImportOptions.savedObjectsClient property - -[client](./kibana-plugin-core-server.savedobjectsclientcontract.md) to use to perform the import operation - -Signature: - -```typescript -savedObjectsClient: SavedObjectsClientContract; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.typeregistry.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.typeregistry.md deleted file mode 100644 index 89c49471d24efa..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportoptions.typeregistry.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsImportOptions](./kibana-plugin-core-server.savedobjectsimportoptions.md) > [typeRegistry](./kibana-plugin-core-server.savedobjectsimportoptions.typeregistry.md) - -## SavedObjectsImportOptions.typeRegistry property - -The registry of all known saved object types - -Signature: - -```typescript -typeRegistry: ISavedObjectTypeRegistry; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportresponse.errors.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportresponse.errors.md index ee2e86c9e4b246..dc6f782fc937f0 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportresponse.errors.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportresponse.errors.md @@ -7,5 +7,5 @@ Signature: ```typescript -errors?: SavedObjectsImportError[]; +errors?: SavedObjectsImportFailure[]; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportresponse.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportresponse.md index 52d39d981d0c23..94d24e946b5bd5 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportresponse.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsimportresponse.md @@ -16,7 +16,7 @@ export interface SavedObjectsImportResponse | Property | Type | Description | | --- | --- | --- | -| [errors](./kibana-plugin-core-server.savedobjectsimportresponse.errors.md) | SavedObjectsImportError[] | | +| [errors](./kibana-plugin-core-server.savedobjectsimportresponse.errors.md) | SavedObjectsImportFailure[] | | | [success](./kibana-plugin-core-server.savedobjectsimportresponse.success.md) | boolean | | | [successCount](./kibana-plugin-core-server.savedobjectsimportresponse.successcount.md) | number | | | [successResults](./kibana-plugin-core-server.savedobjectsimportresponse.successresults.md) | SavedObjectsImportSuccess[] | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md index f97bf284375d17..dcd2305c831f44 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md @@ -18,9 +18,6 @@ export interface SavedObjectsResolveImportErrorsOptions | --- | --- | --- | | [createNewCopies](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.createnewcopies.md) | boolean | If true, will create new copies of import objects, each with a random id and undefined originId. | | [namespace](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.namespace.md) | string | if specified, will import in given namespace | -| [objectLimit](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.objectlimit.md) | number | The maximum number of object to import | | [readStream](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.readstream.md) | Readable | The stream of [saved objects](./kibana-plugin-core-server.savedobject.md) to resolve errors from | | [retries](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.retries.md) | SavedObjectsImportRetry[] | saved object import references to retry | -| [savedObjectsClient](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md) | SavedObjectsClientContract | client to use to perform the import operation | -| [typeRegistry](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.typeregistry.md) | ISavedObjectTypeRegistry | The registry of all known saved object types | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.objectlimit.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.objectlimit.md deleted file mode 100644 index 156fe960292755..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.objectlimit.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) > [objectLimit](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.objectlimit.md) - -## SavedObjectsResolveImportErrorsOptions.objectLimit property - -The maximum number of object to import - -Signature: - -```typescript -objectLimit: number; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md deleted file mode 100644 index b338c132addf21..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) > [savedObjectsClient](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.savedobjectsclient.md) - -## SavedObjectsResolveImportErrorsOptions.savedObjectsClient property - -client to use to perform the import operation - -Signature: - -```typescript -savedObjectsClient: SavedObjectsClientContract; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.typeregistry.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.typeregistry.md deleted file mode 100644 index f06d3eb08c0ac8..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.typeregistry.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsResolveImportErrorsOptions](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) > [typeRegistry](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.typeregistry.md) - -## SavedObjectsResolveImportErrorsOptions.typeRegistry property - -The registry of all known saved object types - -Signature: - -```typescript -typeRegistry: ISavedObjectTypeRegistry; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.getimportexportobjectlimit.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.getimportexportobjectlimit.md deleted file mode 100644 index 792a0ac3d9420c..00000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.getimportexportobjectlimit.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsServiceSetup](./kibana-plugin-core-server.savedobjectsservicesetup.md) > [getImportExportObjectLimit](./kibana-plugin-core-server.savedobjectsservicesetup.getimportexportobjectlimit.md) - -## SavedObjectsServiceSetup.getImportExportObjectLimit property - -Returns the maximum number of objects allowed for import or export operations. - -Signature: - -```typescript -getImportExportObjectLimit: () => number; -``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md index 650459bfdb4358..56ebb48707f59c 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md @@ -52,7 +52,6 @@ export class Plugin() { | Property | Type | Description | | --- | --- | --- | | [addClientWrapper](./kibana-plugin-core-server.savedobjectsservicesetup.addclientwrapper.md) | (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void | Add a [client wrapper factory](./kibana-plugin-core-server.savedobjectsclientwrapperfactory.md) with the given priority. | -| [getImportExportObjectLimit](./kibana-plugin-core-server.savedobjectsservicesetup.getimportexportobjectlimit.md) | () => number | Returns the maximum number of objects allowed for import or export operations. | | [registerType](./kibana-plugin-core-server.savedobjectsservicesetup.registertype.md) | (type: SavedObjectsType) => void | Register a [savedObjects type](./kibana-plugin-core-server.savedobjectstype.md) definition.See the [mappings format](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) and [migration format](./kibana-plugin-core-server.savedobjectmigrationmap.md) for more details about these. | | [setClientFactoryProvider](./kibana-plugin-core-server.savedobjectsservicesetup.setclientfactoryprovider.md) | (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void | Set the default [factory provider](./kibana-plugin-core-server.savedobjectsclientfactoryprovider.md) for creating Saved Objects clients. Only one provider can be set, subsequent calls to this method will fail. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createexporter.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createexporter.md new file mode 100644 index 00000000000000..273d80983f15de --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createexporter.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsServiceStart](./kibana-plugin-core-server.savedobjectsservicestart.md) > [createExporter](./kibana-plugin-core-server.savedobjectsservicestart.createexporter.md) + +## SavedObjectsServiceStart.createExporter property + +Creates an [exporter](./kibana-plugin-core-server.isavedobjectsexporter.md) bound to given client. + +Signature: + +```typescript +createExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createimporter.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createimporter.md new file mode 100644 index 00000000000000..f2617c5c6c12a3 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.createimporter.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsServiceStart](./kibana-plugin-core-server.savedobjectsservicestart.md) > [createImporter](./kibana-plugin-core-server.savedobjectsservicestart.createimporter.md) + +## SavedObjectsServiceStart.createImporter property + +Creates an [importer](./kibana-plugin-core-server.isavedobjectsimporter.md) bound to given client. + +Signature: + +```typescript +createImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.md index 17655bb4878a7d..075a363fe1aa23 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicestart.md @@ -16,6 +16,8 @@ export interface SavedObjectsServiceStart | Property | Type | Description | | --- | --- | --- | +| [createExporter](./kibana-plugin-core-server.savedobjectsservicestart.createexporter.md) | (client: SavedObjectsClientContract) => ISavedObjectsExporter | Creates an [exporter](./kibana-plugin-core-server.isavedobjectsexporter.md) bound to given client. | +| [createImporter](./kibana-plugin-core-server.savedobjectsservicestart.createimporter.md) | (client: SavedObjectsClientContract) => ISavedObjectsImporter | Creates an [importer](./kibana-plugin-core-server.isavedobjectsimporter.md) bound to given client. | | [createInternalRepository](./kibana-plugin-core-server.savedobjectsservicestart.createinternalrepository.md) | (includedHiddenTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsrepository.md) that uses the internal Kibana user for authenticating with Elasticsearch. | | [createScopedRepository](./kibana-plugin-core-server.savedobjectsservicestart.createscopedrepository.md) | (req: KibanaRequest, includedHiddenTypes?: string[]) => ISavedObjectsRepository | Creates a [Saved Objects repository](./kibana-plugin-core-server.isavedobjectsrepository.md) that uses the credentials from the passed in request to authenticate with Elasticsearch. | | [createSerializer](./kibana-plugin-core-server.savedobjectsservicestart.createserializer.md) | () => SavedObjectsSerializer | Creates a [serializer](./kibana-plugin-core-server.savedobjectsserializer.md) that is aware of all registered types. | diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md index 30272cdcdc7f85..1831c2c78b3659 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md @@ -6,8 +6,6 @@ `addTriggerAction` is similar to `attachAction` as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet. -`addTriggerAction` also infers better typing of the `action` argument. - Signature: ```typescript diff --git a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md index fced0bbc3cde2d..20c237fabd074a 100644 --- a/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md +++ b/docs/development/plugins/ui_actions/public/kibana-plugin-plugins-ui_actions-public.uiactionsservice.md @@ -21,7 +21,7 @@ export declare class UiActionsService | Property | Modifiers | Type | Description | | --- | --- | --- | --- | | [actions](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.actions.md) | | ActionRegistry | | -| [addTriggerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md) | | (triggerId: string, action: ActionDefinition) => void | addTriggerAction is similar to attachAction as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet.addTriggerAction also infers better typing of the action argument. | +| [addTriggerAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.addtriggeraction.md) | | (triggerId: string, action: ActionDefinition) => void | addTriggerAction is similar to attachAction as it attaches action to a trigger, but it also registers the action, if it has not been registered, yet. | | [attachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.attachaction.md) | | (triggerId: string, actionId: string) => void | | | [clear](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.clear.md) | | () => void | Removes all registered triggers and actions. | | [detachAction](./kibana-plugin-plugins-ui_actions-public.uiactionsservice.detachaction.md) | | (triggerId: string, actionId: string) => void | | diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 51375072d3e5a8..ea83674ed9d9ca 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -148,7 +148,7 @@ export { SavedObjectsImportUnsupportedTypeError, SavedObjectsImportMissingReferencesError, SavedObjectsImportUnknownError, - SavedObjectsImportError, + SavedObjectsImportFailure, SavedObjectsImportRetry, SavedObjectsNamespaceType, } from './saved_objects'; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index dd06022dc48313..c5b49519ef7b24 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -1246,7 +1246,7 @@ export interface SavedObjectsImportConflictError { } // @public -export interface SavedObjectsImportError { +export interface SavedObjectsImportFailure { // (undocumented) error: SavedObjectsImportConflictError | SavedObjectsImportAmbiguousConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError; // (undocumented) @@ -1277,7 +1277,7 @@ export interface SavedObjectsImportMissingReferencesError { // @public export interface SavedObjectsImportResponse { // (undocumented) - errors?: SavedObjectsImportError[]; + errors?: SavedObjectsImportFailure[]; // (undocumented) success: boolean; // (undocumented) diff --git a/src/core/public/saved_objects/index.ts b/src/core/public/saved_objects/index.ts index cc8fce0884ddf9..54427638e91544 100644 --- a/src/core/public/saved_objects/index.ts +++ b/src/core/public/saved_objects/index.ts @@ -43,7 +43,7 @@ export { SavedObjectsImportUnsupportedTypeError, SavedObjectsImportMissingReferencesError, SavedObjectsImportUnknownError, - SavedObjectsImportError, + SavedObjectsImportFailure, SavedObjectsImportRetry, SavedObjectsNamespaceType, } from '../../server/types'; diff --git a/src/core/server/core_route_handler_context.ts b/src/core/server/core_route_handler_context.ts index 520c5bd3f685bc..ffb1c762b00eff 100644 --- a/src/core/server/core_route_handler_context.ts +++ b/src/core/server/core_route_handler_context.ts @@ -21,7 +21,12 @@ import { InternalCoreStart } from './internal_types'; import { KibanaRequest } from './http/router'; import { SavedObjectsClientContract } from './saved_objects/types'; -import { InternalSavedObjectsServiceStart, ISavedObjectTypeRegistry } from './saved_objects'; +import { + InternalSavedObjectsServiceStart, + ISavedObjectTypeRegistry, + ISavedObjectsExporter, + ISavedObjectsImporter, +} from './saved_objects'; import { InternalElasticsearchServiceStart, IScopedClusterClient, @@ -64,6 +69,8 @@ class CoreSavedObjectsRouteHandlerContext { ) {} #scopedSavedObjectsClient?: SavedObjectsClientContract; #typeRegistry?: ISavedObjectTypeRegistry; + #exporter?: ISavedObjectsExporter; + #importer?: ISavedObjectsImporter; public get client() { if (this.#scopedSavedObjectsClient == null) { @@ -78,6 +85,20 @@ class CoreSavedObjectsRouteHandlerContext { } return this.#typeRegistry; } + + public get exporter() { + if (this.#exporter == null) { + this.#exporter = this.savedObjectsStart.createExporter(this.client); + } + return this.#exporter; + } + + public get importer() { + if (this.#importer == null) { + this.#importer = this.savedObjectsStart.createImporter(this.client); + } + return this.#importer; + } } class CoreUiSettingsRouteHandlerContext { diff --git a/src/core/server/core_usage_data/core_usage_stats_client.ts b/src/core/server/core_usage_data/core_usage_stats_client.ts index c8d48597fae884..7c3047ecd96e40 100644 --- a/src/core/server/core_usage_data/core_usage_stats_client.ts +++ b/src/core/server/core_usage_data/core_usage_stats_client.ts @@ -24,7 +24,6 @@ import { ISavedObjectsRepository, SavedObjectsImportOptions, SavedObjectsResolveImportErrorsOptions, - SavedObjectsExportOptions, KibanaRequest, IBasePath, } from '..'; @@ -40,8 +39,10 @@ export type IncrementSavedObjectsImportOptions = BaseIncrementOptions & export type IncrementSavedObjectsResolveImportErrorsOptions = BaseIncrementOptions & Pick; /** @internal */ -export type IncrementSavedObjectsExportOptions = BaseIncrementOptions & - Pick & { supportedTypes: string[] }; +export type IncrementSavedObjectsExportOptions = BaseIncrementOptions & { + types?: string[]; + supportedTypes: string[]; +}; export const BULK_CREATE_STATS_PREFIX = 'apiCalls.savedObjectsBulkCreate'; export const BULK_GET_STATS_PREFIX = 'apiCalls.savedObjectsBulkGet'; diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 0f2761b67437db..0dae17b4c211e7 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -58,6 +58,8 @@ import { ISavedObjectTypeRegistry, SavedObjectsServiceSetup, SavedObjectsServiceStart, + ISavedObjectsExporter, + ISavedObjectsImporter, } from './saved_objects'; import { CapabilitiesSetup, CapabilitiesStart } from './capabilities'; import { MetricsServiceSetup, MetricsServiceStart } from './metrics'; @@ -265,13 +267,12 @@ export { SavedObjectsClientFactoryProvider, SavedObjectsCreateOptions, SavedObjectsErrorHelpers, - SavedObjectsExportOptions, SavedObjectsExportResultDetails, SavedObjectsFindResult, SavedObjectsFindResponse, SavedObjectsImportConflictError, SavedObjectsImportAmbiguousConflictError, - SavedObjectsImportError, + SavedObjectsImportFailure, SavedObjectsImportMissingReferencesError, SavedObjectsImportOptions, SavedObjectsImportResponse, @@ -317,9 +318,15 @@ export { SavedObjectMigrationMap, SavedObjectMigrationFn, SavedObjectsUtils, - exportSavedObjectsToStream, - importSavedObjectsFromStream, - resolveSavedObjectsImportErrors, + SavedObjectsExporter, + ISavedObjectsExporter, + SavedObjectExportBaseOptions, + SavedObjectsExportByObjectOptions, + SavedObjectsExportByTypeOptions, + SavedObjectsExportError, + SavedObjectsImporter, + ISavedObjectsImporter, + SavedObjectsImportError, } from './saved_objects'; export { @@ -399,6 +406,8 @@ export interface RequestHandlerContext { savedObjects: { client: SavedObjectsClientContract; typeRegistry: ISavedObjectTypeRegistry; + exporter: ISavedObjectsExporter; + importer: ISavedObjectsImporter; }; elasticsearch: { client: IScopedClusterClient; diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts index 669286ccb2318c..609555e4e34c12 100644 --- a/src/core/server/legacy/legacy_service.ts +++ b/src/core/server/legacy/legacy_service.ts @@ -211,6 +211,8 @@ export class LegacyService implements CoreService { createScopedRepository: startDeps.core.savedObjects.createScopedRepository, createInternalRepository: startDeps.core.savedObjects.createInternalRepository, createSerializer: startDeps.core.savedObjects.createSerializer, + createExporter: startDeps.core.savedObjects.createExporter, + createImporter: startDeps.core.savedObjects.createImporter, getTypeRegistry: startDeps.core.savedObjects.getTypeRegistry, }, metrics: { @@ -265,7 +267,6 @@ export class LegacyService implements CoreService { setClientFactoryProvider: setupDeps.core.savedObjects.setClientFactoryProvider, addClientWrapper: setupDeps.core.savedObjects.addClientWrapper, registerType: setupDeps.core.savedObjects.registerType, - getImportExportObjectLimit: setupDeps.core.savedObjects.getImportExportObjectLimit, }, status: { isStatusPageAnonymous: setupDeps.core.status.isStatusPageAnonymous, diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index 03a0ae2d6443ae..c4f0cea428ea56 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -203,6 +203,8 @@ function createCoreRequestHandlerContextMock() { savedObjects: { client: savedObjectsClientMock.create(), typeRegistry: savedObjectsTypeRegistryMock.create(), + exporter: savedObjectsServiceMock.createExporter(), + importer: savedObjectsServiceMock.createImporter(), }, elasticsearch: { client: elasticsearchServiceMock.createScopedClusterClient(), diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index 3b2634ddbe3152..42f44e4405443d 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -188,7 +188,6 @@ export function createPluginSetupContext( setClientFactoryProvider: deps.savedObjects.setClientFactoryProvider, addClientWrapper: deps.savedObjects.addClientWrapper, registerType: deps.savedObjects.registerType, - getImportExportObjectLimit: deps.savedObjects.getImportExportObjectLimit, }, status: { core$: deps.status.core$, @@ -241,6 +240,8 @@ export function createPluginStartContext( createInternalRepository: deps.savedObjects.createInternalRepository, createScopedRepository: deps.savedObjects.createScopedRepository, createSerializer: deps.savedObjects.createSerializer, + createExporter: deps.savedObjects.createExporter, + createImporter: deps.savedObjects.createImporter, getTypeRegistry: deps.savedObjects.getTypeRegistry, }, metrics: { diff --git a/src/core/server/saved_objects/export/errors.ts b/src/core/server/saved_objects/export/errors.ts new file mode 100644 index 00000000000000..3a26b092ab4896 --- /dev/null +++ b/src/core/server/saved_objects/export/errors.ts @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SavedObject } from '../../../types'; + +/** + * @public + */ +export class SavedObjectsExportError extends Error { + constructor( + public readonly type: string, + message: string, + public readonly attributes?: Record + ) { + super(message); + + // Set the prototype explicitly, see: + // https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work + Object.setPrototypeOf(this, SavedObjectsExportError.prototype); + } + + static exportSizeExceeded(limit: number) { + return new SavedObjectsExportError( + 'export-size-exceeded', + `Can't export more than ${limit} objects` + ); + } + + static objectFetchError(objects: SavedObject[]) { + return new SavedObjectsExportError('object-fetch-error', 'Error fetching objects to export', { + objects, + }); + } +} diff --git a/src/core/server/saved_objects/export/inject_nested_depdendencies.test.ts b/src/core/server/saved_objects/export/fetch_nested_dependencies.test.ts similarity index 99% rename from src/core/server/saved_objects/export/inject_nested_depdendencies.test.ts rename to src/core/server/saved_objects/export/fetch_nested_dependencies.test.ts index 862d11cfa663aa..62ee402c4da925 100644 --- a/src/core/server/saved_objects/export/inject_nested_depdendencies.test.ts +++ b/src/core/server/saved_objects/export/fetch_nested_dependencies.test.ts @@ -19,7 +19,7 @@ import { SavedObject } from '../types'; import { savedObjectsClientMock } from '../../mocks'; -import { getObjectReferencesToFetch, fetchNestedDependencies } from './inject_nested_depdendencies'; +import { getObjectReferencesToFetch, fetchNestedDependencies } from './fetch_nested_dependencies'; import { SavedObjectsErrorHelpers } from '..'; describe('getObjectReferencesToFetch()', () => { diff --git a/src/core/server/saved_objects/export/inject_nested_depdendencies.ts b/src/core/server/saved_objects/export/fetch_nested_dependencies.ts similarity index 100% rename from src/core/server/saved_objects/export/inject_nested_depdendencies.ts rename to src/core/server/saved_objects/export/fetch_nested_dependencies.ts diff --git a/src/core/server/saved_objects/export/get_sorted_objects_for_export.test.ts b/src/core/server/saved_objects/export/get_sorted_objects_for_export.test.ts deleted file mode 100644 index 8f397c01ffa719..00000000000000 --- a/src/core/server/saved_objects/export/get_sorted_objects_for_export.test.ts +++ /dev/null @@ -1,955 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { exportSavedObjectsToStream } from './get_sorted_objects_for_export'; -import { savedObjectsClientMock } from '../service/saved_objects_client.mock'; -import { Readable } from 'stream'; -import { createPromiseFromStreams, createConcatStream } from '@kbn/utils'; - -async function readStreamToCompletion(stream: Readable) { - return createPromiseFromStreams([stream, createConcatStream([])]); -} - -describe('getSortedObjectsForExport()', () => { - const savedObjectsClient = savedObjectsClientMock.create(); - - afterEach(() => { - savedObjectsClient.find.mockReset(); - savedObjectsClient.bulkGet.mockReset(); - savedObjectsClient.create.mockReset(); - savedObjectsClient.bulkCreate.mockReset(); - savedObjectsClient.delete.mockReset(); - savedObjectsClient.get.mockReset(); - savedObjectsClient.update.mockReset(); - }); - - test('exports selected types and sorts them', async () => { - savedObjectsClient.find.mockResolvedValueOnce({ - total: 2, - saved_objects: [ - { - id: '2', - type: 'search', - attributes: {}, - score: 1, - references: [ - { - name: 'name', - type: 'index-pattern', - id: '1', - }, - ], - }, - { - id: '1', - type: 'index-pattern', - attributes: {}, - score: 1, - references: [], - }, - ], - per_page: 1, - page: 0, - }); - const exportStream = await exportSavedObjectsToStream({ - savedObjectsClient, - exportSizeLimit: 500, - types: ['index-pattern', 'search'], - }); - - const response = await readStreamToCompletion(exportStream); - - expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 2, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); - expect(savedObjectsClient.find).toMatchInlineSnapshot(` - [MockFunction] { - "calls": Array [ - Array [ - Object { - "hasReference": undefined, - "hasReferenceOperator": undefined, - "namespaces": undefined, - "perPage": 500, - "search": undefined, - "type": Array [ - "index-pattern", - "search", - ], - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], - } - `); - }); - - test('omits the `namespaces` property from the export', async () => { - savedObjectsClient.find.mockResolvedValueOnce({ - total: 2, - saved_objects: [ - { - id: '2', - type: 'search', - attributes: {}, - namespaces: ['foo', 'bar'], - score: 0, - references: [ - { - name: 'name', - type: 'index-pattern', - id: '1', - }, - ], - }, - { - id: '1', - type: 'index-pattern', - attributes: {}, - namespaces: ['foo', 'bar'], - score: 0, - references: [], - }, - ], - per_page: 1, - page: 0, - }); - const exportStream = await exportSavedObjectsToStream({ - savedObjectsClient, - exportSizeLimit: 500, - types: ['index-pattern', 'search'], - }); - - const response = await readStreamToCompletion(exportStream); - - expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 2, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); - expect(savedObjectsClient.find).toMatchInlineSnapshot(` - [MockFunction] { - "calls": Array [ - Array [ - Object { - "hasReference": undefined, - "hasReferenceOperator": undefined, - "namespaces": undefined, - "perPage": 500, - "search": undefined, - "type": Array [ - "index-pattern", - "search", - ], - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], - } - `); - }); - - test('exclude export details if option is specified', async () => { - savedObjectsClient.find.mockResolvedValueOnce({ - total: 2, - saved_objects: [ - { - id: '2', - type: 'search', - attributes: {}, - score: 1, - references: [ - { - name: 'name', - type: 'index-pattern', - id: '1', - }, - ], - }, - { - id: '1', - type: 'index-pattern', - attributes: {}, - score: 1, - references: [], - }, - ], - per_page: 1, - page: 0, - }); - const exportStream = await exportSavedObjectsToStream({ - savedObjectsClient, - exportSizeLimit: 500, - types: ['index-pattern', 'search'], - excludeExportDetails: true, - }); - - const response = await readStreamToCompletion(exportStream); - - expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - ] - `); - }); - - test('exports selected types with search string when present', async () => { - savedObjectsClient.find.mockResolvedValueOnce({ - total: 2, - saved_objects: [ - { - id: '2', - type: 'search', - attributes: {}, - score: 1, - references: [ - { - name: 'name', - type: 'index-pattern', - id: '1', - }, - ], - }, - { - id: '1', - type: 'index-pattern', - attributes: {}, - score: 1, - references: [], - }, - ], - per_page: 1, - page: 0, - }); - const exportStream = await exportSavedObjectsToStream({ - savedObjectsClient, - exportSizeLimit: 500, - types: ['index-pattern', 'search'], - search: 'foo', - }); - - const response = await readStreamToCompletion(exportStream); - - expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 2, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); - expect(savedObjectsClient.find).toMatchInlineSnapshot(` - [MockFunction] { - "calls": Array [ - Array [ - Object { - "hasReference": undefined, - "hasReferenceOperator": undefined, - "namespaces": undefined, - "perPage": 500, - "search": "foo", - "type": Array [ - "index-pattern", - "search", - ], - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], - } - `); - }); - - test('exports selected types with references when present', async () => { - savedObjectsClient.find.mockResolvedValueOnce({ - total: 1, - saved_objects: [ - { - id: '2', - type: 'search', - attributes: {}, - score: 1, - references: [ - { - name: 'name', - type: 'index-pattern', - id: '1', - }, - ], - }, - ], - per_page: 1, - page: 0, - }); - const exportStream = await exportSavedObjectsToStream({ - savedObjectsClient, - exportSizeLimit: 500, - types: ['index-pattern', 'search'], - hasReference: [ - { - id: '1', - type: 'index-pattern', - }, - ], - }); - - const response = await readStreamToCompletion(exportStream); - - expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 1, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); - expect(savedObjectsClient.find).toMatchInlineSnapshot(` - [MockFunction] { - "calls": Array [ - Array [ - Object { - "hasReference": Array [ - Object { - "id": "1", - "type": "index-pattern", - }, - ], - "hasReferenceOperator": "OR", - "namespaces": undefined, - "perPage": 500, - "search": undefined, - "type": Array [ - "index-pattern", - "search", - ], - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], - } - `); - }); - - test('exports from the provided namespace when present', async () => { - savedObjectsClient.find.mockResolvedValueOnce({ - total: 2, - saved_objects: [ - { - id: '2', - type: 'search', - attributes: {}, - score: 1, - references: [ - { - name: 'name', - type: 'index-pattern', - id: '1', - }, - ], - }, - { - id: '1', - type: 'index-pattern', - attributes: {}, - score: 1, - references: [], - }, - ], - per_page: 1, - page: 0, - }); - const exportStream = await exportSavedObjectsToStream({ - savedObjectsClient, - exportSizeLimit: 500, - types: ['index-pattern', 'search'], - namespace: 'foo', - }); - - const response = await readStreamToCompletion(exportStream); - - expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 2, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); - expect(savedObjectsClient.find).toMatchInlineSnapshot(` - [MockFunction] { - "calls": Array [ - Array [ - Object { - "hasReference": undefined, - "hasReferenceOperator": undefined, - "namespaces": Array [ - "foo", - ], - "perPage": 500, - "search": undefined, - "type": Array [ - "index-pattern", - "search", - ], - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], - } - `); - }); - - test('export selected types throws error when exceeding exportSizeLimit', async () => { - savedObjectsClient.find.mockResolvedValueOnce({ - total: 2, - saved_objects: [ - { - id: '2', - type: 'search', - attributes: {}, - score: 1, - references: [ - { - type: 'index-pattern', - name: 'name', - id: '1', - }, - ], - }, - { - id: '1', - type: 'index-pattern', - attributes: {}, - score: 1, - references: [], - }, - ], - per_page: 1, - page: 0, - }); - await expect( - exportSavedObjectsToStream({ - savedObjectsClient, - exportSizeLimit: 1, - types: ['index-pattern', 'search'], - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"Can't export more than 1 objects"`); - }); - - test('sorts objects within type', async () => { - savedObjectsClient.find.mockResolvedValueOnce({ - total: 3, - per_page: 10000, - page: 1, - saved_objects: [ - { - id: '3', - type: 'index-pattern', - attributes: { - name: 'baz', - }, - score: 1, - references: [], - }, - { - id: '1', - type: 'index-pattern', - attributes: { - name: 'foo', - }, - score: 1, - references: [], - }, - { - id: '2', - type: 'index-pattern', - attributes: { - name: 'bar', - }, - score: 1, - references: [], - }, - ], - }); - const exportStream = await exportSavedObjectsToStream({ - exportSizeLimit: 10000, - savedObjectsClient, - types: ['index-pattern'], - }); - const response = await readStreamToCompletion(exportStream); - expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object { - "name": "foo", - }, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object { - "name": "bar", - }, - "id": "2", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object { - "name": "baz", - }, - "id": "3", - "references": Array [], - "type": "index-pattern", - }, - Object { - "exportedCount": 3, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); - }); - - test('exports selected objects and sorts them', async () => { - savedObjectsClient.bulkGet.mockResolvedValueOnce({ - saved_objects: [ - { - id: '2', - type: 'search', - attributes: {}, - references: [ - { - id: '1', - name: 'name', - type: 'index-pattern', - }, - ], - }, - { - id: '1', - type: 'index-pattern', - attributes: {}, - references: [], - }, - ], - }); - const exportStream = await exportSavedObjectsToStream({ - exportSizeLimit: 10000, - savedObjectsClient, - objects: [ - { - type: 'index-pattern', - id: '1', - }, - { - type: 'search', - id: '2', - }, - ], - }); - const response = await readStreamToCompletion(exportStream); - expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 2, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); - expect(savedObjectsClient.bulkGet).toMatchInlineSnapshot(` - [MockFunction] { - "calls": Array [ - Array [ - Array [ - Object { - "id": "1", - "type": "index-pattern", - }, - Object { - "id": "2", - "type": "search", - }, - ], - Object { - "namespace": undefined, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - ], - } - `); - }); - - test('modifies return results to redact `namespaces` attribute', async () => { - const createSavedObject = (obj: any) => ({ ...obj, attributes: {}, references: [] }); - savedObjectsClient.bulkGet.mockResolvedValueOnce({ - saved_objects: [ - createSavedObject({ type: 'multi', id: '1', namespaces: ['foo'] }), - createSavedObject({ type: 'multi', id: '2', namespaces: ['bar'] }), - createSavedObject({ type: 'other', id: '3' }), - ], - }); - const exportStream = await exportSavedObjectsToStream({ - exportSizeLimit: 10000, - savedObjectsClient, - objects: [ - { type: 'multi', id: '1' }, - { type: 'multi', id: '2' }, - { type: 'other', id: '3' }, - ], - }); - const response = await readStreamToCompletion(exportStream); - expect(response).toEqual([ - createSavedObject({ type: 'multi', id: '1' }), - createSavedObject({ type: 'multi', id: '2' }), - createSavedObject({ type: 'other', id: '3' }), - expect.objectContaining({ exportedCount: 3 }), - ]); - }); - - test('includes nested dependencies when passed in', async () => { - savedObjectsClient.bulkGet.mockResolvedValueOnce({ - saved_objects: [ - { - id: '2', - type: 'search', - attributes: {}, - references: [ - { - type: 'index-pattern', - name: 'name', - id: '1', - }, - ], - }, - ], - }); - savedObjectsClient.bulkGet.mockResolvedValueOnce({ - saved_objects: [ - { - id: '1', - type: 'index-pattern', - attributes: {}, - references: [], - }, - ], - }); - const exportStream = await exportSavedObjectsToStream({ - exportSizeLimit: 10000, - savedObjectsClient, - objects: [ - { - type: 'search', - id: '2', - }, - ], - includeReferencesDeep: true, - }); - const response = await readStreamToCompletion(exportStream); - expect(response).toMatchInlineSnapshot(` - Array [ - Object { - "attributes": Object {}, - "id": "1", - "references": Array [], - "type": "index-pattern", - }, - Object { - "attributes": Object {}, - "id": "2", - "references": Array [ - Object { - "id": "1", - "name": "name", - "type": "index-pattern", - }, - ], - "type": "search", - }, - Object { - "exportedCount": 2, - "missingRefCount": 0, - "missingReferences": Array [], - }, - ] - `); - expect(savedObjectsClient.bulkGet).toMatchInlineSnapshot(` - [MockFunction] { - "calls": Array [ - Array [ - Array [ - Object { - "id": "2", - "type": "search", - }, - ], - Object { - "namespace": undefined, - }, - ], - Array [ - Array [ - Object { - "id": "1", - "type": "index-pattern", - }, - ], - Object { - "namespace": undefined, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": Promise {}, - }, - Object { - "type": "return", - "value": Promise {}, - }, - ], - } - `); - }); - - test('export selected objects throws error when exceeding exportSizeLimit', async () => { - const exportOpts = { - exportSizeLimit: 1, - savedObjectsClient, - objects: [ - { - type: 'index-pattern', - id: '1', - }, - { - type: 'search', - id: '2', - }, - ], - }; - await expect(exportSavedObjectsToStream(exportOpts)).rejects.toThrowErrorMatchingInlineSnapshot( - `"Can't export more than 1 objects"` - ); - }); - - test('rejects when neither type nor objects paramaters are passed in', () => { - const exportOpts = { - exportSizeLimit: 1, - savedObjectsClient, - types: undefined, - objects: undefined, - }; - - expect(exportSavedObjectsToStream(exportOpts)).rejects.toThrowErrorMatchingInlineSnapshot( - `"Either \`type\` or \`objects\` are required."` - ); - }); - - test('rejects when both objects and search are passed in', () => { - const exportOpts = { - exportSizeLimit: 1, - savedObjectsClient, - objects: [{ type: 'index-pattern', id: '1' }], - search: 'foo', - }; - - expect(exportSavedObjectsToStream(exportOpts)).rejects.toThrowErrorMatchingInlineSnapshot( - `"Can't specify both \\"search\\" and \\"objects\\" properties when exporting"` - ); - }); - - test('rejects when both objects and references are passed in', () => { - const exportOpts = { - exportSizeLimit: 1, - savedObjectsClient, - objects: [{ type: 'index-pattern', id: '1' }], - hasReference: [{ type: 'index-pattern', id: '1' }], - }; - - expect(exportSavedObjectsToStream(exportOpts)).rejects.toThrowErrorMatchingInlineSnapshot( - `"Can't specify both \\"references\\" and \\"objects\\" properties when exporting"` - ); - }); -}); diff --git a/src/core/server/saved_objects/export/get_sorted_objects_for_export.ts b/src/core/server/saved_objects/export/get_sorted_objects_for_export.ts deleted file mode 100644 index 84b14d0a5f02cd..00000000000000 --- a/src/core/server/saved_objects/export/get_sorted_objects_for_export.ts +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Boom from '@hapi/boom'; -import { createListStream } from '@kbn/utils'; -import { - SavedObjectsClientContract, - SavedObject, - SavedObjectsFindOptionsReference, -} from '../types'; -import { fetchNestedDependencies } from './inject_nested_depdendencies'; -import { sortObjects } from './sort_objects'; - -/** - * Options controlling the export operation. - * @public - */ -export interface SavedObjectsExportOptions { - /** optional array of saved object types. */ - types?: string[]; - /** optional array of references to search object for when exporting by types */ - hasReference?: SavedObjectsFindOptionsReference[]; - /** optional array of objects to export. */ - objects?: Array<{ - /** the saved object id. */ - id: string; - /** the saved object type. */ - type: string; - }>; - /** optional query string to filter exported objects. */ - search?: string; - /** an instance of the SavedObjectsClient. */ - savedObjectsClient: SavedObjectsClientContract; - /** the maximum number of objects to export. */ - exportSizeLimit: number; - /** flag to also include all related saved objects in the export stream. */ - includeReferencesDeep?: boolean; - /** flag to not append {@link SavedObjectsExportResultDetails | export details} to the end of the export stream. */ - excludeExportDetails?: boolean; - /** optional namespace to override the namespace used by the savedObjectsClient. */ - namespace?: string; -} - -interface SavedObjectsFetchByTypeOptions { - /** array of saved object types. */ - types: string[]; - /** optional array of references to search object for when exporting by types */ - hasReference?: SavedObjectsFindOptionsReference[]; - /** optional query string to filter exported objects. */ - search?: string; - /** an instance of the SavedObjectsClient. */ - savedObjectsClient: SavedObjectsClientContract; - /** the maximum number of objects to export. */ - exportSizeLimit: number; - /** optional namespace to override the namespace used by the savedObjectsClient. */ - namespace?: string; -} - -interface SavedObjectsFetchByObjectOptions { - /** optional array of objects to export. */ - objects: Array<{ - /** the saved object id. */ - id: string; - /** the saved object type. */ - type: string; - }>; - /** an instance of the SavedObjectsClient. */ - savedObjectsClient: SavedObjectsClientContract; - /** the maximum number of objects to export. */ - exportSizeLimit: number; - /** optional namespace to override the namespace used by the savedObjectsClient. */ - namespace?: string; -} - -const isFetchByTypeOptions = ( - options: SavedObjectsFetchByTypeOptions | SavedObjectsFetchByObjectOptions -): options is SavedObjectsFetchByTypeOptions => { - return Boolean((options as SavedObjectsFetchByTypeOptions).types); -}; - -/** - * Structure of the export result details entry - * @public - */ -export interface SavedObjectsExportResultDetails { - /** number of successfully exported objects */ - exportedCount: number; - /** number of missing references */ - missingRefCount: number; - /** missing references details */ - missingReferences: Array<{ - /** the missing reference id. */ - id: string; - /** the missing reference type. */ - type: string; - }>; -} - -async function fetchByType({ - types, - namespace, - exportSizeLimit, - hasReference, - search, - savedObjectsClient, -}: SavedObjectsFetchByTypeOptions) { - const findResponse = await savedObjectsClient.find({ - type: types, - hasReference, - hasReferenceOperator: hasReference ? 'OR' : undefined, - search, - perPage: exportSizeLimit, - namespaces: namespace ? [namespace] : undefined, - }); - if (findResponse.total > exportSizeLimit) { - throw Boom.badRequest(`Can't export more than ${exportSizeLimit} objects`); - } - - // sorts server-side by _id, since it's only available in fielddata - return ( - findResponse.saved_objects - // exclude the find-specific `score` property from the exported objects - .map(({ score, ...obj }) => obj) - .sort((a: SavedObject, b: SavedObject) => (a.id > b.id ? 1 : -1)) - ); -} - -async function fetchByObjects({ - objects, - exportSizeLimit, - namespace, - savedObjectsClient, -}: SavedObjectsFetchByObjectOptions) { - if (objects.length > exportSizeLimit) { - throw Boom.badRequest(`Can't export more than ${exportSizeLimit} objects`); - } - const bulkGetResult = await savedObjectsClient.bulkGet(objects, { namespace }); - const erroredObjects = bulkGetResult.saved_objects.filter((obj) => !!obj.error); - if (erroredObjects.length) { - const err = Boom.badRequest(); - err.output.payload.attributes = { - objects: erroredObjects, - }; - throw err; - } - return bulkGetResult.saved_objects; -} - -const validateOptions = ({ - objects, - search, - hasReference, - exportSizeLimit, - namespace, - savedObjectsClient, - types, -}: SavedObjectsExportOptions): - | SavedObjectsFetchByTypeOptions - | SavedObjectsFetchByObjectOptions => { - if ((types?.length ?? 0) > 0 && (objects?.length ?? 0) > 0) { - throw Boom.badRequest(`Can't specify both "types" and "objects" properties when exporting`); - } - if (objects && objects.length > 0) { - if (objects.length > exportSizeLimit) { - throw Boom.badRequest(`Can't export more than ${exportSizeLimit} objects`); - } - if (typeof search === 'string') { - throw Boom.badRequest(`Can't specify both "search" and "objects" properties when exporting`); - } - if (hasReference && hasReference.length) { - throw Boom.badRequest( - `Can't specify both "references" and "objects" properties when exporting` - ); - } - return { - objects, - exportSizeLimit, - savedObjectsClient, - namespace, - } as SavedObjectsFetchByObjectOptions; - } else if (types && types.length > 0) { - return { - types, - hasReference, - search, - exportSizeLimit, - savedObjectsClient, - namespace, - } as SavedObjectsFetchByTypeOptions; - } else { - throw Boom.badRequest('Either `type` or `objects` are required.'); - } -}; - -/** - * Generates sorted saved object stream to be used for export. - * See the {@link SavedObjectsExportOptions | options} for more detailed information. - * - * @public - */ -export async function exportSavedObjectsToStream({ - types, - hasReference, - objects, - search, - savedObjectsClient, - exportSizeLimit, - includeReferencesDeep = false, - excludeExportDetails = false, - namespace, -}: SavedObjectsExportOptions) { - const fetchOptions = validateOptions({ - savedObjectsClient, - namespace, - exportSizeLimit, - hasReference, - search, - objects, - excludeExportDetails, - includeReferencesDeep, - types, - }); - - const rootObjects = isFetchByTypeOptions(fetchOptions) - ? await fetchByType(fetchOptions) - : await fetchByObjects(fetchOptions); - - let exportedObjects: Array> = []; - let missingReferences: SavedObjectsExportResultDetails['missingReferences'] = []; - - if (includeReferencesDeep) { - const fetchResult = await fetchNestedDependencies(rootObjects, savedObjectsClient, namespace); - exportedObjects = sortObjects(fetchResult.objects); - missingReferences = fetchResult.missingRefs; - } else { - exportedObjects = sortObjects(rootObjects); - } - - // redact attributes that should not be exported - const redactedObjects = exportedObjects.map>( - ({ namespaces, ...object }) => object - ); - - const exportDetails: SavedObjectsExportResultDetails = { - exportedCount: exportedObjects.length, - missingRefCount: missingReferences.length, - missingReferences, - }; - return createListStream([...redactedObjects, ...(excludeExportDetails ? [] : [exportDetails])]); -} diff --git a/src/core/server/saved_objects/export/index.ts b/src/core/server/saved_objects/export/index.ts index 37824cceb18cba..5166f20b3d1c1d 100644 --- a/src/core/server/saved_objects/export/index.ts +++ b/src/core/server/saved_objects/export/index.ts @@ -18,7 +18,10 @@ */ export { - exportSavedObjectsToStream, - SavedObjectsExportOptions, + SavedObjectsExportByObjectOptions, + SavedObjectExportBaseOptions, + SavedObjectsExportByTypeOptions, SavedObjectsExportResultDetails, -} from './get_sorted_objects_for_export'; +} from './types'; +export { ISavedObjectsExporter, SavedObjectsExporter } from './saved_objects_exporter'; +export { SavedObjectsExportError } from './errors'; diff --git a/src/core/server/saved_objects/export/saved_objects_exporter.mock.ts b/src/core/server/saved_objects/export/saved_objects_exporter.mock.ts new file mode 100644 index 00000000000000..71f08a17e3251e --- /dev/null +++ b/src/core/server/saved_objects/export/saved_objects_exporter.mock.ts @@ -0,0 +1,33 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ISavedObjectsExporter } from './saved_objects_exporter'; + +const createExporterMock = () => { + const mock: jest.Mocked = { + exportByObjects: jest.fn(), + exportByTypes: jest.fn(), + }; + + return mock; +}; + +export const savedObjectsExporterMock = { + create: createExporterMock, +}; diff --git a/src/core/server/saved_objects/export/saved_objects_exporter.test.ts b/src/core/server/saved_objects/export/saved_objects_exporter.test.ts new file mode 100644 index 00000000000000..b382a36a35ef7a --- /dev/null +++ b/src/core/server/saved_objects/export/saved_objects_exporter.test.ts @@ -0,0 +1,936 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SavedObjectsExporter } from './saved_objects_exporter'; +import { savedObjectsClientMock } from '../service/saved_objects_client.mock'; +import { Readable } from 'stream'; +import { createPromiseFromStreams, createConcatStream } from '@kbn/utils'; + +async function readStreamToCompletion(stream: Readable) { + return createPromiseFromStreams([stream, createConcatStream([])]); +} + +const exportSizeLimit = 500; + +describe('getSortedObjectsForExport()', () => { + let savedObjectsClient: ReturnType; + let exporter: SavedObjectsExporter; + + beforeEach(() => { + savedObjectsClient = savedObjectsClientMock.create(); + exporter = new SavedObjectsExporter({ savedObjectsClient, exportSizeLimit }); + }); + + describe('#exportByTypes', () => { + test('exports selected types and sorts them', async () => { + savedObjectsClient.find.mockResolvedValueOnce({ + total: 2, + saved_objects: [ + { + id: '2', + type: 'search', + attributes: {}, + score: 1, + references: [ + { + name: 'name', + type: 'index-pattern', + id: '1', + }, + ], + }, + { + id: '1', + type: 'index-pattern', + attributes: {}, + score: 1, + references: [], + }, + ], + per_page: 1, + page: 0, + }); + const exportStream = await exporter.exportByTypes({ + types: ['index-pattern', 'search'], + }); + + const response = await readStreamToCompletion(exportStream); + + expect(response).toMatchInlineSnapshot(` + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "exportedCount": 2, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); + expect(savedObjectsClient.find).toMatchInlineSnapshot(` + [MockFunction] { + "calls": Array [ + Array [ + Object { + "hasReference": undefined, + "hasReferenceOperator": undefined, + "namespaces": undefined, + "perPage": 500, + "search": undefined, + "type": Array [ + "index-pattern", + "search", + ], + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], + } + `); + }); + + test('omits the `namespaces` property from the export', async () => { + savedObjectsClient.find.mockResolvedValueOnce({ + total: 2, + saved_objects: [ + { + id: '2', + type: 'search', + attributes: {}, + namespaces: ['foo', 'bar'], + score: 0, + references: [ + { + name: 'name', + type: 'index-pattern', + id: '1', + }, + ], + }, + { + id: '1', + type: 'index-pattern', + attributes: {}, + namespaces: ['foo', 'bar'], + score: 0, + references: [], + }, + ], + per_page: 1, + page: 0, + }); + const exportStream = await exporter.exportByTypes({ + types: ['index-pattern', 'search'], + }); + + const response = await readStreamToCompletion(exportStream); + + expect(response).toMatchInlineSnapshot(` + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "exportedCount": 2, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); + expect(savedObjectsClient.find).toMatchInlineSnapshot(` + [MockFunction] { + "calls": Array [ + Array [ + Object { + "hasReference": undefined, + "hasReferenceOperator": undefined, + "namespaces": undefined, + "perPage": 500, + "search": undefined, + "type": Array [ + "index-pattern", + "search", + ], + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], + } + `); + }); + + test('exclude export details if option is specified', async () => { + savedObjectsClient.find.mockResolvedValueOnce({ + total: 2, + saved_objects: [ + { + id: '2', + type: 'search', + attributes: {}, + score: 1, + references: [ + { + name: 'name', + type: 'index-pattern', + id: '1', + }, + ], + }, + { + id: '1', + type: 'index-pattern', + attributes: {}, + score: 1, + references: [], + }, + ], + per_page: 1, + page: 0, + }); + const exportStream = await exporter.exportByTypes({ + types: ['index-pattern', 'search'], + excludeExportDetails: true, + }); + + const response = await readStreamToCompletion(exportStream); + + expect(response).toMatchInlineSnapshot(` + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + ] + `); + }); + + test('exports selected types with search string when present', async () => { + savedObjectsClient.find.mockResolvedValueOnce({ + total: 2, + saved_objects: [ + { + id: '2', + type: 'search', + attributes: {}, + score: 1, + references: [ + { + name: 'name', + type: 'index-pattern', + id: '1', + }, + ], + }, + { + id: '1', + type: 'index-pattern', + attributes: {}, + score: 1, + references: [], + }, + ], + per_page: 1, + page: 0, + }); + const exportStream = await exporter.exportByTypes({ + types: ['index-pattern', 'search'], + search: 'foo', + }); + + const response = await readStreamToCompletion(exportStream); + + expect(response).toMatchInlineSnapshot(` + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "exportedCount": 2, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); + expect(savedObjectsClient.find).toMatchInlineSnapshot(` + [MockFunction] { + "calls": Array [ + Array [ + Object { + "hasReference": undefined, + "hasReferenceOperator": undefined, + "namespaces": undefined, + "perPage": 500, + "search": "foo", + "type": Array [ + "index-pattern", + "search", + ], + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], + } + `); + }); + + test('exports selected types with references when present', async () => { + savedObjectsClient.find.mockResolvedValueOnce({ + total: 1, + saved_objects: [ + { + id: '2', + type: 'search', + attributes: {}, + score: 1, + references: [ + { + name: 'name', + type: 'index-pattern', + id: '1', + }, + ], + }, + ], + per_page: 1, + page: 0, + }); + const exportStream = await exporter.exportByTypes({ + types: ['index-pattern', 'search'], + hasReference: [ + { + id: '1', + type: 'index-pattern', + }, + ], + }); + + const response = await readStreamToCompletion(exportStream); + + expect(response).toMatchInlineSnapshot(` + Array [ + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "exportedCount": 1, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); + expect(savedObjectsClient.find).toMatchInlineSnapshot(` + [MockFunction] { + "calls": Array [ + Array [ + Object { + "hasReference": Array [ + Object { + "id": "1", + "type": "index-pattern", + }, + ], + "hasReferenceOperator": "OR", + "namespaces": undefined, + "perPage": 500, + "search": undefined, + "type": Array [ + "index-pattern", + "search", + ], + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], + } + `); + }); + + test('exports from the provided namespace when present', async () => { + savedObjectsClient.find.mockResolvedValueOnce({ + total: 2, + saved_objects: [ + { + id: '2', + type: 'search', + attributes: {}, + score: 1, + references: [ + { + name: 'name', + type: 'index-pattern', + id: '1', + }, + ], + }, + { + id: '1', + type: 'index-pattern', + attributes: {}, + score: 1, + references: [], + }, + ], + per_page: 1, + page: 0, + }); + const exportStream = await exporter.exportByTypes({ + types: ['index-pattern', 'search'], + namespace: 'foo', + }); + + const response = await readStreamToCompletion(exportStream); + + expect(response).toMatchInlineSnapshot(` + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "exportedCount": 2, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); + expect(savedObjectsClient.find).toMatchInlineSnapshot(` + [MockFunction] { + "calls": Array [ + Array [ + Object { + "hasReference": undefined, + "hasReferenceOperator": undefined, + "namespaces": Array [ + "foo", + ], + "perPage": 500, + "search": undefined, + "type": Array [ + "index-pattern", + "search", + ], + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], + } + `); + }); + + test('export selected types throws error when exceeding exportSizeLimit', async () => { + exporter = new SavedObjectsExporter({ savedObjectsClient, exportSizeLimit: 1 }); + + savedObjectsClient.find.mockResolvedValueOnce({ + total: 2, + saved_objects: [ + { + id: '2', + type: 'search', + attributes: {}, + score: 1, + references: [ + { + type: 'index-pattern', + name: 'name', + id: '1', + }, + ], + }, + { + id: '1', + type: 'index-pattern', + attributes: {}, + score: 1, + references: [], + }, + ], + per_page: 1, + page: 0, + }); + await expect( + exporter.exportByTypes({ + types: ['index-pattern', 'search'], + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"Can't export more than 1 objects"`); + }); + + test('sorts objects within type', async () => { + savedObjectsClient.find.mockResolvedValueOnce({ + total: 3, + per_page: 10000, + page: 1, + saved_objects: [ + { + id: '3', + type: 'index-pattern', + attributes: { + name: 'baz', + }, + score: 1, + references: [], + }, + { + id: '1', + type: 'index-pattern', + attributes: { + name: 'foo', + }, + score: 1, + references: [], + }, + { + id: '2', + type: 'index-pattern', + attributes: { + name: 'bar', + }, + score: 1, + references: [], + }, + ], + }); + const exportStream = await exporter.exportByTypes({ + types: ['index-pattern'], + }); + const response = await readStreamToCompletion(exportStream); + expect(response).toMatchInlineSnapshot(` + Array [ + Object { + "attributes": Object { + "name": "foo", + }, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object { + "name": "bar", + }, + "id": "2", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object { + "name": "baz", + }, + "id": "3", + "references": Array [], + "type": "index-pattern", + }, + Object { + "exportedCount": 3, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); + }); + }); + + describe('#exportByObjects', () => { + test('exports selected objects and sorts them', async () => { + savedObjectsClient.bulkGet.mockResolvedValueOnce({ + saved_objects: [ + { + id: '2', + type: 'search', + attributes: {}, + references: [ + { + id: '1', + name: 'name', + type: 'index-pattern', + }, + ], + }, + { + id: '1', + type: 'index-pattern', + attributes: {}, + references: [], + }, + ], + }); + const exportStream = await exporter.exportByObjects({ + objects: [ + { + type: 'index-pattern', + id: '1', + }, + { + type: 'search', + id: '2', + }, + ], + }); + const response = await readStreamToCompletion(exportStream); + expect(response).toMatchInlineSnapshot(` + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "exportedCount": 2, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); + expect(savedObjectsClient.bulkGet).toMatchInlineSnapshot(` + [MockFunction] { + "calls": Array [ + Array [ + Array [ + Object { + "id": "1", + "type": "index-pattern", + }, + Object { + "id": "2", + "type": "search", + }, + ], + Object { + "namespace": undefined, + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + ], + } + `); + }); + + test('throws when `bulkGet` returns any errored object', async () => { + savedObjectsClient.bulkGet.mockResolvedValueOnce({ + saved_objects: [ + { + id: '1', + type: 'search', + attributes: {}, + references: [], + }, + { + id: '2', + type: 'index-pattern', + error: { + error: 'NotFound', + message: 'NotFound', + statusCode: 404, + }, + attributes: {}, + references: [], + }, + ], + }); + await expect( + exporter.exportByObjects({ + objects: [ + { + type: 'index-pattern', + id: '1', + }, + { + type: 'search', + id: '2', + }, + ], + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"Error fetching objects to export"`); + }); + + test('export selected objects throws error when exceeding exportSizeLimit', async () => { + exporter = new SavedObjectsExporter({ savedObjectsClient, exportSizeLimit: 1 }); + + const exportOpts = { + objects: [ + { + type: 'index-pattern', + id: '1', + }, + { + type: 'search', + id: '2', + }, + ], + }; + await expect(exporter.exportByObjects(exportOpts)).rejects.toThrowErrorMatchingInlineSnapshot( + `"Can't export more than 1 objects"` + ); + }); + + test('modifies return results to redact `namespaces` attribute', async () => { + const createSavedObject = (obj: any) => ({ ...obj, attributes: {}, references: [] }); + savedObjectsClient.bulkGet.mockResolvedValueOnce({ + saved_objects: [ + createSavedObject({ type: 'multi', id: '1', namespaces: ['foo'] }), + createSavedObject({ type: 'multi', id: '2', namespaces: ['bar'] }), + createSavedObject({ type: 'other', id: '3' }), + ], + }); + const exportStream = await exporter.exportByObjects({ + objects: [ + { type: 'multi', id: '1' }, + { type: 'multi', id: '2' }, + { type: 'other', id: '3' }, + ], + }); + const response = await readStreamToCompletion(exportStream); + expect(response).toEqual([ + createSavedObject({ type: 'multi', id: '1' }), + createSavedObject({ type: 'multi', id: '2' }), + createSavedObject({ type: 'other', id: '3' }), + expect.objectContaining({ exportedCount: 3 }), + ]); + }); + + test('includes nested dependencies when passed in', async () => { + savedObjectsClient.bulkGet.mockResolvedValueOnce({ + saved_objects: [ + { + id: '2', + type: 'search', + attributes: {}, + references: [ + { + type: 'index-pattern', + name: 'name', + id: '1', + }, + ], + }, + ], + }); + savedObjectsClient.bulkGet.mockResolvedValueOnce({ + saved_objects: [ + { + id: '1', + type: 'index-pattern', + attributes: {}, + references: [], + }, + ], + }); + const exportStream = await exporter.exportByObjects({ + objects: [ + { + type: 'search', + id: '2', + }, + ], + includeReferencesDeep: true, + }); + const response = await readStreamToCompletion(exportStream); + expect(response).toMatchInlineSnapshot(` + Array [ + Object { + "attributes": Object {}, + "id": "1", + "references": Array [], + "type": "index-pattern", + }, + Object { + "attributes": Object {}, + "id": "2", + "references": Array [ + Object { + "id": "1", + "name": "name", + "type": "index-pattern", + }, + ], + "type": "search", + }, + Object { + "exportedCount": 2, + "missingRefCount": 0, + "missingReferences": Array [], + }, + ] + `); + expect(savedObjectsClient.bulkGet).toMatchInlineSnapshot(` + [MockFunction] { + "calls": Array [ + Array [ + Array [ + Object { + "id": "2", + "type": "search", + }, + ], + Object { + "namespace": undefined, + }, + ], + Array [ + Array [ + Object { + "id": "1", + "type": "index-pattern", + }, + ], + Object { + "namespace": undefined, + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Promise {}, + }, + Object { + "type": "return", + "value": Promise {}, + }, + ], + } + `); + }); + }); +}); diff --git a/src/core/server/saved_objects/export/saved_objects_exporter.ts b/src/core/server/saved_objects/export/saved_objects_exporter.ts new file mode 100644 index 00000000000000..94b21dda56be10 --- /dev/null +++ b/src/core/server/saved_objects/export/saved_objects_exporter.ts @@ -0,0 +1,162 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createListStream } from '@kbn/utils'; +import { PublicMethodsOf } from '@kbn/utility-types'; +import { SavedObject, SavedObjectsClientContract } from '../types'; +import { fetchNestedDependencies } from './fetch_nested_dependencies'; +import { sortObjects } from './sort_objects'; +import { + SavedObjectsExportResultDetails, + SavedObjectExportBaseOptions, + SavedObjectsExportByObjectOptions, + SavedObjectsExportByTypeOptions, +} from './types'; +import { SavedObjectsExportError } from './errors'; + +/** + * @public + */ +export type ISavedObjectsExporter = PublicMethodsOf; + +/** + * @public + */ +export class SavedObjectsExporter { + readonly #savedObjectsClient: SavedObjectsClientContract; + readonly #exportSizeLimit: number; + + constructor({ + savedObjectsClient, + exportSizeLimit, + }: { + savedObjectsClient: SavedObjectsClientContract; + exportSizeLimit: number; + }) { + this.#savedObjectsClient = savedObjectsClient; + this.#exportSizeLimit = exportSizeLimit; + } + + /** + * Generates an export stream for given types. + * + * See the {@link SavedObjectsExportByTypeOptions | options} for more detailed information. + * + * @throws SavedObjectsExportError + */ + public async exportByTypes(options: SavedObjectsExportByTypeOptions) { + const objects = await this.fetchByTypes(options); + return this.processObjects(objects, { + includeReferencesDeep: options.includeReferencesDeep, + excludeExportDetails: options.excludeExportDetails, + namespace: options.namespace, + }); + } + + /** + * Generates an export stream for given object references. + * + * See the {@link SavedObjectsExportByObjectOptions | options} for more detailed information. + * + * @throws SavedObjectsExportError + */ + public async exportByObjects(options: SavedObjectsExportByObjectOptions) { + if (options.objects.length > this.#exportSizeLimit) { + throw SavedObjectsExportError.exportSizeExceeded(this.#exportSizeLimit); + } + const objects = await this.fetchByObjects(options); + return this.processObjects(objects, { + includeReferencesDeep: options.includeReferencesDeep, + excludeExportDetails: options.excludeExportDetails, + namespace: options.namespace, + }); + } + + private async processObjects( + savedObjects: SavedObject[], + { + excludeExportDetails = false, + includeReferencesDeep = false, + namespace, + }: SavedObjectExportBaseOptions + ) { + let exportedObjects: Array>; + let missingReferences: SavedObjectsExportResultDetails['missingReferences'] = []; + + if (includeReferencesDeep) { + const fetchResult = await fetchNestedDependencies( + savedObjects, + this.#savedObjectsClient, + namespace + ); + exportedObjects = sortObjects(fetchResult.objects); + missingReferences = fetchResult.missingRefs; + } else { + exportedObjects = sortObjects(savedObjects); + } + + // redact attributes that should not be exported + const redactedObjects = exportedObjects.map>( + ({ namespaces, ...object }) => object + ); + + const exportDetails: SavedObjectsExportResultDetails = { + exportedCount: exportedObjects.length, + missingRefCount: missingReferences.length, + missingReferences, + }; + return createListStream([...redactedObjects, ...(excludeExportDetails ? [] : [exportDetails])]); + } + + private async fetchByObjects({ objects, namespace }: SavedObjectsExportByObjectOptions) { + const bulkGetResult = await this.#savedObjectsClient.bulkGet(objects, { namespace }); + const erroredObjects = bulkGetResult.saved_objects.filter((obj) => !!obj.error); + if (erroredObjects.length) { + throw SavedObjectsExportError.objectFetchError(erroredObjects); + } + return bulkGetResult.saved_objects; + } + + private async fetchByTypes({ + types, + namespace, + hasReference, + search, + }: SavedObjectsExportByTypeOptions) { + const findResponse = await this.#savedObjectsClient.find({ + type: types, + hasReference, + hasReferenceOperator: hasReference ? 'OR' : undefined, + search, + perPage: this.#exportSizeLimit, + namespaces: namespace ? [namespace] : undefined, + }); + if (findResponse.total > this.#exportSizeLimit) { + throw SavedObjectsExportError.exportSizeExceeded(this.#exportSizeLimit); + } + + // sorts server-side by _id, since it's only available in fielddata + return ( + findResponse.saved_objects + // exclude the find-specific `score` property from the exported objects + .map(({ score, ...obj }) => obj) + .sort((a: SavedObject, b: SavedObject) => (a.id > b.id ? 1 : -1)) + ); + } +} diff --git a/src/core/server/saved_objects/export/types.ts b/src/core/server/saved_objects/export/types.ts new file mode 100644 index 00000000000000..0ddcdc361c896d --- /dev/null +++ b/src/core/server/saved_objects/export/types.ts @@ -0,0 +1,77 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SavedObjectsFindOptionsReference } from '../types'; + +/** @public */ +export interface SavedObjectExportBaseOptions { + /** flag to also include all related saved objects in the export stream. */ + includeReferencesDeep?: boolean; + /** flag to not append {@link SavedObjectsExportResultDetails | export details} to the end of the export stream. */ + excludeExportDetails?: boolean; + /** optional namespace to override the namespace used by the savedObjectsClient. */ + namespace?: string; +} + +/** + * Options for the {@link SavedObjectsExporter.exportByTypes | export by type API} + * + * @public + */ +export interface SavedObjectsExportByTypeOptions extends SavedObjectExportBaseOptions { + /** array of saved object types. */ + types: string[]; + /** optional array of references to search object for. */ + hasReference?: SavedObjectsFindOptionsReference[]; + /** optional query string to filter exported objects. */ + search?: string; +} + +/** + * Options for the {@link SavedObjectsExporter.exportByObjects | export by objects API} + * + * @public + */ +export interface SavedObjectsExportByObjectOptions extends SavedObjectExportBaseOptions { + /** optional array of objects to export. */ + objects: Array<{ + /** the saved object id. */ + id: string; + /** the saved object type. */ + type: string; + }>; +} + +/** + * Structure of the export result details entry + * @public + */ +export interface SavedObjectsExportResultDetails { + /** number of successfully exported objects */ + exportedCount: number; + /** number of missing references */ + missingRefCount: number; + /** missing references details */ + missingReferences: Array<{ + /** the missing reference id. */ + id: string; + /** the missing reference type. */ + type: string; + }>; +} diff --git a/src/core/server/saved_objects/import/errors.ts b/src/core/server/saved_objects/import/errors.ts new file mode 100644 index 00000000000000..eab39fa8485236 --- /dev/null +++ b/src/core/server/saved_objects/import/errors.ts @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SavedObject } from '../../../types'; + +/** + * @public + */ +export class SavedObjectsImportError extends Error { + private constructor( + public readonly type: string, + message: string, + public readonly attributes?: Record + ) { + super(message); + + // Set the prototype explicitly, see: + // https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work + Object.setPrototypeOf(this, SavedObjectsImportError.prototype); + } + + static importSizeExceeded(limit: number) { + return new SavedObjectsImportError( + 'import-size-exceeded', + `Can't import more than ${limit} objects` + ); + } + + static nonUniqueImportObjects(nonUniqueEntries: string[]) { + return new SavedObjectsImportError( + 'non-unique-entries', + `Non-unique import objects detected: [${nonUniqueEntries.join()}]` + ); + } + + static nonUniqueRetryObjects(nonUniqueRetryObjects: string[]) { + return new SavedObjectsImportError( + 'non-unique-retry-objects', + `Non-unique retry objects: [${nonUniqueRetryObjects.join()}]` + ); + } + + static nonUniqueRetryDestinations(nonUniqueRetryDestinations: string[]) { + return new SavedObjectsImportError( + 'non-unique-retry-destination', + `Non-unique retry destinations: [${nonUniqueRetryDestinations.join()}]` + ); + } + + static referencesFetchError(objects: SavedObject[]) { + return new SavedObjectsImportError( + 'references-fetch-error', + 'Error fetching references for imported objects', + { + objects, + } + ); + } +} diff --git a/src/core/server/saved_objects/import/import_saved_objects.test.ts b/src/core/server/saved_objects/import/import_saved_objects.test.ts index 294f716036f124..d9f6ffc2800789 100644 --- a/src/core/server/saved_objects/import/import_saved_objects.test.ts +++ b/src/core/server/saved_objects/import/import_saved_objects.test.ts @@ -23,26 +23,28 @@ import { SavedObjectsClientContract, SavedObjectsType, SavedObject, - SavedObjectsImportError, + SavedObjectsImportFailure, } from '../types'; import { savedObjectsClientMock } from '../../mocks'; -import { SavedObjectsImportOptions, ISavedObjectTypeRegistry } from '..'; +import { ISavedObjectTypeRegistry } from '..'; import { typeRegistryMock } from '../saved_objects_type_registry.mock'; -import { importSavedObjectsFromStream } from './import_saved_objects'; - -import { collectSavedObjects } from './collect_saved_objects'; -import { regenerateIds } from './regenerate_ids'; -import { validateReferences } from './validate_references'; -import { checkConflicts } from './check_conflicts'; -import { checkOriginConflicts } from './check_origin_conflicts'; -import { createSavedObjects } from './create_saved_objects'; - -jest.mock('./collect_saved_objects'); -jest.mock('./regenerate_ids'); -jest.mock('./validate_references'); -jest.mock('./check_conflicts'); -jest.mock('./check_origin_conflicts'); -jest.mock('./create_saved_objects'); +import { importSavedObjectsFromStream, ImportSavedObjectsOptions } from './import_saved_objects'; + +import { + collectSavedObjects, + regenerateIds, + validateReferences, + checkConflicts, + checkOriginConflicts, + createSavedObjects, +} from './lib'; + +jest.mock('./lib/collect_saved_objects'); +jest.mock('./lib/regenerate_ids'); +jest.mock('./lib/validate_references'); +jest.mock('./lib/check_conflicts'); +jest.mock('./lib/check_origin_conflicts'); +jest.mock('./lib/create_saved_objects'); const getMockFn = any, U>(fn: (...args: Parameters) => U) => fn as jest.MockedFunction<(...args: Parameters) => U>; @@ -86,7 +88,7 @@ describe('#importSavedObjectsFromStream', () => { // other attributes aren't needed for the purposes of injecting metadata management: { icon: `${type}-icon` }, } as any) - ): SavedObjectsImportOptions => { + ): ImportSavedObjectsOptions => { readStream = new Readable(); savedObjectsClient = savedObjectsClientMock.create(); typeRegistry = typeRegistryMock.create(); @@ -114,7 +116,7 @@ describe('#importSavedObjectsFromStream', () => { attributes: { title }, }; }; - const createError = (): SavedObjectsImportError => { + const createError = (): SavedObjectsImportFailure => { const title = 'some-title'; return { type: 'foo-type', diff --git a/src/core/server/saved_objects/import/import_saved_objects.ts b/src/core/server/saved_objects/import/import_saved_objects.ts index fd169e92cc89a4..b0debc5b19ef52 100644 --- a/src/core/server/saved_objects/import/import_saved_objects.ts +++ b/src/core/server/saved_objects/import/import_saved_objects.ts @@ -17,17 +17,38 @@ * under the License. */ -import { collectSavedObjects } from './collect_saved_objects'; +import { Readable } from 'stream'; +import { ISavedObjectTypeRegistry } from '../saved_objects_type_registry'; +import { SavedObjectsClientContract } from '../types'; +import { SavedObjectsImportFailure, SavedObjectsImportResponse } from './types'; import { - SavedObjectsImportError, - SavedObjectsImportResponse, - SavedObjectsImportOptions, -} from './types'; -import { validateReferences } from './validate_references'; -import { checkOriginConflicts } from './check_origin_conflicts'; -import { createSavedObjects } from './create_saved_objects'; -import { checkConflicts } from './check_conflicts'; -import { regenerateIds } from './regenerate_ids'; + validateReferences, + checkOriginConflicts, + createSavedObjects, + checkConflicts, + regenerateIds, + collectSavedObjects, +} from './lib'; + +/** + * Options to control the import operation. + */ +export interface ImportSavedObjectsOptions { + /** The stream of {@link SavedObject | saved objects} to import */ + readStream: Readable; + /** The maximum number of object to import */ + objectLimit: number; + /** If true, will override existing object if present. Note: this has no effect when used with the `createNewCopies` option. */ + overwrite: boolean; + /** {@link SavedObjectsClientContract | client} to use to perform the import operation */ + savedObjectsClient: SavedObjectsClientContract; + /** The registry of all known saved object types */ + typeRegistry: ISavedObjectTypeRegistry; + /** if specified, will import in given namespace, else will import as global object */ + namespace?: string; + /** If true, will create new copies of import objects, each with a random `id` and undefined `originId`. */ + createNewCopies: boolean; +} /** * Import saved objects from given stream. See the {@link SavedObjectsImportOptions | options} for more @@ -43,8 +64,8 @@ export async function importSavedObjectsFromStream({ savedObjectsClient, typeRegistry, namespace, -}: SavedObjectsImportOptions): Promise { - let errorAccumulator: SavedObjectsImportError[] = []; +}: ImportSavedObjectsOptions): Promise { + let errorAccumulator: SavedObjectsImportFailure[] = []; const supportedTypes = typeRegistry.getImportableAndExportableTypes().map((type) => type.name); // Get the objects to import diff --git a/src/core/server/saved_objects/import/index.ts b/src/core/server/saved_objects/import/index.ts index ab69e4fc441973..d9300f65b1935f 100644 --- a/src/core/server/saved_objects/import/index.ts +++ b/src/core/server/saved_objects/import/index.ts @@ -17,12 +17,11 @@ * under the License. */ -export { importSavedObjectsFromStream } from './import_saved_objects'; -export { resolveSavedObjectsImportErrors } from './resolve_import_errors'; +export { ISavedObjectsImporter, SavedObjectsImporter } from './saved_objects_importer'; export { SavedObjectsImportResponse, SavedObjectsImportSuccess, - SavedObjectsImportError, + SavedObjectsImportFailure, SavedObjectsImportOptions, SavedObjectsImportConflictError, SavedObjectsImportAmbiguousConflictError, @@ -32,3 +31,4 @@ export { SavedObjectsResolveImportErrorsOptions, SavedObjectsImportRetry, } from './types'; +export { SavedObjectsImportError } from './errors'; diff --git a/src/core/server/saved_objects/import/__mocks__/index.ts b/src/core/server/saved_objects/import/lib/__mocks__/index.ts similarity index 100% rename from src/core/server/saved_objects/import/__mocks__/index.ts rename to src/core/server/saved_objects/import/lib/__mocks__/index.ts diff --git a/src/core/server/saved_objects/import/check_conflicts.test.ts b/src/core/server/saved_objects/import/lib/check_conflicts.test.ts similarity index 97% rename from src/core/server/saved_objects/import/check_conflicts.test.ts rename to src/core/server/saved_objects/import/lib/check_conflicts.test.ts index 0d58970eee2cce..17b4e22e07ebf5 100644 --- a/src/core/server/saved_objects/import/check_conflicts.test.ts +++ b/src/core/server/saved_objects/import/lib/check_conflicts.test.ts @@ -18,10 +18,10 @@ */ import { mockUuidv4 } from './__mocks__'; -import { savedObjectsClientMock } from '../../mocks'; +import { savedObjectsClientMock } from '../../../mocks'; import { SavedObjectReference, SavedObjectsImportRetry } from 'kibana/public'; -import { SavedObjectsClientContract, SavedObject } from '../types'; -import { SavedObjectsErrorHelpers } from '..'; +import { SavedObjectsClientContract, SavedObject } from '../../types'; +import { SavedObjectsErrorHelpers } from '../../service'; import { checkConflicts } from './check_conflicts'; type SavedObjectType = SavedObject<{ title?: string }>; diff --git a/src/core/server/saved_objects/import/check_conflicts.ts b/src/core/server/saved_objects/import/lib/check_conflicts.ts similarity index 97% rename from src/core/server/saved_objects/import/check_conflicts.ts rename to src/core/server/saved_objects/import/lib/check_conflicts.ts index 88ef1bf0e02365..25b86834e4e405 100644 --- a/src/core/server/saved_objects/import/check_conflicts.ts +++ b/src/core/server/saved_objects/import/lib/check_conflicts.ts @@ -21,10 +21,10 @@ import { v4 as uuidv4 } from 'uuid'; import { SavedObject, SavedObjectsClientContract, - SavedObjectsImportError, + SavedObjectsImportFailure, SavedObjectError, SavedObjectsImportRetry, -} from '../types'; +} from '../../types'; interface CheckConflictsParams { objects: Array>; @@ -47,7 +47,7 @@ export async function checkConflicts({ createNewCopies, }: CheckConflictsParams) { const filteredObjects: Array> = []; - const errors: SavedObjectsImportError[] = []; + const errors: SavedObjectsImportFailure[] = []; const importIdMap = new Map(); const pendingOverwrites = new Set(); diff --git a/src/core/server/saved_objects/import/check_origin_conflicts.test.ts b/src/core/server/saved_objects/import/lib/check_origin_conflicts.test.ts similarity index 98% rename from src/core/server/saved_objects/import/check_origin_conflicts.test.ts rename to src/core/server/saved_objects/import/lib/check_origin_conflicts.test.ts index ba5576bd05b739..ff7f843a2a8dc3 100644 --- a/src/core/server/saved_objects/import/check_origin_conflicts.test.ts +++ b/src/core/server/saved_objects/import/lib/check_origin_conflicts.test.ts @@ -23,12 +23,12 @@ import { SavedObjectReference, SavedObject, SavedObjectsImportRetry, - SavedObjectsImportError, -} from '../types'; + SavedObjectsImportFailure, +} from '../../types'; import { checkOriginConflicts, getImportIdMapForRetries } from './check_origin_conflicts'; -import { savedObjectsClientMock } from '../../mocks'; -import { typeRegistryMock } from '../saved_objects_type_registry.mock'; -import { ISavedObjectTypeRegistry } from '..'; +import { savedObjectsClientMock } from '../../../mocks'; +import { typeRegistryMock } from '../../saved_objects_type_registry.mock'; +import { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry'; type SavedObjectType = SavedObject<{ title?: string }>; type CheckOriginConflictsParams = Parameters[0]; @@ -164,7 +164,7 @@ describe('#checkOriginConflicts', () => { const createAmbiguousConflictError = ( object: SavedObjectType, destinations: SavedObjectType[] - ): SavedObjectsImportError => ({ + ): SavedObjectsImportFailure => ({ type: object.type, id: object.id, title: object.attributes.title, @@ -177,7 +177,7 @@ describe('#checkOriginConflicts', () => { const createConflictError = ( object: SavedObjectType, destinationId?: string - ): SavedObjectsImportError => ({ + ): SavedObjectsImportFailure => ({ type: object.type, id: object.id, title: object.attributes?.title, diff --git a/src/core/server/saved_objects/import/check_origin_conflicts.ts b/src/core/server/saved_objects/import/lib/check_origin_conflicts.ts similarity index 98% rename from src/core/server/saved_objects/import/check_origin_conflicts.ts rename to src/core/server/saved_objects/import/lib/check_origin_conflicts.ts index 433574fbdbf4c0..3aa7025f216164 100644 --- a/src/core/server/saved_objects/import/check_origin_conflicts.ts +++ b/src/core/server/saved_objects/import/lib/check_origin_conflicts.ts @@ -22,10 +22,10 @@ import { v4 as uuidv4 } from 'uuid'; import { SavedObject, SavedObjectsClientContract, - SavedObjectsImportError, + SavedObjectsImportFailure, SavedObjectsImportRetry, -} from '../types'; -import { ISavedObjectTypeRegistry } from '..'; +} from '../../types'; +import { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry'; interface CheckOriginConflictsParams { objects: Array>; @@ -159,7 +159,7 @@ export async function checkOriginConflicts({ objects, ...params }: CheckOriginCo return acc.set(key, [...value, cur.value.object]); }, new Map>>()); - const errors: SavedObjectsImportError[] = []; + const errors: SavedObjectsImportFailure[] = []; const importIdMap = new Map(); const pendingOverwrites = new Set(); checkOriginConflictResults.forEach((result) => { diff --git a/src/core/server/saved_objects/import/collect_saved_objects.test.ts b/src/core/server/saved_objects/import/lib/collect_saved_objects.test.ts similarity index 96% rename from src/core/server/saved_objects/import/collect_saved_objects.test.ts rename to src/core/server/saved_objects/import/lib/collect_saved_objects.test.ts index f54130be326ad5..701c1b9b2aeeb3 100644 --- a/src/core/server/saved_objects/import/collect_saved_objects.test.ts +++ b/src/core/server/saved_objects/import/lib/collect_saved_objects.test.ts @@ -18,6 +18,7 @@ */ import { Readable, PassThrough } from 'stream'; +import { SavedObjectsImportError } from '../errors'; import { collectSavedObjects } from './collect_saved_objects'; import { createLimitStream } from './create_limit_stream'; import { getNonUniqueEntries } from './get_non_unique_entries'; @@ -112,16 +113,16 @@ describe('collectSavedObjects()', () => { }); describe('results', () => { - test('throws Boom error if any import objects are not unique', async () => { + test('throws import error if any import objects are not unique', async () => { getMockFn(getNonUniqueEntries).mockReturnValue(['type1:id1', 'type2:id2']); const readStream = createReadStream(); expect.assertions(2); try { await collectSavedObjects({ readStream, supportedTypes: [], objectLimit }); - } catch ({ isBoom, message }) { - expect(isBoom).toBe(true); - expect(message).toMatchInlineSnapshot( - `"Non-unique import objects detected: [type1:id1,type2:id2]: Bad Request"` + } catch (e) { + expect(e).toBeInstanceOf(SavedObjectsImportError); + expect(e.message).toMatchInlineSnapshot( + `"Non-unique import objects detected: [type1:id1,type2:id2]"` ); } }); diff --git a/src/core/server/saved_objects/import/collect_saved_objects.ts b/src/core/server/saved_objects/import/lib/collect_saved_objects.ts similarity index 89% rename from src/core/server/saved_objects/import/collect_saved_objects.ts rename to src/core/server/saved_objects/import/lib/collect_saved_objects.ts index 8f09e69f6c7278..0494fada87ed96 100644 --- a/src/core/server/saved_objects/import/collect_saved_objects.ts +++ b/src/core/server/saved_objects/import/lib/collect_saved_objects.ts @@ -25,11 +25,11 @@ import { createPromiseFromStreams, } from '@kbn/utils'; -import { SavedObject } from '../types'; -import { createLimitStream } from './create_limit_stream'; -import { SavedObjectsImportError } from './types'; +import { SavedObject } from '../../types'; +import { SavedObjectsImportFailure } from '../types'; +import { SavedObjectsImportError } from '../errors'; import { getNonUniqueEntries } from './get_non_unique_entries'; -import { SavedObjectsErrorHelpers } from '..'; +import { createLimitStream } from './create_limit_stream'; interface CollectSavedObjectsOptions { readStream: Readable; @@ -44,7 +44,7 @@ export async function collectSavedObjects({ filter, supportedTypes, }: CollectSavedObjectsOptions) { - const errors: SavedObjectsImportError[] = []; + const errors: SavedObjectsImportFailure[] = []; const entries: Array<{ type: string; id: string }> = []; const importIdMap = new Map(); const collectedObjects: Array> = await createPromiseFromStreams([ @@ -79,9 +79,7 @@ export async function collectSavedObjects({ // throw a BadRequest error if we see the same import object type/id more than once const nonUniqueEntries = getNonUniqueEntries(entries); if (nonUniqueEntries.length > 0) { - throw SavedObjectsErrorHelpers.createBadRequestError( - `Non-unique import objects detected: [${nonUniqueEntries.join()}]` - ); + throw SavedObjectsImportError.nonUniqueImportObjects(nonUniqueEntries); } return { diff --git a/src/core/server/saved_objects/import/create_limit_stream.test.ts b/src/core/server/saved_objects/import/lib/create_limit_stream.test.ts similarity index 100% rename from src/core/server/saved_objects/import/create_limit_stream.test.ts rename to src/core/server/saved_objects/import/lib/create_limit_stream.test.ts diff --git a/src/core/server/saved_objects/import/create_limit_stream.ts b/src/core/server/saved_objects/import/lib/create_limit_stream.ts similarity index 89% rename from src/core/server/saved_objects/import/create_limit_stream.ts rename to src/core/server/saved_objects/import/lib/create_limit_stream.ts index 709bb3b2d00656..73c2675c0973cb 100644 --- a/src/core/server/saved_objects/import/create_limit_stream.ts +++ b/src/core/server/saved_objects/import/lib/create_limit_stream.ts @@ -17,8 +17,8 @@ * under the License. */ -import Boom from '@hapi/boom'; import { Transform } from 'stream'; +import { SavedObjectsImportError } from '../errors'; export function createLimitStream(limit: number) { let counter = 0; @@ -26,7 +26,7 @@ export function createLimitStream(limit: number) { objectMode: true, async transform(obj, enc, done) { if (counter >= limit) { - return done(Boom.badRequest(`Can't import more than ${limit} objects`)); + return done(SavedObjectsImportError.importSizeExceeded(limit)); } counter++; done(undefined, obj); diff --git a/src/core/server/saved_objects/import/create_objects_filter.test.ts b/src/core/server/saved_objects/import/lib/create_objects_filter.test.ts similarity index 100% rename from src/core/server/saved_objects/import/create_objects_filter.test.ts rename to src/core/server/saved_objects/import/lib/create_objects_filter.test.ts diff --git a/src/core/server/saved_objects/import/create_objects_filter.ts b/src/core/server/saved_objects/import/lib/create_objects_filter.ts similarity index 91% rename from src/core/server/saved_objects/import/create_objects_filter.ts rename to src/core/server/saved_objects/import/lib/create_objects_filter.ts index 55b8ab128d7532..885b09d1f8adfe 100644 --- a/src/core/server/saved_objects/import/create_objects_filter.ts +++ b/src/core/server/saved_objects/import/lib/create_objects_filter.ts @@ -17,8 +17,8 @@ * under the License. */ -import { SavedObject } from '../types'; -import { SavedObjectsImportRetry } from './types'; +import { SavedObject } from '../../types'; +import { SavedObjectsImportRetry } from '../types'; export function createObjectsFilter(retries: SavedObjectsImportRetry[]) { const retryKeys = new Set(retries.map((retry) => `${retry.type}:${retry.id}`)); diff --git a/src/core/server/saved_objects/import/create_saved_objects.test.ts b/src/core/server/saved_objects/import/lib/create_saved_objects.test.ts similarity index 95% rename from src/core/server/saved_objects/import/create_saved_objects.test.ts rename to src/core/server/saved_objects/import/lib/create_saved_objects.test.ts index 6c396e58e1a287..8448875e1f7c7a 100644 --- a/src/core/server/saved_objects/import/create_saved_objects.test.ts +++ b/src/core/server/saved_objects/import/lib/create_saved_objects.test.ts @@ -17,10 +17,10 @@ * under the License. */ -import { savedObjectsClientMock } from '../../mocks'; +import { savedObjectsClientMock } from '../../../mocks'; import { createSavedObjects } from './create_saved_objects'; -import { SavedObjectsClientContract, SavedObject, SavedObjectsImportError } from '../types'; -import { SavedObjectsErrorHelpers } from '..'; +import { SavedObjectsClientContract, SavedObject, SavedObjectsImportFailure } from '../../types'; +import { SavedObjectsErrorHelpers } from '../../service'; import { extractErrors } from './extract_errors'; type CreateSavedObjectsParams = Parameters[0]; @@ -79,7 +79,7 @@ describe('#createSavedObjects', () => { */ const setupParams = (partial: { objects: SavedObject[]; - accumulatedErrors?: SavedObjectsImportError[]; + accumulatedErrors?: SavedObjectsImportFailure[]; namespace?: string; overwrite?: boolean; }): CreateSavedObjectsParams => { @@ -158,7 +158,7 @@ describe('#createSavedObjects', () => { }; test('filters out objects that have errors present', async () => { - const error = { type: obj1.type, id: obj1.id } as SavedObjectsImportError; + const error = { type: obj1.type, id: obj1.id } as SavedObjectsImportFailure; const options = setupParams({ objects: [obj1], accumulatedErrors: [error] }); const createSavedObjectsResult = await createSavedObjects(options); @@ -197,22 +197,26 @@ describe('#createSavedObjects', () => { }; describe('handles accumulated errors as expected', () => { - const resolvableErrors: SavedObjectsImportError[] = [ - { type: 'foo', id: 'foo-id', error: { type: 'conflict' } } as SavedObjectsImportError, + const resolvableErrors: SavedObjectsImportFailure[] = [ + { type: 'foo', id: 'foo-id', error: { type: 'conflict' } } as SavedObjectsImportFailure, { type: 'bar', id: 'bar-id', error: { type: 'ambiguous_conflict' }, - } as SavedObjectsImportError, + } as SavedObjectsImportFailure, { type: 'baz', id: 'baz-id', error: { type: 'missing_references' }, - } as SavedObjectsImportError, + } as SavedObjectsImportFailure, ]; - const unresolvableErrors: SavedObjectsImportError[] = [ - { type: 'qux', id: 'qux-id', error: { type: 'unsupported_type' } } as SavedObjectsImportError, - { type: 'quux', id: 'quux-id', error: { type: 'unknown' } } as SavedObjectsImportError, + const unresolvableErrors: SavedObjectsImportFailure[] = [ + { + type: 'qux', + id: 'qux-id', + error: { type: 'unsupported_type' }, + } as SavedObjectsImportFailure, + { type: 'quux', id: 'quux-id', error: { type: 'unknown' } } as SavedObjectsImportFailure, ]; test('does not call bulkCreate when resolvable errors are present', async () => { diff --git a/src/core/server/saved_objects/import/create_saved_objects.ts b/src/core/server/saved_objects/import/lib/create_saved_objects.ts similarity index 96% rename from src/core/server/saved_objects/import/create_saved_objects.ts rename to src/core/server/saved_objects/import/lib/create_saved_objects.ts index 9930e9c69358a9..faddf24983609d 100644 --- a/src/core/server/saved_objects/import/create_saved_objects.ts +++ b/src/core/server/saved_objects/import/lib/create_saved_objects.ts @@ -17,13 +17,13 @@ * under the License. */ -import { SavedObject, SavedObjectsClientContract, SavedObjectsImportError } from '../types'; +import { SavedObject, SavedObjectsClientContract, SavedObjectsImportFailure } from '../../types'; import { extractErrors } from './extract_errors'; -import { CreatedObject } from './types'; +import { CreatedObject } from '../types'; interface CreateSavedObjectsParams { objects: Array>; - accumulatedErrors: SavedObjectsImportError[]; + accumulatedErrors: SavedObjectsImportFailure[]; savedObjectsClient: SavedObjectsClientContract; importIdMap: Map; namespace?: string; @@ -31,7 +31,7 @@ interface CreateSavedObjectsParams { } interface CreateSavedObjectsResult { createdObjects: Array>; - errors: SavedObjectsImportError[]; + errors: SavedObjectsImportFailure[]; } /** diff --git a/src/core/server/saved_objects/import/extract_errors.test.ts b/src/core/server/saved_objects/import/lib/extract_errors.test.ts similarity index 95% rename from src/core/server/saved_objects/import/extract_errors.test.ts rename to src/core/server/saved_objects/import/lib/extract_errors.test.ts index 047c4ae36266f0..cafc7a1ff885b6 100644 --- a/src/core/server/saved_objects/import/extract_errors.test.ts +++ b/src/core/server/saved_objects/import/lib/extract_errors.test.ts @@ -17,10 +17,10 @@ * under the License. */ -import { SavedObject } from '../types'; +import { SavedObject } from '../../types'; import { extractErrors } from './extract_errors'; -import { SavedObjectsErrorHelpers } from '..'; -import { CreatedObject } from './types'; +import { SavedObjectsErrorHelpers } from '../../service'; +import { CreatedObject } from '../types'; describe('extractErrors()', () => { test('returns empty array when no errors exist', () => { diff --git a/src/core/server/saved_objects/import/extract_errors.ts b/src/core/server/saved_objects/import/lib/extract_errors.ts similarity index 92% rename from src/core/server/saved_objects/import/extract_errors.ts rename to src/core/server/saved_objects/import/lib/extract_errors.ts index 6a7e5d4d9dfa40..6a68adba7f9170 100644 --- a/src/core/server/saved_objects/import/extract_errors.ts +++ b/src/core/server/saved_objects/import/lib/extract_errors.ts @@ -16,15 +16,15 @@ * specific language governing permissions and limitations * under the License. */ -import { SavedObject } from '../types'; -import { SavedObjectsImportError, CreatedObject } from './types'; +import { SavedObject } from '../../types'; +import { SavedObjectsImportFailure, CreatedObject } from '../types'; export function extractErrors( // TODO: define saved object type savedObjectResults: Array>, savedObjectsToImport: Array> ) { - const errors: SavedObjectsImportError[] = []; + const errors: SavedObjectsImportFailure[] = []; const originalSavedObjectsMap = new Map>(); for (const savedObject of savedObjectsToImport) { originalSavedObjectsMap.set(`${savedObject.type}:${savedObject.id}`, savedObject); diff --git a/src/core/server/saved_objects/import/get_non_unique_entries.test.ts b/src/core/server/saved_objects/import/lib/get_non_unique_entries.test.ts similarity index 100% rename from src/core/server/saved_objects/import/get_non_unique_entries.test.ts rename to src/core/server/saved_objects/import/lib/get_non_unique_entries.test.ts diff --git a/src/core/server/saved_objects/import/get_non_unique_entries.ts b/src/core/server/saved_objects/import/lib/get_non_unique_entries.ts similarity index 100% rename from src/core/server/saved_objects/import/get_non_unique_entries.ts rename to src/core/server/saved_objects/import/lib/get_non_unique_entries.ts diff --git a/src/core/server/saved_objects/import/lib/index.ts b/src/core/server/saved_objects/import/lib/index.ts new file mode 100644 index 00000000000000..2025ca257b616a --- /dev/null +++ b/src/core/server/saved_objects/import/lib/index.ts @@ -0,0 +1,31 @@ +/* + * 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. + */ + +export { checkConflicts } from './check_conflicts'; +export { checkOriginConflicts, getImportIdMapForRetries } from './check_origin_conflicts'; +export { collectSavedObjects } from './collect_saved_objects'; +export { createLimitStream } from './create_limit_stream'; +export { createObjectsFilter } from './create_objects_filter'; +export { createSavedObjects } from './create_saved_objects'; +export { extractErrors } from './extract_errors'; +export { getNonUniqueEntries } from './get_non_unique_entries'; +export { regenerateIds } from './regenerate_ids'; +export { splitOverwrites } from './split_overwrites'; +export { getNonExistingReferenceAsKeys, validateReferences } from './validate_references'; +export { validateRetries } from './validate_retries'; diff --git a/src/core/server/saved_objects/import/regenerate_ids.test.ts b/src/core/server/saved_objects/import/lib/regenerate_ids.test.ts similarity index 97% rename from src/core/server/saved_objects/import/regenerate_ids.test.ts rename to src/core/server/saved_objects/import/lib/regenerate_ids.test.ts index 1bbc2693e4f491..dbaa3062157c4c 100644 --- a/src/core/server/saved_objects/import/regenerate_ids.test.ts +++ b/src/core/server/saved_objects/import/lib/regenerate_ids.test.ts @@ -19,7 +19,7 @@ import { mockUuidv4 } from './__mocks__'; import { regenerateIds } from './regenerate_ids'; -import { SavedObject } from '../types'; +import { SavedObject } from '../../types'; describe('#regenerateIds', () => { const objects = ([ diff --git a/src/core/server/saved_objects/import/regenerate_ids.ts b/src/core/server/saved_objects/import/lib/regenerate_ids.ts similarity index 96% rename from src/core/server/saved_objects/import/regenerate_ids.ts rename to src/core/server/saved_objects/import/lib/regenerate_ids.ts index 647386ed164696..6f088f146c3eab 100644 --- a/src/core/server/saved_objects/import/regenerate_ids.ts +++ b/src/core/server/saved_objects/import/lib/regenerate_ids.ts @@ -18,7 +18,7 @@ */ import { v4 as uuidv4 } from 'uuid'; -import { SavedObject } from '../types'; +import { SavedObject } from '../../types'; /** * Takes an array of saved objects and returns an importIdMap of randomly-generated new IDs. diff --git a/src/core/server/saved_objects/import/split_overwrites.test.ts b/src/core/server/saved_objects/import/lib/split_overwrites.test.ts similarity index 100% rename from src/core/server/saved_objects/import/split_overwrites.test.ts rename to src/core/server/saved_objects/import/lib/split_overwrites.test.ts diff --git a/src/core/server/saved_objects/import/split_overwrites.ts b/src/core/server/saved_objects/import/lib/split_overwrites.ts similarity index 93% rename from src/core/server/saved_objects/import/split_overwrites.ts rename to src/core/server/saved_objects/import/lib/split_overwrites.ts index 03ae6b96e78237..9c59a34e232096 100644 --- a/src/core/server/saved_objects/import/split_overwrites.ts +++ b/src/core/server/saved_objects/import/lib/split_overwrites.ts @@ -17,8 +17,8 @@ * under the License. */ -import { SavedObject } from '../types'; -import { SavedObjectsImportRetry } from './types'; +import { SavedObject } from '../../types'; +import { SavedObjectsImportRetry } from '../types'; export function splitOverwrites( savedObjects: Array>, diff --git a/src/core/server/saved_objects/import/validate_references.test.ts b/src/core/server/saved_objects/import/lib/validate_references.test.ts similarity index 98% rename from src/core/server/saved_objects/import/validate_references.test.ts rename to src/core/server/saved_objects/import/lib/validate_references.test.ts index 6efd1b28b199d6..5611c62610654c 100644 --- a/src/core/server/saved_objects/import/validate_references.test.ts +++ b/src/core/server/saved_objects/import/lib/validate_references.test.ts @@ -18,8 +18,8 @@ */ import { getNonExistingReferenceAsKeys, validateReferences } from './validate_references'; -import { savedObjectsClientMock } from '../../mocks'; -import { SavedObjectsErrorHelpers } from '..'; +import { savedObjectsClientMock } from '../../../mocks'; +import { SavedObjectsErrorHelpers } from '../../service'; describe('getNonExistingReferenceAsKeys()', () => { const savedObjectsClient = savedObjectsClientMock.create(); @@ -586,6 +586,8 @@ describe('validateReferences()', () => { ]; await expect( validateReferences(savedObjects, savedObjectsClient) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"Bad Request"`); + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Error fetching references for imported objects"` + ); }); }); diff --git a/src/core/server/saved_objects/import/validate_references.ts b/src/core/server/saved_objects/import/lib/validate_references.ts similarity index 89% rename from src/core/server/saved_objects/import/validate_references.ts rename to src/core/server/saved_objects/import/lib/validate_references.ts index b0686215c00dd2..ff5b2e9c8e1d7f 100644 --- a/src/core/server/saved_objects/import/validate_references.ts +++ b/src/core/server/saved_objects/import/lib/validate_references.ts @@ -17,14 +17,14 @@ * under the License. */ -import Boom from '@hapi/boom'; -import { SavedObject, SavedObjectsClientContract } from '../types'; -import { SavedObjectsImportError, SavedObjectsImportRetry } from './types'; +import { SavedObject, SavedObjectsClientContract } from '../../types'; +import { SavedObjectsImportFailure, SavedObjectsImportRetry } from '../types'; +import { SavedObjectsImportError } from '../errors'; -const REF_TYPES_TO_VLIDATE = ['index-pattern', 'search']; +const REF_TYPES_TO_VALIDATE = ['index-pattern', 'search']; function filterReferencesToValidate({ type }: { type: string }) { - return REF_TYPES_TO_VLIDATE.includes(type); + return REF_TYPES_TO_VALIDATE.includes(type); } const getObjectsToSkip = (retries: SavedObjectsImportRetry[] = []) => retries.reduce( @@ -70,11 +70,7 @@ export async function getNonExistingReferenceAsKeys( (obj) => obj.error && obj.error.statusCode !== 404 ); if (erroredObjects.length) { - const err = Boom.badRequest(); - err.output.payload.attributes = { - objects: erroredObjects, - }; - throw err; + throw SavedObjectsImportError.referencesFetchError(erroredObjects); } // Cleanup collector @@ -95,7 +91,7 @@ export async function validateReferences( retries?: SavedObjectsImportRetry[] ) { const objectsToSkip = getObjectsToSkip(retries); - const errorMap: { [key: string]: SavedObjectsImportError } = {}; + const errorMap: { [key: string]: SavedObjectsImportFailure } = {}; const nonExistingReferenceKeys = await getNonExistingReferenceAsKeys( savedObjects, savedObjectsClient, diff --git a/src/core/server/saved_objects/import/validate_retries.test.ts b/src/core/server/saved_objects/import/lib/validate_retries.test.ts similarity index 85% rename from src/core/server/saved_objects/import/validate_retries.test.ts rename to src/core/server/saved_objects/import/lib/validate_retries.test.ts index fd3c1e9795f9f6..1583296a4a3ab8 100644 --- a/src/core/server/saved_objects/import/validate_retries.test.ts +++ b/src/core/server/saved_objects/import/lib/validate_retries.test.ts @@ -18,7 +18,8 @@ */ import { validateRetries } from './validate_retries'; -import { SavedObjectsImportRetry } from '.'; +import { SavedObjectsImportRetry } from '../types'; +import { SavedObjectsImportError } from '../errors'; import { getNonUniqueEntries } from './get_non_unique_entries'; jest.mock('./get_non_unique_entries'); @@ -62,29 +63,29 @@ describe('#validateRetries', () => { }); describe('results', () => { - test('throws Boom error if any retry objects are not unique', () => { + test('throws import error if any retry objects are not unique', () => { mockGetNonUniqueEntries.mockReturnValue(['type1:id1', 'type2:id2']); expect.assertions(2); try { validateRetries([]); - } catch ({ isBoom, message }) { - expect(isBoom).toBe(true); - expect(message).toMatchInlineSnapshot( - `"Non-unique retry objects: [type1:id1,type2:id2]: Bad Request"` + } catch (e) { + expect(e).toBeInstanceOf(SavedObjectsImportError); + expect(e.message).toMatchInlineSnapshot( + `"Non-unique retry objects: [type1:id1,type2:id2]"` ); } }); - test('throws Boom error if any retry destinations are not unique', () => { + test('throws import error if any retry destinations are not unique', () => { mockGetNonUniqueEntries.mockReturnValueOnce([]); mockGetNonUniqueEntries.mockReturnValue(['type1:id1', 'type2:id2']); expect.assertions(2); try { validateRetries([]); - } catch ({ isBoom, message }) { - expect(isBoom).toBe(true); - expect(message).toMatchInlineSnapshot( - `"Non-unique retry destinations: [type1:id1,type2:id2]: Bad Request"` + } catch (e) { + expect(e).toBeInstanceOf(SavedObjectsImportError); + expect(e.message).toMatchInlineSnapshot( + `"Non-unique retry destinations: [type1:id1,type2:id2]"` ); } }); diff --git a/src/core/server/saved_objects/import/validate_retries.ts b/src/core/server/saved_objects/import/lib/validate_retries.ts similarity index 78% rename from src/core/server/saved_objects/import/validate_retries.ts rename to src/core/server/saved_objects/import/lib/validate_retries.ts index f625436edb6362..d18f6062b7715b 100644 --- a/src/core/server/saved_objects/import/validate_retries.ts +++ b/src/core/server/saved_objects/import/lib/validate_retries.ts @@ -17,16 +17,14 @@ * under the License. */ -import { SavedObjectsImportRetry } from './types'; +import { SavedObjectsImportRetry } from '../types'; import { getNonUniqueEntries } from './get_non_unique_entries'; -import { SavedObjectsErrorHelpers } from '..'; +import { SavedObjectsImportError } from '../errors'; export const validateRetries = (retries: SavedObjectsImportRetry[]) => { const nonUniqueRetryObjects = getNonUniqueEntries(retries); if (nonUniqueRetryObjects.length > 0) { - throw SavedObjectsErrorHelpers.createBadRequestError( - `Non-unique retry objects: [${nonUniqueRetryObjects.join()}]` - ); + throw SavedObjectsImportError.nonUniqueRetryObjects(nonUniqueRetryObjects); } const destinationEntries = retries @@ -34,8 +32,6 @@ export const validateRetries = (retries: SavedObjectsImportRetry[]) => { .map(({ type, destinationId }) => ({ type, id: destinationId! })); const nonUniqueRetryDestinations = getNonUniqueEntries(destinationEntries); if (nonUniqueRetryDestinations.length > 0) { - throw SavedObjectsErrorHelpers.createBadRequestError( - `Non-unique retry destinations: [${nonUniqueRetryDestinations.join()}]` - ); + throw SavedObjectsImportError.nonUniqueRetryDestinations(nonUniqueRetryDestinations); } }; diff --git a/src/core/server/saved_objects/import/resolve_import_errors.test.ts b/src/core/server/saved_objects/import/resolve_import_errors.test.ts index a9dd00eb4ce928..079bc14342927d 100644 --- a/src/core/server/saved_objects/import/resolve_import_errors.test.ts +++ b/src/core/server/saved_objects/import/resolve_import_errors.test.ts @@ -23,34 +23,39 @@ import { SavedObjectsClientContract, SavedObjectsType, SavedObject, - SavedObjectsImportError, + SavedObjectsImportFailure, SavedObjectsImportRetry, SavedObjectReference, } from '../types'; import { savedObjectsClientMock } from '../../mocks'; -import { SavedObjectsResolveImportErrorsOptions, ISavedObjectTypeRegistry } from '..'; +import { ISavedObjectTypeRegistry } from '..'; import { typeRegistryMock } from '../saved_objects_type_registry.mock'; -import { resolveSavedObjectsImportErrors } from './resolve_import_errors'; - -import { validateRetries } from './validate_retries'; -import { collectSavedObjects } from './collect_saved_objects'; -import { regenerateIds } from './regenerate_ids'; -import { validateReferences } from './validate_references'; -import { checkConflicts } from './check_conflicts'; -import { getImportIdMapForRetries } from './check_origin_conflicts'; -import { splitOverwrites } from './split_overwrites'; -import { createSavedObjects } from './create_saved_objects'; -import { createObjectsFilter } from './create_objects_filter'; - -jest.mock('./validate_retries'); -jest.mock('./create_objects_filter'); -jest.mock('./collect_saved_objects'); -jest.mock('./regenerate_ids'); -jest.mock('./validate_references'); -jest.mock('./check_conflicts'); -jest.mock('./check_origin_conflicts'); -jest.mock('./split_overwrites'); -jest.mock('./create_saved_objects'); +import { + resolveSavedObjectsImportErrors, + ResolveSavedObjectsImportErrorsOptions, +} from './resolve_import_errors'; + +import { + validateRetries, + collectSavedObjects, + regenerateIds, + validateReferences, + checkConflicts, + getImportIdMapForRetries, + splitOverwrites, + createSavedObjects, + createObjectsFilter, +} from './lib'; + +jest.mock('./lib/validate_retries'); +jest.mock('./lib/create_objects_filter'); +jest.mock('./lib/collect_saved_objects'); +jest.mock('./lib/regenerate_ids'); +jest.mock('./lib/validate_references'); +jest.mock('./lib/check_conflicts'); +jest.mock('./lib/check_origin_conflicts'); +jest.mock('./lib/split_overwrites'); +jest.mock('./lib/create_saved_objects'); const getMockFn = any, U>(fn: (...args: Parameters) => U) => fn as jest.MockedFunction<(...args: Parameters) => U>; @@ -95,7 +100,7 @@ describe('#importSavedObjectsFromStream', () => { // other attributes aren't needed for the purposes of injecting metadata management: { icon: `${type}-icon` }, } as any) - ): SavedObjectsResolveImportErrorsOptions => { + ): ResolveSavedObjectsImportErrorsOptions => { readStream = new Readable(); savedObjectsClient = savedObjectsClientMock.create(); typeRegistry = typeRegistryMock.create(); @@ -134,7 +139,7 @@ describe('#importSavedObjectsFromStream', () => { attributes: { title }, }; }; - const createError = (): SavedObjectsImportError => { + const createError = (): SavedObjectsImportFailure => { const title = 'some-title'; return { type: 'foo-type', diff --git a/src/core/server/saved_objects/import/resolve_import_errors.ts b/src/core/server/saved_objects/import/resolve_import_errors.ts index e1d7075b9371ba..9df338a765cfd2 100644 --- a/src/core/server/saved_objects/import/resolve_import_errors.ts +++ b/src/core/server/saved_objects/import/resolve_import_errors.ts @@ -16,22 +16,46 @@ * specific language governing permissions and limitations * under the License. */ -import { collectSavedObjects } from './collect_saved_objects'; -import { createObjectsFilter } from './create_objects_filter'; -import { splitOverwrites } from './split_overwrites'; + +import { Readable } from 'stream'; +import { SavedObject, SavedObjectsClientContract, SavedObjectsImportRetry } from '../types'; +import { ISavedObjectTypeRegistry } from '../saved_objects_type_registry'; import { - SavedObjectsImportError, + SavedObjectsImportFailure, SavedObjectsImportResponse, - SavedObjectsResolveImportErrorsOptions, SavedObjectsImportSuccess, } from './types'; -import { regenerateIds } from './regenerate_ids'; -import { validateReferences } from './validate_references'; -import { validateRetries } from './validate_retries'; -import { createSavedObjects } from './create_saved_objects'; -import { getImportIdMapForRetries } from './check_origin_conflicts'; -import { SavedObject } from '../types'; -import { checkConflicts } from './check_conflicts'; +import { + collectSavedObjects, + createObjectsFilter, + splitOverwrites, + regenerateIds, + validateReferences, + validateRetries, + createSavedObjects, + getImportIdMapForRetries, + checkConflicts, +} from './lib'; + +/** + * Options to control the "resolve import" operation. + */ +export interface ResolveSavedObjectsImportErrorsOptions { + /** The stream of {@link SavedObject | saved objects} to resolve errors from */ + readStream: Readable; + /** The maximum number of object to import */ + objectLimit: number; + /** client to use to perform the import operation */ + savedObjectsClient: SavedObjectsClientContract; + /** The registry of all known saved object types */ + typeRegistry: ISavedObjectTypeRegistry; + /** saved object import references to retry */ + retries: SavedObjectsImportRetry[]; + /** if specified, will import in given namespace */ + namespace?: string; + /** If true, will create new copies of import objects, each with a random `id` and undefined `originId`. */ + createNewCopies: boolean; +} /** * Resolve and return saved object import errors. @@ -47,12 +71,12 @@ export async function resolveSavedObjectsImportErrors({ typeRegistry, namespace, createNewCopies, -}: SavedObjectsResolveImportErrorsOptions): Promise { +}: ResolveSavedObjectsImportErrorsOptions): Promise { // throw a BadRequest error if we see invalid retries validateRetries(retries); let successCount = 0; - let errorAccumulator: SavedObjectsImportError[] = []; + let errorAccumulator: SavedObjectsImportFailure[] = []; let importIdMap: Map = new Map(); const supportedTypes = typeRegistry.getImportableAndExportableTypes().map((type) => type.name); const filter = createObjectsFilter(retries); diff --git a/src/core/server/saved_objects/import/saved_objects_importer.mock.ts b/src/core/server/saved_objects/import/saved_objects_importer.mock.ts new file mode 100644 index 00000000000000..d122a9b7c34e50 --- /dev/null +++ b/src/core/server/saved_objects/import/saved_objects_importer.mock.ts @@ -0,0 +1,33 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ISavedObjectsImporter } from './saved_objects_importer'; + +const createImporterMock = () => { + const mock: jest.Mocked = { + import: jest.fn(), + resolveImportErrors: jest.fn(), + }; + + return mock; +}; + +export const savedObjectsImporterMock = { + create: createImporterMock, +}; diff --git a/src/core/server/saved_objects/import/saved_objects_importer.ts b/src/core/server/saved_objects/import/saved_objects_importer.ts new file mode 100644 index 00000000000000..11ba104f47b495 --- /dev/null +++ b/src/core/server/saved_objects/import/saved_objects_importer.ts @@ -0,0 +1,103 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PublicMethodsOf } from '@kbn/utility-types'; +import { SavedObjectsClientContract } from '../types'; +import { ISavedObjectTypeRegistry } from '../saved_objects_type_registry'; +import { importSavedObjectsFromStream } from './import_saved_objects'; +import { resolveSavedObjectsImportErrors } from './resolve_import_errors'; +import { + SavedObjectsImportResponse, + SavedObjectsImportOptions, + SavedObjectsResolveImportErrorsOptions, +} from './types'; + +/** + * @public + */ +export type ISavedObjectsImporter = PublicMethodsOf; + +/** + * @public + */ +export class SavedObjectsImporter { + readonly #savedObjectsClient: SavedObjectsClientContract; + readonly #typeRegistry: ISavedObjectTypeRegistry; + readonly #importSizeLimit: number; + + constructor({ + savedObjectsClient, + typeRegistry, + importSizeLimit, + }: { + savedObjectsClient: SavedObjectsClientContract; + typeRegistry: ISavedObjectTypeRegistry; + importSizeLimit: number; + }) { + this.#savedObjectsClient = savedObjectsClient; + this.#typeRegistry = typeRegistry; + this.#importSizeLimit = importSizeLimit; + } + + /** + * Import saved objects from given stream. See the {@link SavedObjectsImportOptions | options} for more + * detailed information. + * + * @throws SavedObjectsImportError + */ + import({ + readStream, + createNewCopies, + namespace, + overwrite, + }: SavedObjectsImportOptions): Promise { + return importSavedObjectsFromStream({ + readStream, + createNewCopies, + namespace, + overwrite, + objectLimit: this.#importSizeLimit, + savedObjectsClient: this.#savedObjectsClient, + typeRegistry: this.#typeRegistry, + }); + } + + /** + * Resolve and return saved object import errors. + * See the {@link SavedObjectsResolveImportErrorsOptions | options} for more detailed informations. + * + * @throws SavedObjectsImportError + */ + resolveImportErrors({ + readStream, + createNewCopies, + namespace, + retries, + }: SavedObjectsResolveImportErrorsOptions): Promise { + return resolveSavedObjectsImportErrors({ + readStream, + createNewCopies, + namespace, + retries, + objectLimit: this.#importSizeLimit, + savedObjectsClient: this.#savedObjectsClient, + typeRegistry: this.#typeRegistry, + }); + } +} diff --git a/src/core/server/saved_objects/import/types.ts b/src/core/server/saved_objects/import/types.ts index a242ffdf5b50f1..5a1793d39739e6 100644 --- a/src/core/server/saved_objects/import/types.ts +++ b/src/core/server/saved_objects/import/types.ts @@ -18,8 +18,7 @@ */ import { Readable } from 'stream'; -import { SavedObjectsClientContract, SavedObject } from '../types'; -import { ISavedObjectTypeRegistry } from '..'; +import { SavedObject } from '../types'; /** * Describes a retry operation for importing a saved object. @@ -98,7 +97,7 @@ export interface SavedObjectsImportMissingReferencesError { * Represents a failure to import. * @public */ -export interface SavedObjectsImportError { +export interface SavedObjectsImportFailure { id: string; type: string; /** @@ -154,7 +153,7 @@ export interface SavedObjectsImportResponse { success: boolean; successCount: number; successResults?: SavedObjectsImportSuccess[]; - errors?: SavedObjectsImportError[]; + errors?: SavedObjectsImportFailure[]; } /** @@ -164,14 +163,8 @@ export interface SavedObjectsImportResponse { export interface SavedObjectsImportOptions { /** The stream of {@link SavedObject | saved objects} to import */ readStream: Readable; - /** The maximum number of object to import */ - objectLimit: number; /** If true, will override existing object if present. Note: this has no effect when used with the `createNewCopies` option. */ overwrite: boolean; - /** {@link SavedObjectsClientContract | client} to use to perform the import operation */ - savedObjectsClient: SavedObjectsClientContract; - /** The registry of all known saved object types */ - typeRegistry: ISavedObjectTypeRegistry; /** if specified, will import in given namespace, else will import as global object */ namespace?: string; /** If true, will create new copies of import objects, each with a random `id` and undefined `originId`. */ @@ -185,12 +178,6 @@ export interface SavedObjectsImportOptions { export interface SavedObjectsResolveImportErrorsOptions { /** The stream of {@link SavedObject | saved objects} to resolve errors from */ readStream: Readable; - /** The maximum number of object to import */ - objectLimit: number; - /** client to use to perform the import operation */ - savedObjectsClient: SavedObjectsClientContract; - /** The registry of all known saved object types */ - typeRegistry: ISavedObjectTypeRegistry; /** saved object import references to retry */ retries: SavedObjectsImportRetry[]; /** if specified, will import in given namespace */ diff --git a/src/core/server/saved_objects/index.ts b/src/core/server/saved_objects/index.ts index 7a0088094e841a..2d9e2f2b247fe0 100644 --- a/src/core/server/saved_objects/index.ts +++ b/src/core/server/saved_objects/index.ts @@ -19,12 +19,31 @@ export * from './service'; -export * from './import'; +export { + ISavedObjectsImporter, + SavedObjectsImporter, + SavedObjectsImportAmbiguousConflictError, + SavedObjectsImportConflictError, + SavedObjectsImportFailure, + SavedObjectsImportMissingReferencesError, + SavedObjectsImportOptions, + SavedObjectsImportResponse, + SavedObjectsImportRetry, + SavedObjectsImportSuccess, + SavedObjectsImportUnknownError, + SavedObjectsImportUnsupportedTypeError, + SavedObjectsResolveImportErrorsOptions, + SavedObjectsImportError, +} from './import'; export { - exportSavedObjectsToStream, - SavedObjectsExportOptions, + SavedObjectsExporter, + ISavedObjectsExporter, + SavedObjectExportBaseOptions, + SavedObjectsExportByTypeOptions, + SavedObjectsExportByObjectOptions, SavedObjectsExportResultDetails, + SavedObjectsExportError, } from './export'; export { diff --git a/src/core/server/saved_objects/routes/export.ts b/src/core/server/saved_objects/routes/export.ts index 8f5c19d927d400..6343e535f4db31 100644 --- a/src/core/server/saved_objects/routes/export.ts +++ b/src/core/server/saved_objects/routes/export.ts @@ -24,7 +24,11 @@ import { createPromiseFromStreams, createMapStream, createConcatStream } from '@ import { IRouter } from '../../http'; import { CoreUsageDataSetup } from '../../core_usage_data'; import { SavedObjectConfig } from '../saved_objects_config'; -import { exportSavedObjectsToStream } from '../export'; +import { + SavedObjectsExportByTypeOptions, + SavedObjectsExportByObjectOptions, + SavedObjectsExportError, +} from '../export'; import { validateTypes, validateObjects } from './utils'; interface RouteDependencies { @@ -32,6 +36,103 @@ interface RouteDependencies { coreUsageData: CoreUsageDataSetup; } +type EitherExportOptions = SavedObjectsExportByTypeOptions | SavedObjectsExportByObjectOptions; + +interface ExportRawOptions { + type?: string | string[]; + hasReference?: { id: string; type: string } | Array<{ id: string; type: string }>; + objects?: Array<{ id: string; type: string }>; + search?: string; + includeReferencesDeep: boolean; + excludeExportDetails: boolean; +} + +interface ExportOptions { + types?: string[]; + hasReference?: Array<{ id: string; type: string }>; + objects?: Array<{ id: string; type: string }>; + search?: string; + includeReferencesDeep: boolean; + excludeExportDetails: boolean; +} + +const cleanOptions = ({ + type, + objects, + search, + hasReference, + excludeExportDetails, + includeReferencesDeep, +}: ExportRawOptions): ExportOptions => { + return { + types: typeof type === 'string' ? [type] : type, + search, + objects, + hasReference: hasReference && !Array.isArray(hasReference) ? [hasReference] : hasReference, + excludeExportDetails, + includeReferencesDeep, + }; +}; + +const isExportByTypeOptions = ( + options: EitherExportOptions +): options is SavedObjectsExportByTypeOptions => { + return Boolean((options as SavedObjectsExportByTypeOptions).types); +}; + +const validateOptions = ( + { + types, + objects, + excludeExportDetails, + hasReference, + includeReferencesDeep, + search, + }: ExportOptions, + { exportSizeLimit, supportedTypes }: { exportSizeLimit: number; supportedTypes: string[] } +): EitherExportOptions => { + const hasTypes = (types?.length ?? 0) > 0; + const hasObjects = (objects?.length ?? 0) > 0; + if (!hasTypes && !hasObjects) { + throw new Error('Either `type` or `objects` are required.'); + } + if (hasTypes && hasObjects) { + throw new Error(`Can't specify both "types" and "objects" properties when exporting`); + } + if (hasObjects) { + if (objects!.length > exportSizeLimit) { + throw new Error(`Can't export more than ${exportSizeLimit} objects`); + } + if (typeof search === 'string') { + throw new Error(`Can't specify both "search" and "objects" properties when exporting`); + } + if (hasReference && hasReference.length) { + throw new Error(`Can't specify both "references" and "objects" properties when exporting`); + } + const validationError = validateObjects(objects!, supportedTypes); + if (validationError) { + throw new Error(validationError); + } + return { + objects: objects!, + excludeExportDetails, + includeReferencesDeep, + }; + } else { + const validationError = validateTypes(types!, supportedTypes); + if (validationError) { + throw new Error(validationError); + } + return { + types: types!, + hasReference, + search, + excludeExportDetails, + includeReferencesDeep, + }; + } +}; + export const registerExportRoute = ( router: IRouter, { config, coreUsageData }: RouteDependencies @@ -68,73 +169,60 @@ export const registerExportRoute = ( }, }, router.handleLegacyErrors(async (context, req, res) => { - const savedObjectsClient = context.core.savedObjects.client; - const { - type, - hasReference, - objects, - search, - excludeExportDetails, - includeReferencesDeep, - } = req.body; - const types = typeof type === 'string' ? [type] : type; - - // need to access the registry for type validation, can't use the schema for this + const cleaned = cleanOptions(req.body); const supportedTypes = context.core.savedObjects.typeRegistry .getImportableAndExportableTypes() .map((t) => t.name); - if (types) { - const validationError = validateTypes(types, supportedTypes); - if (validationError) { - return res.badRequest({ - body: { - message: validationError, - }, - }); - } + let options: EitherExportOptions; + try { + options = validateOptions(cleaned, { + exportSizeLimit: maxImportExportSize, + supportedTypes, + }); + } catch (e) { + return res.badRequest({ + body: e, + }); } - if (objects) { - const validationError = validateObjects(objects, supportedTypes); - if (validationError) { + + const exporter = context.core.savedObjects.exporter; + + const usageStatsClient = coreUsageData.getClient(); + usageStatsClient + .incrementSavedObjectsExport({ request: req, types: cleaned.types, supportedTypes }) + .catch(() => {}); + + try { + const exportStream = isExportByTypeOptions(options) + ? await exporter.exportByTypes(options) + : await exporter.exportByObjects(options); + + const docsToExport: string[] = await createPromiseFromStreams([ + exportStream, + createMapStream((obj: unknown) => { + return stringify(obj); + }), + createConcatStream([]), + ]); + + return res.ok({ + body: docsToExport.join('\n'), + headers: { + 'Content-Disposition': `attachment; filename="export.ndjson"`, + 'Content-Type': 'application/ndjson', + }, + }); + } catch (e) { + if (e instanceof SavedObjectsExportError) { return res.badRequest({ body: { - message: validationError, + message: e.message, + attributes: e.attributes, }, }); } + throw e; } - - const usageStatsClient = coreUsageData.getClient(); - usageStatsClient - .incrementSavedObjectsExport({ request: req, types, supportedTypes }) - .catch(() => {}); - - const exportStream = await exportSavedObjectsToStream({ - savedObjectsClient, - types, - hasReference: hasReference && !Array.isArray(hasReference) ? [hasReference] : hasReference, - search, - objects, - exportSizeLimit: maxImportExportSize, - includeReferencesDeep, - excludeExportDetails, - }); - - const docsToExport: string[] = await createPromiseFromStreams([ - exportStream, - createMapStream((obj: unknown) => { - return stringify(obj); - }), - createConcatStream([]), - ]); - - return res.ok({ - body: docsToExport.join('\n'), - headers: { - 'Content-Disposition': `attachment; filename="export.ndjson"`, - 'Content-Type': 'application/ndjson', - }, - }); }) ); }; diff --git a/src/core/server/saved_objects/routes/import.ts b/src/core/server/saved_objects/routes/import.ts index ebc52c32e2c709..abd0f4335d9c5e 100644 --- a/src/core/server/saved_objects/routes/import.ts +++ b/src/core/server/saved_objects/routes/import.ts @@ -22,8 +22,8 @@ import { extname } from 'path'; import { schema } from '@kbn/config-schema'; import { IRouter } from '../../http'; import { CoreUsageDataSetup } from '../../core_usage_data'; -import { importSavedObjectsFromStream } from '../import'; import { SavedObjectConfig } from '../saved_objects_config'; +import { SavedObjectsImportError } from '../import'; import { createSavedObjectsStreamFromNdJson } from './utils'; interface RouteDependencies { @@ -41,7 +41,7 @@ export const registerImportRoute = ( router: IRouter, { config, coreUsageData }: RouteDependencies ) => { - const { maxImportExportSize, maxImportPayloadBytes } = config; + const { maxImportPayloadBytes } = config; router.post( { @@ -95,16 +95,26 @@ export const registerImportRoute = ( }); } - const result = await importSavedObjectsFromStream({ - savedObjectsClient: context.core.savedObjects.client, - typeRegistry: context.core.savedObjects.typeRegistry, - readStream, - objectLimit: maxImportExportSize, - overwrite, - createNewCopies, - }); + const { importer } = context.core.savedObjects; + try { + const result = await importer.import({ + readStream, + overwrite, + createNewCopies, + }); - return res.ok({ body: result }); + return res.ok({ body: result }); + } catch (e) { + if (e instanceof SavedObjectsImportError) { + return res.badRequest({ + body: { + message: e.message, + attributes: e.attributes, + }, + }); + } + throw e; + } }) ); }; diff --git a/src/core/server/saved_objects/routes/integration_tests/export.test.ts b/src/core/server/saved_objects/routes/integration_tests/export.test.ts index d5b1e492e573fc..752b02aa3dcc69 100644 --- a/src/core/server/saved_objects/routes/integration_tests/export.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/export.test.ts @@ -21,19 +21,18 @@ jest.mock('../../export', () => ({ exportSavedObjectsToStream: jest.fn(), })); -import * as exportMock from '../../export'; import supertest from 'supertest'; import type { UnwrapPromise } from '@kbn/utility-types'; import { createListStream } from '@kbn/utils'; import { CoreUsageStatsClient } from '../../../core_usage_data'; import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_stats_client.mock'; import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; +import { savedObjectsExporterMock } from '../../export/saved_objects_exporter.mock'; import { SavedObjectConfig } from '../../saved_objects_config'; import { registerExportRoute } from '../export'; import { setupServer, createExportableType } from '../test_utils'; type SetupServerReturn = UnwrapPromise>; -const exportSavedObjectsToStream = exportMock.exportSavedObjectsToStream as jest.Mock; const allowedTypes = ['index-pattern', 'search']; const config = { maxImportPayloadBytes: 26214400, @@ -45,12 +44,14 @@ describe('POST /api/saved_objects/_export', () => { let server: SetupServerReturn['server']; let httpSetup: SetupServerReturn['httpSetup']; let handlerContext: SetupServerReturn['handlerContext']; + let exporter: ReturnType; beforeEach(async () => { ({ server, httpSetup, handlerContext } = await setupServer()); handlerContext.savedObjects.typeRegistry.getImportableAndExportableTypes.mockReturnValue( allowedTypes.map(createExportableType) ); + exporter = handlerContext.savedObjects.exporter; const router = httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); @@ -87,7 +88,7 @@ describe('POST /api/saved_objects/_export', () => { ], }, ]; - exportSavedObjectsToStream.mockResolvedValueOnce(createListStream(sortedObjects)); + exporter.exportByTypes.mockResolvedValueOnce(createListStream(sortedObjects)); const result = await supertest(httpSetup.server.listener) .post('/api/saved_objects/_export') @@ -107,12 +108,10 @@ describe('POST /api/saved_objects/_export', () => { const objects = (result.text as string).split('\n').map((row) => JSON.parse(row)); expect(objects).toEqual(sortedObjects); - expect(exportSavedObjectsToStream.mock.calls[0][0]).toEqual( + expect(exporter.exportByTypes.mock.calls[0][0]).toEqual( expect.objectContaining({ excludeExportDetails: false, - exportSizeLimit: 10000, includeReferencesDeep: true, - objects: undefined, search: 'my search string', types: ['search'], }) diff --git a/src/core/server/saved_objects/routes/integration_tests/import.test.ts b/src/core/server/saved_objects/routes/integration_tests/import.test.ts index b80deb87725d48..16d07f2a94d3a1 100644 --- a/src/core/server/saved_objects/routes/integration_tests/import.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/import.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { mockUuidv4 } from '../../import/__mocks__'; +import { mockUuidv4 } from '../../import/lib/__mocks__'; import supertest from 'supertest'; import { UnwrapPromise } from '@kbn/utility-types'; import { registerImportRoute } from '../import'; @@ -27,7 +27,7 @@ import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_st import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; import { SavedObjectConfig } from '../../saved_objects_config'; import { setupServer, createExportableType } from '../test_utils'; -import { SavedObjectsErrorHelpers } from '../..'; +import { SavedObjectsErrorHelpers, SavedObjectsImporter } from '../..'; type SetupServerReturn = UnwrapPromise>; @@ -74,6 +74,15 @@ describe(`POST ${URL}`, () => { savedObjectsClient.find.mockResolvedValue(emptyResponse); savedObjectsClient.checkConflicts.mockResolvedValue({ errors: [] }); + const importer = new SavedObjectsImporter({ + savedObjectsClient, + typeRegistry: handlerContext.savedObjects.typeRegistry, + importSizeLimit: 10000, + }); + handlerContext.savedObjects.importer.import.mockImplementation((options) => + importer.import(options) + ); + const router = httpSetup.createRouter('/internal/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsImport.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail diff --git a/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts b/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts index f135e34231cb66..2207f2c69ec749 100644 --- a/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/resolve_import_errors.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { mockUuidv4 } from '../../import/__mocks__'; +import { mockUuidv4 } from '../../import/lib/__mocks__'; import supertest from 'supertest'; import { UnwrapPromise } from '@kbn/utility-types'; import { registerResolveImportErrorsRoute } from '../resolve_import_errors'; @@ -27,6 +27,7 @@ import { coreUsageStatsClientMock } from '../../../core_usage_data/core_usage_st import { coreUsageDataServiceMock } from '../../../core_usage_data/core_usage_data_service.mock'; import { setupServer, createExportableType } from '../test_utils'; import { SavedObjectConfig } from '../../saved_objects_config'; +import { SavedObjectsImporter } from '../..'; type SetupServerReturn = UnwrapPromise>; @@ -79,6 +80,15 @@ describe(`POST ${URL}`, () => { savedObjectsClient = handlerContext.savedObjects.client; savedObjectsClient.checkConflicts.mockResolvedValue({ errors: [] }); + const importer = new SavedObjectsImporter({ + savedObjectsClient, + typeRegistry: handlerContext.savedObjects.typeRegistry, + importSizeLimit: 10000, + }); + handlerContext.savedObjects.importer.resolveImportErrors.mockImplementation((options) => + importer.resolveImportErrors(options) + ); + const router = httpSetup.createRouter('/api/saved_objects/'); coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsResolveImportErrors.mockRejectedValue( diff --git a/src/core/server/saved_objects/routes/resolve_import_errors.ts b/src/core/server/saved_objects/routes/resolve_import_errors.ts index 5db5454b224d7b..5df0a862fee2aa 100644 --- a/src/core/server/saved_objects/routes/resolve_import_errors.ts +++ b/src/core/server/saved_objects/routes/resolve_import_errors.ts @@ -22,8 +22,8 @@ import { Readable } from 'stream'; import { schema } from '@kbn/config-schema'; import { IRouter } from '../../http'; import { CoreUsageDataSetup } from '../../core_usage_data'; -import { resolveSavedObjectsImportErrors } from '../import'; import { SavedObjectConfig } from '../saved_objects_config'; +import { SavedObjectsImportError } from '../import'; import { createSavedObjectsStreamFromNdJson } from './utils'; interface RouteDependencies { @@ -41,7 +41,7 @@ export const registerResolveImportErrorsRoute = ( router: IRouter, { config, coreUsageData }: RouteDependencies ) => { - const { maxImportExportSize, maxImportPayloadBytes } = config; + const { maxImportPayloadBytes } = config; router.post( { @@ -103,16 +103,27 @@ export const registerResolveImportErrorsRoute = ( }); } - const result = await resolveSavedObjectsImportErrors({ - typeRegistry: context.core.savedObjects.typeRegistry, - savedObjectsClient: context.core.savedObjects.client, - readStream, - retries: req.body.retries, - objectLimit: maxImportExportSize, - createNewCopies, - }); + const { importer } = context.core.savedObjects; - return res.ok({ body: result }); + try { + const result = await importer.resolveImportErrors({ + readStream, + retries: req.body.retries, + createNewCopies, + }); + + return res.ok({ body: result }); + } catch (e) { + if (e instanceof SavedObjectsImportError) { + return res.badRequest({ + body: { + message: e.message, + attributes: e.attributes, + }, + }); + } + throw e; + } }) ); }; diff --git a/src/core/server/saved_objects/saved_objects_service.mock.ts b/src/core/server/saved_objects/saved_objects_service.mock.ts index 85dbf4b5e8c6a5..1a920501541b66 100644 --- a/src/core/server/saved_objects/saved_objects_service.mock.ts +++ b/src/core/server/saved_objects/saved_objects_service.mock.ts @@ -30,6 +30,8 @@ import type { import { savedObjectsRepositoryMock } from './service/lib/repository.mock'; import { savedObjectsClientMock } from './service/saved_objects_client.mock'; import { typeRegistryMock } from './saved_objects_type_registry.mock'; +import { savedObjectsExporterMock } from './export/saved_objects_exporter.mock'; +import { savedObjectsImporterMock } from './import/saved_objects_importer.mock'; import { migrationMocks } from './migrations/mocks'; import { ServiceStatusLevels } from '../status'; import { ISavedObjectTypeRegistry } from './saved_objects_type_registry'; @@ -42,6 +44,8 @@ const createStartContractMock = (typeRegistry?: jest.Mocked { setClientFactoryProvider: jest.fn(), addClientWrapper: jest.fn(), registerType: jest.fn(), - getImportExportObjectLimit: jest.fn(), }; - setupContract.getImportExportObjectLimit.mockReturnValue(100); - return setupContract; }; @@ -106,4 +109,6 @@ export const savedObjectsServiceMock = { createStartContract: createStartContractMock, createMigrationContext: migrationMocks.createContext, createTypeRegistryMock: typeRegistryMock.create, + createExporter: savedObjectsExporterMock.create, + createImporter: savedObjectsImporterMock.create, }; diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts index d2e4d8c5cbb2d2..c34da35a355314 100644 --- a/src/core/server/saved_objects/saved_objects_service.ts +++ b/src/core/server/saved_objects/saved_objects_service.ts @@ -49,6 +49,8 @@ import { import { Logger } from '../logging'; import { SavedObjectTypeRegistry, ISavedObjectTypeRegistry } from './saved_objects_type_registry'; import { SavedObjectsSerializer } from './serialization'; +import { SavedObjectsExporter, ISavedObjectsExporter } from './export'; +import { SavedObjectsImporter, ISavedObjectsImporter } from './import'; import { registerRoutes } from './routes'; import { ServiceStatus } from '../status'; import { calculateStatus$ } from './status'; @@ -149,11 +151,6 @@ export interface SavedObjectsServiceSetup { * ``` */ registerType: (type: SavedObjectsType) => void; - - /** - * Returns the maximum number of objects allowed for import or export operations. - */ - getImportExportObjectLimit: () => number; } /** @@ -212,6 +209,14 @@ export interface SavedObjectsServiceStart { * Creates a {@link SavedObjectsSerializer | serializer} that is aware of all registered types. */ createSerializer: () => SavedObjectsSerializer; + /** + * Creates an {@link ISavedObjectsExporter | exporter} bound to given client. + */ + createExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter; + /** + * Creates an {@link ISavedObjectsImporter | importer} bound to given client. + */ + createImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter; /** * Returns the {@link ISavedObjectTypeRegistry | registry} containing all registered * {@link SavedObjectsType | saved object types} @@ -340,7 +345,6 @@ export class SavedObjectsService } this.typeRegistry.registerType(type); }, - getImportExportObjectLimit: () => this.config!.maxImportExportSize, }; } @@ -451,6 +455,17 @@ export class SavedObjectsService createScopedRepository: repositoryFactory.createScopedRepository, createInternalRepository: repositoryFactory.createInternalRepository, createSerializer: () => new SavedObjectsSerializer(this.typeRegistry), + createExporter: (savedObjectsClient) => + new SavedObjectsExporter({ + savedObjectsClient, + exportSizeLimit: this.config!.maxImportExportSize, + }), + createImporter: (savedObjectsClient) => + new SavedObjectsImporter({ + savedObjectsClient, + typeRegistry: this.typeRegistry, + importSizeLimit: this.config!.maxImportExportSize, + }), getTypeRegistry: () => this.typeRegistry, }; } diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index b16eeb2aa03a69..c8f8b47949ca50 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -29,7 +29,7 @@ export { SavedObjectsImportUnsupportedTypeError, SavedObjectsImportMissingReferencesError, SavedObjectsImportUnknownError, - SavedObjectsImportError, + SavedObjectsImportFailure, SavedObjectsImportRetry, } from './import/types'; diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 848cd3a657e9c3..8c284facb442ea 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -123,6 +123,7 @@ import { PackageInfo } from '@kbn/config'; import { PathConfigType } from '@kbn/utils'; import { PeerCertificate } from 'tls'; import { PingParams } from 'elasticsearch'; +import { PublicMethodsOf } from '@kbn/utility-types'; import { PutScriptParams } from 'elasticsearch'; import { PutTemplateParams } from 'elasticsearch'; import { Readable } from 'stream'; @@ -907,9 +908,6 @@ export interface Explanation { value: number; } -// @public -export function exportSavedObjectsToStream({ types, hasReference, objects, search, savedObjectsClient, exportSizeLimit, includeReferencesDeep, excludeExportDetails, namespace, }: SavedObjectsExportOptions): Promise; - // @public export interface FakeRequest { headers: Headers; @@ -1123,9 +1121,6 @@ export interface ImageValidation { }; } -// @public -export function importSavedObjectsFromStream({ readStream, objectLimit, overwrite, createNewCopies, savedObjectsClient, typeRegistry, namespace, }: SavedObjectsImportOptions): Promise; - // @public @deprecated (undocumented) export interface IndexSettingsDeprecationInfo { // (undocumented) @@ -1157,6 +1152,12 @@ export interface IRouter { // @public export type IsAuthenticated = (request: KibanaRequest | LegacyRequest) => boolean; +// @public (undocumented) +export type ISavedObjectsExporter = PublicMethodsOf; + +// @public (undocumented) +export type ISavedObjectsImporter = PublicMethodsOf; + // @public export type ISavedObjectsRepository = Pick; @@ -1894,6 +1895,8 @@ export interface RequestHandlerContext { savedObjects: { client: SavedObjectsClientContract; typeRegistry: ISavedObjectTypeRegistry; + exporter: ISavedObjectsExporter; + importer: ISavedObjectsImporter; }; elasticsearch: { client: IScopedClusterClient; @@ -1916,9 +1919,6 @@ export type RequestHandlerContextProvider(handler: RequestHandler) => RequestHandler; -// @public -export function resolveSavedObjectsImportErrors({ readStream, objectLimit, retries, savedObjectsClient, typeRegistry, namespace, createNewCopies, }: SavedObjectsResolveImportErrorsOptions): Promise; - // @public export type ResponseError = string | Error | { message: string | Error; @@ -2049,6 +2049,13 @@ export interface SavedObjectAttributes { // @public export type SavedObjectAttributeSingle = string | number | boolean | null | undefined | SavedObjectAttributes; +// @public (undocumented) +export interface SavedObjectExportBaseOptions { + excludeExportDetails?: boolean; + includeReferencesDeep?: boolean; + namespace?: string; +} + // @public export interface SavedObjectMigrationContext { log: SavedObjectsMigrationLogger; @@ -2350,19 +2357,43 @@ export class SavedObjectsErrorHelpers { } // @public -export interface SavedObjectsExportOptions { - excludeExportDetails?: boolean; - exportSizeLimit: number; - hasReference?: SavedObjectsFindOptionsReference[]; - includeReferencesDeep?: boolean; - namespace?: string; - objects?: Array<{ +export interface SavedObjectsExportByObjectOptions extends SavedObjectExportBaseOptions { + objects: Array<{ id: string; type: string; }>; - savedObjectsClient: SavedObjectsClientContract; +} + +// @public +export interface SavedObjectsExportByTypeOptions extends SavedObjectExportBaseOptions { + hasReference?: SavedObjectsFindOptionsReference[]; search?: string; - types?: string[]; + types: string[]; +} + +// @public (undocumented) +export class SavedObjectsExporter { + // (undocumented) + #private; + constructor({ savedObjectsClient, exportSizeLimit, }: { + savedObjectsClient: SavedObjectsClientContract; + exportSizeLimit: number; + }); + exportByObjects(options: SavedObjectsExportByObjectOptions): Promise; + exportByTypes(options: SavedObjectsExportByTypeOptions): Promise; + } + +// @public (undocumented) +export class SavedObjectsExportError extends Error { + constructor(type: string, message: string, attributes?: Record | undefined); + // (undocumented) + readonly attributes?: Record | undefined; + // (undocumented) + static exportSizeExceeded(limit: number): SavedObjectsExportError; + // (undocumented) + static objectFetchError(objects: SavedObject[]): SavedObjectsExportError; + // (undocumented) + readonly type: string; } // @public @@ -2452,8 +2483,39 @@ export interface SavedObjectsImportConflictError { type: 'conflict'; } +// @public (undocumented) +export class SavedObjectsImporter { + // (undocumented) + #private; + constructor({ savedObjectsClient, typeRegistry, importSizeLimit, }: { + savedObjectsClient: SavedObjectsClientContract; + typeRegistry: ISavedObjectTypeRegistry; + importSizeLimit: number; + }); + import({ readStream, createNewCopies, namespace, overwrite, }: SavedObjectsImportOptions): Promise; + resolveImportErrors({ readStream, createNewCopies, namespace, retries, }: SavedObjectsResolveImportErrorsOptions): Promise; +} + +// @public (undocumented) +export class SavedObjectsImportError extends Error { + // (undocumented) + readonly attributes?: Record | undefined; + // (undocumented) + static importSizeExceeded(limit: number): SavedObjectsImportError; + // (undocumented) + static nonUniqueImportObjects(nonUniqueEntries: string[]): SavedObjectsImportError; + // (undocumented) + static nonUniqueRetryDestinations(nonUniqueRetryDestinations: string[]): SavedObjectsImportError; + // (undocumented) + static nonUniqueRetryObjects(nonUniqueRetryObjects: string[]): SavedObjectsImportError; + // (undocumented) + static referencesFetchError(objects: SavedObject[]): SavedObjectsImportError; + // (undocumented) + readonly type: string; +} + // @public -export interface SavedObjectsImportError { +export interface SavedObjectsImportFailure { // (undocumented) error: SavedObjectsImportConflictError | SavedObjectsImportAmbiguousConflictError | SavedObjectsImportUnsupportedTypeError | SavedObjectsImportMissingReferencesError | SavedObjectsImportUnknownError; // (undocumented) @@ -2485,17 +2547,14 @@ export interface SavedObjectsImportMissingReferencesError { export interface SavedObjectsImportOptions { createNewCopies: boolean; namespace?: string; - objectLimit: number; overwrite: boolean; readStream: Readable; - savedObjectsClient: SavedObjectsClientContract; - typeRegistry: ISavedObjectTypeRegistry; } // @public export interface SavedObjectsImportResponse { // (undocumented) - errors?: SavedObjectsImportError[]; + errors?: SavedObjectsImportFailure[]; // (undocumented) success: boolean; // (undocumented) @@ -2656,11 +2715,8 @@ export interface SavedObjectsRepositoryFactory { export interface SavedObjectsResolveImportErrorsOptions { createNewCopies: boolean; namespace?: string; - objectLimit: number; readStream: Readable; retries: SavedObjectsImportRetry[]; - savedObjectsClient: SavedObjectsClientContract; - typeRegistry: ISavedObjectTypeRegistry; } // @public @@ -2676,13 +2732,14 @@ export class SavedObjectsSerializer { // @public export interface SavedObjectsServiceSetup { addClientWrapper: (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void; - getImportExportObjectLimit: () => number; registerType: (type: SavedObjectsType) => void; setClientFactoryProvider: (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void; } // @public export interface SavedObjectsServiceStart { + createExporter: (client: SavedObjectsClientContract) => ISavedObjectsExporter; + createImporter: (client: SavedObjectsClientContract) => ISavedObjectsImporter; createInternalRepository: (includedHiddenTypes?: string[]) => ISavedObjectsRepository; createScopedRepository: (req: KibanaRequest, includedHiddenTypes?: string[]) => ISavedObjectsRepository; createSerializer: () => SavedObjectsSerializer; diff --git a/src/plugins/saved_objects_management/public/lib/import_file.ts b/src/plugins/saved_objects_management/public/lib/import_file.ts index 84177bda3eb43d..bc15954cc2c205 100644 --- a/src/plugins/saved_objects_management/public/lib/import_file.ts +++ b/src/plugins/saved_objects_management/public/lib/import_file.ts @@ -17,13 +17,13 @@ * under the License. */ -import { HttpStart, SavedObjectsImportError } from 'src/core/public'; +import { HttpStart, SavedObjectsImportFailure } from 'src/core/public'; import { ImportMode } from '../management_section/objects_table/components/import_mode_control'; interface ImportResponse { success: boolean; successCount: number; - errors?: SavedObjectsImportError[]; + errors?: SavedObjectsImportFailure[]; } export async function importFile( diff --git a/src/plugins/saved_objects_management/public/lib/process_import_response.ts b/src/plugins/saved_objects_management/public/lib/process_import_response.ts index bb7492bb9b3dec..bfa376b176f8d2 100644 --- a/src/plugins/saved_objects_management/public/lib/process_import_response.ts +++ b/src/plugins/saved_objects_management/public/lib/process_import_response.ts @@ -24,12 +24,12 @@ import { SavedObjectsImportUnsupportedTypeError, SavedObjectsImportMissingReferencesError, SavedObjectsImportUnknownError, - SavedObjectsImportError, + SavedObjectsImportFailure, SavedObjectsImportSuccess, } from 'src/core/public'; export interface FailedImport { - obj: Omit; + obj: Omit; error: | SavedObjectsImportConflictError | SavedObjectsImportAmbiguousConflictError @@ -40,7 +40,7 @@ export interface FailedImport { interface UnmatchedReference { existingIndexPatternId: string; - list: Array>; + list: Array>; newIndexPatternId?: string; } diff --git a/test/api_integration/apis/saved_objects/export.ts b/test/api_integration/apis/saved_objects/export.ts index 7254f3b3fcf316..43bf37275c00f8 100644 --- a/test/api_integration/apis/saved_objects/export.ts +++ b/test/api_integration/apis/saved_objects/export.ts @@ -167,7 +167,7 @@ export default function ({ getService }: FtrProviderContext) { expect(resp.body).to.eql({ statusCode: 400, error: 'Bad Request', - message: 'Bad Request', + message: 'Error fetching objects to export', attributes: { objects: [ { diff --git a/test/api_integration/apis/saved_objects/import.ts b/test/api_integration/apis/saved_objects/import.ts index bdb695ef20dd1a..b661822f4dcd31 100644 --- a/test/api_integration/apis/saved_objects/import.ts +++ b/test/api_integration/apis/saved_objects/import.ts @@ -20,12 +20,12 @@ import expect from '@kbn/expect'; import { join } from 'path'; import dedent from 'dedent'; -import type { SavedObjectsImportError } from 'src/core/server'; +import type { SavedObjectsImportFailure } from 'src/core/server'; import type { FtrProviderContext } from '../../ftr_provider_context'; const createConflictError = ( - object: Omit -): SavedObjectsImportError => ({ + object: Omit +): SavedObjectsImportFailure => ({ ...object, title: object.meta.title, error: { type: 'conflict' }, diff --git a/x-pack/plugins/spaces/server/lib/copy_to_spaces/copy_to_spaces.test.ts b/x-pack/plugins/spaces/server/lib/copy_to_spaces/copy_to_spaces.test.ts index 945a2bdbf6daf0..db731713811b42 100644 --- a/x-pack/plugins/spaces/server/lib/copy_to_spaces/copy_to_spaces.test.ts +++ b/x-pack/plugins/spaces/server/lib/copy_to_spaces/copy_to_spaces.test.ts @@ -7,42 +7,26 @@ import { Readable } from 'stream'; import { SavedObjectsImportResponse, SavedObjectsImportOptions, - SavedObjectsExportOptions, SavedObjectsImportSuccess, + SavedObjectsExportByObjectOptions, } from 'src/core/server'; import { coreMock, httpServerMock, savedObjectsTypeRegistryMock, savedObjectsClientMock, + savedObjectsServiceMock, } from 'src/core/server/mocks'; import { copySavedObjectsToSpacesFactory } from './copy_to_spaces'; -// Mock out circular dependency -jest.mock('../../../../../../src/core/server/saved_objects/es_query', () => {}); - -jest.mock('../../../../../../src/core/server', () => { - return { - ...(jest.requireActual('../../../../../../src/core/server') as Record), - exportSavedObjectsToStream: jest.fn(), - importSavedObjectsFromStream: jest.fn(), - }; -}); -import { - exportSavedObjectsToStream, - importSavedObjectsFromStream, -} from '../../../../../../src/core/server'; - interface SetupOpts { objects: Array<{ type: string; id: string; attributes: Record }>; - exportSavedObjectsToStreamImpl?: (opts: SavedObjectsExportOptions) => Promise; + exportByObjectsImpl?: (opts: SavedObjectsExportByObjectOptions) => Promise; importSavedObjectsFromStreamImpl?: ( opts: SavedObjectsImportOptions ) => Promise; } -const EXPORT_LIMIT = 1000; - const expectStreamToContainObjects = async ( stream: Readable, expectedObjects: SetupOpts['objects'] @@ -73,9 +57,13 @@ describe('copySavedObjectsToSpaces', () => { const coreStart = coreMock.createStart(); const savedObjectsClient = savedObjectsClientMock.create(); + const savedObjectsExporter = savedObjectsServiceMock.createExporter(); + const savedObjectsImporter = savedObjectsServiceMock.createImporter(); const typeRegistry = savedObjectsTypeRegistryMock.create(); coreStart.savedObjects.getScopedClient.mockReturnValue(savedObjectsClient); coreStart.savedObjects.getTypeRegistry.mockReturnValue(typeRegistry); + coreStart.savedObjects.createExporter.mockReturnValue(savedObjectsExporter); + coreStart.savedObjects.createImporter.mockReturnValue(savedObjectsImporter); typeRegistry.getImportableAndExportableTypes.mockReturnValue([ // don't need to include all types, just need a positive case (agnostic) and a negative case (non-agnostic) @@ -98,62 +86,54 @@ describe('copySavedObjectsToSpaces', () => { .some((t) => t.name === type && t.namespaceType === 'agnostic') ); - (exportSavedObjectsToStream as jest.Mock).mockImplementation( - async (opts: SavedObjectsExportOptions) => { - return ( - setupOpts.exportSavedObjectsToStreamImpl?.(opts) ?? - new Readable({ - objectMode: true, - read() { - setupOpts.objects.forEach((o) => this.push(o)); - - this.push(null); - }, - }) - ); - } - ); - - (importSavedObjectsFromStream as jest.Mock).mockImplementation( - async (opts: SavedObjectsImportOptions) => { - const defaultImpl = async () => { - // namespace-agnostic types should be filtered out before import - const filteredObjects = setupOpts.objects.filter(({ type }) => type !== 'globaltype'); - await expectStreamToContainObjects(opts.readStream, filteredObjects); - const response: SavedObjectsImportResponse = { - success: true, - successCount: filteredObjects.length, - successResults: [ - ('Some success(es) occurred!' as unknown) as SavedObjectsImportSuccess, - ], - }; + savedObjectsExporter.exportByObjects.mockImplementation(async (opts) => { + return ( + setupOpts.exportByObjectsImpl?.(opts) ?? + new Readable({ + objectMode: true, + read() { + setupOpts.objects.forEach((o) => this.push(o)); + + this.push(null); + }, + }) + ); + }); - return Promise.resolve(response); + savedObjectsImporter.import.mockImplementation(async (opts) => { + const defaultImpl = async () => { + // namespace-agnostic types should be filtered out before import + const filteredObjects = setupOpts.objects.filter(({ type }) => type !== 'globaltype'); + await expectStreamToContainObjects(opts.readStream, filteredObjects); + const response: SavedObjectsImportResponse = { + success: true, + successCount: filteredObjects.length, + successResults: [('Some success(es) occurred!' as unknown) as SavedObjectsImportSuccess], }; - return setupOpts.importSavedObjectsFromStreamImpl?.(opts) ?? defaultImpl(); - } - ); + return Promise.resolve(response); + }; + + return setupOpts.importSavedObjectsFromStreamImpl?.(opts) ?? defaultImpl(); + }); return { savedObjects: coreStart.savedObjects, savedObjectsClient, + savedObjectsExporter, + savedObjectsImporter, typeRegistry, }; }; it('uses the Saved Objects Service to perform an export followed by a series of imports', async () => { - const { savedObjects, savedObjectsClient, typeRegistry } = setup({ + const { savedObjects, savedObjectsExporter, savedObjectsImporter } = setup({ objects: mockExportResults, }); const request = httpServerMock.createKibanaRequest(); - const copySavedObjectsToSpaces = copySavedObjectsToSpacesFactory( - savedObjects, - () => EXPORT_LIMIT, - request - ); + const copySavedObjectsToSpaces = copySavedObjectsToSpacesFactory(savedObjects, request); const namespace = 'sourceSpace'; const objects = [{ type: 'dashboard', id: 'my-dashboard' }]; @@ -185,28 +165,23 @@ describe('copySavedObjectsToSpaces', () => { } `); - expect(exportSavedObjectsToStream).toHaveBeenCalledWith({ + expect(savedObjectsExporter.exportByObjects).toHaveBeenCalledWith({ excludeExportDetails: true, - exportSizeLimit: EXPORT_LIMIT, includeReferencesDeep: true, namespace, objects, - savedObjectsClient, }); const importOptions = { createNewCopies: false, - objectLimit: EXPORT_LIMIT, overwrite: true, readStream: expect.any(Readable), - savedObjectsClient, - typeRegistry, }; - expect(importSavedObjectsFromStream).toHaveBeenNthCalledWith(1, { + expect(savedObjectsImporter.import).toHaveBeenNthCalledWith(1, { ...importOptions, namespace: 'destination1', }); - expect(importSavedObjectsFromStream).toHaveBeenNthCalledWith(2, { + expect(savedObjectsImporter.import).toHaveBeenNthCalledWith(2, { ...importOptions, namespace: 'destination2', }); @@ -232,11 +207,7 @@ describe('copySavedObjectsToSpaces', () => { const request = httpServerMock.createKibanaRequest(); - const copySavedObjectsToSpaces = copySavedObjectsToSpacesFactory( - savedObjects, - () => EXPORT_LIMIT, - request - ); + const copySavedObjectsToSpaces = copySavedObjectsToSpacesFactory(savedObjects, request); const result = await copySavedObjectsToSpaces( 'sourceSpace', @@ -281,7 +252,7 @@ describe('copySavedObjectsToSpaces', () => { it(`handles stream read errors`, async () => { const { savedObjects } = setup({ objects: mockExportResults, - exportSavedObjectsToStreamImpl: (_opts) => { + exportByObjectsImpl: (_opts) => { return Promise.resolve( new Readable({ objectMode: true, @@ -295,11 +266,7 @@ describe('copySavedObjectsToSpaces', () => { const request = httpServerMock.createKibanaRequest(); - const copySavedObjectsToSpaces = copySavedObjectsToSpacesFactory( - savedObjects, - () => EXPORT_LIMIT, - request - ); + const copySavedObjectsToSpaces = copySavedObjectsToSpacesFactory(savedObjects, request); await expect( copySavedObjectsToSpaces( diff --git a/x-pack/plugins/spaces/server/lib/copy_to_spaces/copy_to_spaces.ts b/x-pack/plugins/spaces/server/lib/copy_to_spaces/copy_to_spaces.ts index 5575052d7bbb80..852f680b0245ab 100644 --- a/x-pack/plugins/spaces/server/lib/copy_to_spaces/copy_to_spaces.ts +++ b/x-pack/plugins/spaces/server/lib/copy_to_spaces/copy_to_spaces.ts @@ -6,10 +6,6 @@ import { SavedObject, KibanaRequest, CoreStart } from 'src/core/server'; import { Readable } from 'stream'; -import { - exportSavedObjectsToStream, - importSavedObjectsFromStream, -} from '../../../../../../src/core/server'; import { spaceIdToNamespace } from '../utils/namespace'; import { CopyOptions, CopyResponse } from './types'; import { createReadableStreamFromArray } from './lib/readable_stream_from_array'; @@ -20,24 +16,23 @@ import { getIneligibleTypes } from './lib/get_ineligible_types'; export function copySavedObjectsToSpacesFactory( savedObjects: CoreStart['savedObjects'], - getImportExportObjectLimit: () => number, request: KibanaRequest ) { - const { getTypeRegistry, getScopedClient } = savedObjects; + const { getTypeRegistry, getScopedClient, createExporter, createImporter } = savedObjects; const savedObjectsClient = getScopedClient(request, COPY_TO_SPACES_SAVED_OBJECTS_CLIENT_OPTS); + const savedObjectsExporter = createExporter(savedObjectsClient); + const savedObjectsImporter = createImporter(savedObjectsClient); const exportRequestedObjects = async ( sourceSpaceId: string, options: Pick ) => { - const objectStream = await exportSavedObjectsToStream({ + const objectStream = await savedObjectsExporter.exportByObjects({ namespace: spaceIdToNamespace(sourceSpaceId), includeReferencesDeep: options.includeReferences, excludeExportDetails: true, objects: options.objects, - savedObjectsClient, - exportSizeLimit: getImportExportObjectLimit(), }); return readStreamToCompletion(objectStream); @@ -49,12 +44,9 @@ export function copySavedObjectsToSpacesFactory( options: CopyOptions ) => { try { - const importResponse = await importSavedObjectsFromStream({ + const importResponse = await savedObjectsImporter.import({ namespace: spaceIdToNamespace(spaceId), - objectLimit: getImportExportObjectLimit(), overwrite: options.overwrite, - savedObjectsClient, - typeRegistry: getTypeRegistry(), readStream: objectsStream, createNewCopies: options.createNewCopies, }); diff --git a/x-pack/plugins/spaces/server/lib/copy_to_spaces/lib/create_empty_failure_response.ts b/x-pack/plugins/spaces/server/lib/copy_to_spaces/lib/create_empty_failure_response.ts index 3980eef7caac20..b391b4c321d8c5 100644 --- a/x-pack/plugins/spaces/server/lib/copy_to_spaces/lib/create_empty_failure_response.ts +++ b/x-pack/plugins/spaces/server/lib/copy_to_spaces/lib/create_empty_failure_response.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import Boom, { Payload } from '@hapi/boom'; import { SavedObjectsImportError } from 'src/core/server'; @@ -13,7 +14,6 @@ export const createEmptyFailureResponse = (errors?: Array {}); - -jest.mock('../../../../../../src/core/server', () => { - return { - ...(jest.requireActual('../../../../../../src/core/server') as Record), - exportSavedObjectsToStream: jest.fn(), - resolveSavedObjectsImportErrors: jest.fn(), - }; -}); -import { - exportSavedObjectsToStream, - resolveSavedObjectsImportErrors, -} from '../../../../../../src/core/server'; - interface SetupOpts { objects: Array<{ type: string; id: string; attributes: Record }>; - exportSavedObjectsToStreamImpl?: (opts: SavedObjectsExportOptions) => Promise; + exportByObjectsImpl?: (opts: SavedObjectsExportByObjectOptions) => Promise; resolveSavedObjectsImportErrorsImpl?: ( opts: SavedObjectsResolveImportErrorsOptions ) => Promise; } -const EXPORT_LIMIT = 1000; - const expectStreamToContainObjects = async ( stream: Readable, expectedObjects: SetupOpts['objects'] @@ -73,8 +57,12 @@ describe('resolveCopySavedObjectsToSpacesConflicts', () => { const savedObjectsClient = savedObjectsClientMock.create(); const typeRegistry = savedObjectsTypeRegistryMock.create(); + const savedObjectsExporter = savedObjectsServiceMock.createExporter(); + const savedObjectsImporter = savedObjectsServiceMock.createImporter(); coreStart.savedObjects.getScopedClient.mockReturnValue(savedObjectsClient); coreStart.savedObjects.getTypeRegistry.mockReturnValue(typeRegistry); + coreStart.savedObjects.createExporter.mockReturnValue(savedObjectsExporter); + coreStart.savedObjects.createImporter.mockReturnValue(savedObjectsImporter); typeRegistry.getImportableAndExportableTypes.mockReturnValue([ // don't need to include all types, just need a positive case (agnostic) and a negative case (non-agnostic) @@ -97,53 +85,49 @@ describe('resolveCopySavedObjectsToSpacesConflicts', () => { .some((t) => t.name === type && t.namespaceType === 'agnostic') ); - (exportSavedObjectsToStream as jest.Mock).mockImplementation( - async (opts: SavedObjectsExportOptions) => { - return ( - setupOpts.exportSavedObjectsToStreamImpl?.(opts) ?? - new Readable({ - objectMode: true, - read() { - setupOpts.objects.forEach((o) => this.push(o)); - - this.push(null); - }, - }) - ); - } - ); - - (resolveSavedObjectsImportErrors as jest.Mock).mockImplementation( - async (opts: SavedObjectsResolveImportErrorsOptions) => { - const defaultImpl = async () => { - // namespace-agnostic types should be filtered out before import - const filteredObjects = setupOpts.objects.filter(({ type }) => type !== 'globaltype'); - await expectStreamToContainObjects(opts.readStream, filteredObjects); + savedObjectsExporter.exportByObjects.mockImplementation(async (opts) => { + return ( + setupOpts.exportByObjectsImpl?.(opts) ?? + new Readable({ + objectMode: true, + read() { + setupOpts.objects.forEach((o) => this.push(o)); + + this.push(null); + }, + }) + ); + }); - const response: SavedObjectsImportResponse = { - success: true, - successCount: filteredObjects.length, - successResults: [ - ('Some success(es) occurred!' as unknown) as SavedObjectsImportSuccess, - ], - }; + savedObjectsImporter.resolveImportErrors.mockImplementation(async (opts) => { + const defaultImpl = async () => { + // namespace-agnostic types should be filtered out before import + const filteredObjects = setupOpts.objects.filter(({ type }) => type !== 'globaltype'); + await expectStreamToContainObjects(opts.readStream, filteredObjects); - return response; + const response: SavedObjectsImportResponse = { + success: true, + successCount: filteredObjects.length, + successResults: [('Some success(es) occurred!' as unknown) as SavedObjectsImportSuccess], }; - return setupOpts.resolveSavedObjectsImportErrorsImpl?.(opts) ?? defaultImpl(); - } - ); + return response; + }; + + return setupOpts.resolveSavedObjectsImportErrorsImpl?.(opts) ?? defaultImpl(); + }); return { savedObjects: coreStart.savedObjects, savedObjectsClient, + savedObjectsExporter, + savedObjectsImporter, typeRegistry, }; }; it('uses the Saved Objects Service to perform an export followed by a series of conflict resolution calls', async () => { - const { savedObjects, savedObjectsClient, typeRegistry } = setup({ + const { savedObjects, savedObjectsExporter, savedObjectsImporter } = setup({ objects: mockExportResults, }); @@ -151,7 +135,6 @@ describe('resolveCopySavedObjectsToSpacesConflicts', () => { const resolveCopySavedObjectsToSpacesConflicts = resolveCopySavedObjectsToSpacesConflictsFactory( savedObjects, - () => EXPORT_LIMIT, request ); @@ -189,28 +172,23 @@ describe('resolveCopySavedObjectsToSpacesConflicts', () => { } `); - expect(exportSavedObjectsToStream).toHaveBeenCalledWith({ + expect(savedObjectsExporter.exportByObjects).toHaveBeenCalledWith({ excludeExportDetails: true, - exportSizeLimit: EXPORT_LIMIT, includeReferencesDeep: true, namespace, objects, - savedObjectsClient, }); const importOptions = { createNewCopies: false, - objectLimit: EXPORT_LIMIT, readStream: expect.any(Readable), - savedObjectsClient, - typeRegistry, }; - expect(resolveSavedObjectsImportErrors).toHaveBeenNthCalledWith(1, { + expect(savedObjectsImporter.resolveImportErrors).toHaveBeenNthCalledWith(1, { ...importOptions, namespace: 'destination1', retries: [{ ...retries.destination1[0], replaceReferences: [] }], }); - expect(resolveSavedObjectsImportErrors).toHaveBeenNthCalledWith(2, { + expect(savedObjectsImporter.resolveImportErrors).toHaveBeenNthCalledWith(2, { ...importOptions, namespace: 'destination2', retries: [{ ...retries.destination2[0], replaceReferences: [] }], @@ -239,7 +217,6 @@ describe('resolveCopySavedObjectsToSpacesConflicts', () => { const resolveCopySavedObjectsToSpacesConflicts = resolveCopySavedObjectsToSpacesConflictsFactory( savedObjects, - () => EXPORT_LIMIT, request ); @@ -288,7 +265,7 @@ describe('resolveCopySavedObjectsToSpacesConflicts', () => { it(`handles stream read errors`, async () => { const { savedObjects } = setup({ objects: [], - exportSavedObjectsToStreamImpl: (opts) => { + exportByObjectsImpl: (opts) => { return Promise.resolve( new Readable({ objectMode: true, @@ -304,7 +281,6 @@ describe('resolveCopySavedObjectsToSpacesConflicts', () => { const resolveCopySavedObjectsToSpacesConflicts = resolveCopySavedObjectsToSpacesConflictsFactory( savedObjects, - () => EXPORT_LIMIT, request ); diff --git a/x-pack/plugins/spaces/server/lib/copy_to_spaces/resolve_copy_conflicts.ts b/x-pack/plugins/spaces/server/lib/copy_to_spaces/resolve_copy_conflicts.ts index d433712bb9412f..2a671b1423e8c0 100644 --- a/x-pack/plugins/spaces/server/lib/copy_to_spaces/resolve_copy_conflicts.ts +++ b/x-pack/plugins/spaces/server/lib/copy_to_spaces/resolve_copy_conflicts.ts @@ -6,10 +6,6 @@ import { Readable } from 'stream'; import { SavedObject, CoreStart, KibanaRequest, SavedObjectsImportRetry } from 'src/core/server'; -import { - exportSavedObjectsToStream, - resolveSavedObjectsImportErrors, -} from '../../../../../../src/core/server'; import { spaceIdToNamespace } from '../utils/namespace'; import { CopyOptions, ResolveConflictsOptions, CopyResponse } from './types'; import { createEmptyFailureResponse } from './lib/create_empty_failure_response'; @@ -20,24 +16,23 @@ import { getIneligibleTypes } from './lib/get_ineligible_types'; export function resolveCopySavedObjectsToSpacesConflictsFactory( savedObjects: CoreStart['savedObjects'], - getImportExportObjectLimit: () => number, request: KibanaRequest ) { - const { getTypeRegistry, getScopedClient } = savedObjects; + const { getTypeRegistry, getScopedClient, createExporter, createImporter } = savedObjects; const savedObjectsClient = getScopedClient(request, COPY_TO_SPACES_SAVED_OBJECTS_CLIENT_OPTS); + const savedObjectsExporter = createExporter(savedObjectsClient); + const savedObjectsImporter = createImporter(savedObjectsClient); const exportRequestedObjects = async ( sourceSpaceId: string, options: Pick ) => { - const objectStream = await exportSavedObjectsToStream({ + const objectStream = await savedObjectsExporter.exportByObjects({ namespace: spaceIdToNamespace(sourceSpaceId), includeReferencesDeep: options.includeReferences, excludeExportDetails: true, objects: options.objects, - savedObjectsClient, - exportSizeLimit: getImportExportObjectLimit(), }); return readStreamToCompletion(objectStream); }; @@ -49,11 +44,8 @@ export function resolveCopySavedObjectsToSpacesConflictsFactory( createNewCopies: boolean ) => { try { - const importResponse = await resolveSavedObjectsImportErrors({ + const importResponse = await savedObjectsImporter.resolveImportErrors({ namespace: spaceIdToNamespace(spaceId), - objectLimit: getImportExportObjectLimit(), - savedObjectsClient, - typeRegistry: getTypeRegistry(), readStream: objectsStream, retries, createNewCopies, diff --git a/x-pack/plugins/spaces/server/lib/copy_to_spaces/types.ts b/x-pack/plugins/spaces/server/lib/copy_to_spaces/types.ts index d774231d3eb48c..8d7aa7da9d60de 100644 --- a/x-pack/plugins/spaces/server/lib/copy_to_spaces/types.ts +++ b/x-pack/plugins/spaces/server/lib/copy_to_spaces/types.ts @@ -7,8 +7,9 @@ import { Payload } from '@hapi/boom'; import { SavedObjectsImportSuccess, - SavedObjectsImportError, + SavedObjectsImportFailure, SavedObjectsImportRetry, + SavedObjectsImportError, } from 'src/core/server'; export interface CopyOptions { @@ -32,6 +33,6 @@ export interface CopyResponse { success: boolean; successCount: number; successResults?: SavedObjectsImportSuccess[]; - errors?: Array; + errors?: Array; }; } diff --git a/x-pack/plugins/spaces/server/plugin.ts b/x-pack/plugins/spaces/server/plugin.ts index cd36ca3c7a6ec0..e50ab60a277387 100644 --- a/x-pack/plugins/spaces/server/plugin.ts +++ b/x-pack/plugins/spaces/server/plugin.ts @@ -128,7 +128,6 @@ export class Plugin { externalRouter, log: this.log, getStartServices: core.getStartServices, - getImportExportObjectLimit: core.savedObjects.getImportExportObjectLimit, getSpacesService, usageStatsServicePromise, }); diff --git a/x-pack/plugins/spaces/server/routes/api/__fixtures__/create_mock_so_service.ts b/x-pack/plugins/spaces/server/routes/api/__fixtures__/create_mock_so_service.ts index fa8ef1882099cf..59fb5a59e3e0f2 100644 --- a/x-pack/plugins/spaces/server/routes/api/__fixtures__/create_mock_so_service.ts +++ b/x-pack/plugins/spaces/server/routes/api/__fixtures__/create_mock_so_service.ts @@ -9,11 +9,15 @@ import { coreMock, savedObjectsClientMock, savedObjectsTypeRegistryMock, + savedObjectsServiceMock, } from '../../../../../../../src/core/server/mocks'; export const createMockSavedObjectsService = (spaces: any[] = []) => { const typeRegistry = savedObjectsTypeRegistryMock.create(); const savedObjectsClient = savedObjectsClientMock.create(); + const savedObjectsExporter = savedObjectsServiceMock.createExporter(); + const savedObjectsImporter = savedObjectsServiceMock.createImporter(); + savedObjectsClient.get.mockImplementation((type, id) => { const result = spaces.filter((s) => s.id === id); if (!result.length) { @@ -43,6 +47,14 @@ export const createMockSavedObjectsService = (spaces: any[] = []) => { const { savedObjects } = coreMock.createStart(); savedObjects.getTypeRegistry.mockReturnValue(typeRegistry); savedObjects.getScopedClient.mockReturnValue(savedObjectsClient); + savedObjects.createExporter.mockReturnValue(savedObjectsExporter); + savedObjects.createImporter.mockReturnValue(savedObjectsImporter); - return { savedObjects, typeRegistry, savedObjectsClient }; + return { + savedObjects, + typeRegistry, + savedObjectsClient, + savedObjectsExporter, + savedObjectsImporter, + }; }; diff --git a/x-pack/plugins/spaces/server/routes/api/external/copy_to_space.test.ts b/x-pack/plugins/spaces/server/routes/api/external/copy_to_space.test.ts index c8b25bf3cf7fad..6b586355a2a223 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/copy_to_space.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/copy_to_space.test.ts @@ -28,55 +28,32 @@ import { initCopyToSpacesApi } from './copy_to_space'; import { spacesConfig } from '../../../lib/__fixtures__'; import { ObjectType } from '@kbn/config-schema'; -// Mock out circular dependency -jest.mock('../../../../../../../src/core/server/saved_objects/es_query', () => {}); - -jest.mock('../../../../../../../src/core/server', () => { - return { - ...(jest.requireActual('../../../../../../../src/core/server') as Record), - exportSavedObjectsToStream: jest.fn(), - importSavedObjectsFromStream: jest.fn(), - resolveSavedObjectsImportErrors: jest.fn(), - }; -}); -import { - exportSavedObjectsToStream, - importSavedObjectsFromStream, - resolveSavedObjectsImportErrors, -} from '../../../../../../../src/core/server'; import { SpacesClientService } from '../../../spaces_client'; describe('copy to space', () => { const spacesSavedObjects = createSpaces(); const spaces = spacesSavedObjects.map((s) => ({ id: s.id, ...s.attributes })); - beforeEach(() => { - (exportSavedObjectsToStream as jest.Mock).mockReset(); - (importSavedObjectsFromStream as jest.Mock).mockReset(); - (resolveSavedObjectsImportErrors as jest.Mock).mockReset(); - }); - const setup = async () => { const httpService = httpServiceMock.createSetupContract(); const router = httpService.createRouter(); const savedObjectsRepositoryMock = createMockSavedObjectsRepository(spacesSavedObjects); - (exportSavedObjectsToStream as jest.Mock).mockImplementation( - createExportSavedObjectsToStreamMock() - ); - (importSavedObjectsFromStream as jest.Mock).mockImplementation( - createImportSavedObjectsFromStreamMock() - ); - (resolveSavedObjectsImportErrors as jest.Mock).mockImplementation( - createResolveSavedObjectsImportErrorsMock() - ); - const log = loggingSystemMock.create().get('spaces'); const coreStart = coreMock.createStart(); - const { savedObjects } = createMockSavedObjectsService(spaces); + const { + savedObjects, + savedObjectsExporter, + savedObjectsImporter, + } = createMockSavedObjectsService(spaces); coreStart.savedObjects = savedObjects; + savedObjectsExporter.exportByObjects.mockImplementation(createExportSavedObjectsToStreamMock()); + savedObjectsImporter.import.mockImplementation(createImportSavedObjectsFromStreamMock()); + savedObjectsImporter.resolveImportErrors.mockImplementation( + createResolveSavedObjectsImportErrorsMock() + ); const clientService = new SpacesClientService(jest.fn()); clientService @@ -103,7 +80,6 @@ describe('copy to space', () => { initCopyToSpacesApi({ externalRouter: router, getStartServices: async () => [coreStart, {}, {}], - getImportExportObjectLimit: () => 1000, log, getSpacesService: () => spacesServiceStart, usageStatsServicePromise, @@ -125,6 +101,8 @@ describe('copy to space', () => { routeHandler: resolveRouteHandler, }, savedObjectsRepositoryMock, + savedObjectsExporter, + savedObjectsImporter, usageStatsClient, }; }; @@ -255,7 +233,7 @@ describe('copy to space', () => { objects: [{ type: 'visualization', id: 'bar' }], }; - const { copyToSpace } = await setup(); + const { copyToSpace, savedObjectsImporter } = await setup(); const request = httpServerMock.createKibanaRequest({ body: payload, @@ -271,14 +249,14 @@ describe('copy to space', () => { const { status } = response; expect(status).toEqual(200); - expect(importSavedObjectsFromStream).toHaveBeenCalledTimes(2); - const [firstImportCallOptions] = (importSavedObjectsFromStream as jest.Mock).mock.calls[0]; + expect(savedObjectsImporter.import).toHaveBeenCalledTimes(2); + const [firstImportCallOptions] = savedObjectsImporter.import.mock.calls[0]; expect(firstImportCallOptions).toMatchObject({ namespace: 'a-space', }); - const [secondImportCallOptions] = (importSavedObjectsFromStream as jest.Mock).mock.calls[1]; + const [secondImportCallOptions] = savedObjectsImporter.import.mock.calls[1]; expect(secondImportCallOptions).toMatchObject({ namespace: 'b-space', @@ -413,7 +391,7 @@ describe('copy to space', () => { }, }; - const { resolveConflicts } = await setup(); + const { resolveConflicts, savedObjectsImporter } = await setup(); const request = httpServerMock.createKibanaRequest({ body: payload, @@ -429,16 +407,16 @@ describe('copy to space', () => { const { status } = response; expect(status).toEqual(200); - expect(resolveSavedObjectsImportErrors).toHaveBeenCalledTimes(2); + expect(savedObjectsImporter.resolveImportErrors).toHaveBeenCalledTimes(2); const [ resolveImportErrorsFirstCallOptions, - ] = (resolveSavedObjectsImportErrors as jest.Mock).mock.calls[0]; + ] = savedObjectsImporter.resolveImportErrors.mock.calls[0]; expect(resolveImportErrorsFirstCallOptions).toMatchObject({ namespace: 'a-space' }); const [ resolveImportErrorsSecondCallOptions, - ] = (resolveSavedObjectsImportErrors as jest.Mock).mock.calls[1]; + ] = savedObjectsImporter.resolveImportErrors.mock.calls[1]; expect(resolveImportErrorsSecondCallOptions).toMatchObject({ namespace: 'b-space' }); }); diff --git a/x-pack/plugins/spaces/server/routes/api/external/copy_to_space.ts b/x-pack/plugins/spaces/server/routes/api/external/copy_to_space.ts index 2b1be42f9cbb00..d6adc68da31237 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/copy_to_space.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/copy_to_space.ts @@ -21,13 +21,7 @@ const areObjectsUnique = (objects: SavedObjectIdentifier[]) => _.uniqBy(objects, (o: SavedObjectIdentifier) => `${o.type}:${o.id}`).length === objects.length; export function initCopyToSpacesApi(deps: ExternalRouteDeps) { - const { - externalRouter, - getSpacesService, - usageStatsServicePromise, - getImportExportObjectLimit, - getStartServices, - } = deps; + const { externalRouter, getSpacesService, usageStatsServicePromise, getStartServices } = deps; const usageStatsClientPromise = usageStatsServicePromise.then(({ getClient }) => getClient()); externalRouter.post( @@ -99,7 +93,6 @@ export function initCopyToSpacesApi(deps: ExternalRouteDeps) { const copySavedObjectsToSpaces = copySavedObjectsToSpacesFactory( startServices.savedObjects, - getImportExportObjectLimit, request ); const sourceSpaceId = getSpacesService().getSpaceId(request); @@ -169,7 +162,6 @@ export function initCopyToSpacesApi(deps: ExternalRouteDeps) { const resolveCopySavedObjectsToSpacesConflicts = resolveCopySavedObjectsToSpacesConflictsFactory( startServices.savedObjects, - getImportExportObjectLimit, request ); const sourceSpaceId = getSpacesService().getSpaceId(request); diff --git a/x-pack/plugins/spaces/server/routes/api/external/delete.test.ts b/x-pack/plugins/spaces/server/routes/api/external/delete.test.ts index 0dc6f67cc278f2..b182ed13943e54 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/delete.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/delete.test.ts @@ -64,7 +64,6 @@ describe('Spaces Public API', () => { initDeleteSpacesApi({ externalRouter: router, getStartServices: async () => [coreStart, {}, {}], - getImportExportObjectLimit: () => 1000, log, getSpacesService: () => spacesServiceStart, usageStatsServicePromise, diff --git a/x-pack/plugins/spaces/server/routes/api/external/get.test.ts b/x-pack/plugins/spaces/server/routes/api/external/get.test.ts index 9944655f73b759..d12c15ea38a9cb 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/get.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/get.test.ts @@ -59,7 +59,6 @@ describe('GET space', () => { initGetSpaceApi({ externalRouter: router, getStartServices: async () => [coreStart, {}, {}], - getImportExportObjectLimit: () => 1000, log, getSpacesService: () => spacesServiceStart, usageStatsServicePromise, diff --git a/x-pack/plugins/spaces/server/routes/api/external/get_all.test.ts b/x-pack/plugins/spaces/server/routes/api/external/get_all.test.ts index d79596b754fc9c..c41f8e3aa894eb 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/get_all.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/get_all.test.ts @@ -60,7 +60,6 @@ describe('GET /spaces/space', () => { initGetAllSpacesApi({ externalRouter: router, getStartServices: async () => [coreStart, {}, {}], - getImportExportObjectLimit: () => 1000, log, getSpacesService: () => spacesServiceStart, usageStatsServicePromise, diff --git a/x-pack/plugins/spaces/server/routes/api/external/index.ts b/x-pack/plugins/spaces/server/routes/api/external/index.ts index b828bb457aba5e..d481c2e0675fa8 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/index.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/index.ts @@ -18,7 +18,6 @@ import { initShareToSpacesApi } from './share_to_space'; export interface ExternalRouteDeps { externalRouter: IRouter; getStartServices: CoreSetup['getStartServices']; - getImportExportObjectLimit: () => number; getSpacesService: () => SpacesServiceStart; usageStatsServicePromise: Promise; log: Logger; diff --git a/x-pack/plugins/spaces/server/routes/api/external/post.test.ts b/x-pack/plugins/spaces/server/routes/api/external/post.test.ts index 30429bb2866ef9..930760c2726922 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/post.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/post.test.ts @@ -59,7 +59,6 @@ describe('Spaces Public API', () => { initPostSpacesApi({ externalRouter: router, getStartServices: async () => [coreStart, {}, {}], - getImportExportObjectLimit: () => 1000, log, getSpacesService: () => spacesServiceStart, usageStatsServicePromise, diff --git a/x-pack/plugins/spaces/server/routes/api/external/put.test.ts b/x-pack/plugins/spaces/server/routes/api/external/put.test.ts index f4aed1efbaa5f0..2b0f55fda4a770 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/put.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/put.test.ts @@ -60,7 +60,6 @@ describe('PUT /api/spaces/space', () => { initPutSpacesApi({ externalRouter: router, getStartServices: async () => [coreStart, {}, {}], - getImportExportObjectLimit: () => 1000, log, getSpacesService: () => spacesServiceStart, usageStatsServicePromise, diff --git a/x-pack/plugins/spaces/server/routes/api/external/share_to_space.test.ts b/x-pack/plugins/spaces/server/routes/api/external/share_to_space.test.ts index 9a8a619f661469..525b45d6fb9e98 100644 --- a/x-pack/plugins/spaces/server/routes/api/external/share_to_space.test.ts +++ b/x-pack/plugins/spaces/server/routes/api/external/share_to_space.test.ts @@ -59,7 +59,6 @@ describe('share to space', () => { initShareToSpacesApi({ externalRouter: router, getStartServices: async () => [coreStart, {}, {}], - getImportExportObjectLimit: () => 1000, log, getSpacesService: () => spacesServiceStart, usageStatsServicePromise, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.tsx index 0f3e7bb0e94d6c..cada7958f8d7cd 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.tsx @@ -5,6 +5,8 @@ */ import React, { useState } from 'react'; import { EuiCodeEditor, EuiFormRow } from '@elastic/eui'; + +import 'brace/theme/github'; import { XJsonMode } from '@kbn/ace'; import './add_message_variables.scss';