Initial server-side support for sharing saved-objects phase 1.5#66089
Conversation
24b44ed to
4a65de5
Compare
de5a3cb to
44fc7c9
Compare
SavedObject.error type did not specify the error attribute and did not reflect what is actually returned by SavedObjectsRepository. Updated this for consistency, and updated relevant saved object unit tests to utilize the SavedObjectsErrorHelper functions instead of manually mocking error objects.
`importSavedObjectsFromStream` and `resolveSavedObjectImportErrors` previously expected an array of supported saved object types. Updated these functions to use the SavedObjectTypeRegistry directly to obtain the list of importable/exportable types. This simplifies logic for other consumers (e.g., Spaces), and it lays the groundwork for regenerating IDs of multi-namespace saved objects upon import.
This is only intended to be set during migration or create operations. It is in place to support future changes for migrating and importing multi-namespace saved objects, so IDs can be regenerated deterministically. This will allow saved objects to be overwritten consistently if they are imported multiple times into a given space.
Single-namespace saved objects do not include the `namespace` field after deserialization, hence it was never exported. Multi-namespace saved objects do include the `namespaces` field, but this should be omitted when the object is exported from Kibana.
bulkCreate now attaches error metadata to indicate when an unresolvable conflict occurred.
When attempting to search with a simple_query_string term, the `searchFields` option only allows for selecting type-specific attributes (e.g., the fields in the `attributes` object). Every element in `searchFields` is prefixed by the object type before being added to the simple_query_string term. This commit adds a `rawSearchFields` option which is not prefixed by the object type -- this way, searches can use fields that are not specific to the object type (such as `_id` or `originId`).
Kibana does not officially support importing multiple objects with the same type/ID simultaneously. While this will not fail, it will result in a confusing outcome, because these objects would conflict with each other (and overwrite each other if that flag is used). This commit simply adds validation to throw a descriptive error if this situation is encountered. It should never happen in normal usage of Kibana, only if someone is tampering with an exported NDJSON file or otherwise misusing the API.
Imports for single-namespace saved objects ensured that, at most, one "copy" of an object was made in any given space. Re-importing an object into a space would result in a conflict that could be overwritten. This commit ensures that multi-namespace saved objects can be imported, and that they behave in the same way. Primary changes: 1. Pre-flight searches to ensure that conflicts are made with the correct ID, and that ambiguous conflicts are detected. 2. Abstract out behavior of bulkCreate to handle the case of unresolvable conflicts, which shouldn't be exposed to consumers. 3. Support resolving ambiguous_conflict import errors by allowing consumers to select which conflicting object should be overwritten.
Saved object import that resulted in a Conflict error previously had one resolution, which is "overwrite". This commit adds another resolution, "duplicate", which will create a new object with a different ID instead.
These test suites do not currently include test cases for multi- namespace saved object types. However, the test suites broke due to the changes to the import APIs. I fixed the few problems that were present, and took this opportunity to refactor some of the test suites to make them more readable and maintainable.
Also fixed existing Jest integration tests, but did not add new test cases for those since they are currently disabled in CI.
The implementation already included this field in some cases when using this as a return type, for some reason the type checker did not prohibit that though.
dfa3b77 to
7954483
Compare
|
Pinging @elastic/ingest-management (Team:Ingest Management) |
jportner
left a comment
There was a problem hiding this comment.
Notes for reviewers.
| type SavedObjectsFindOptions = Omit<SavedObjectFindOptionsServer, 'namespace' | 'sortOrder'>; | ||
| type SavedObjectsFindOptions = Omit< | ||
| SavedObjectFindOptionsServer, | ||
| 'namespace' | 'sortOrder' | 'rawSearchFields' |
There was a problem hiding this comment.
I omitted rawSearchFields here because we only need to be able to use it on the server side.
Despite this, it's still showing up in the public API docs, I suspect due to some quirk of the docs generation process.
pgayvallet
left a comment
There was a problem hiding this comment.
I think this one was even bigger than the phase 1 review.
A few nits and comments, but did not found anything major. My biggest concern is that every phase of this SO sharing issue makes the (already way too complex) SO code yet more complex and hard to follow, but I don't really see how that can be avoided to be honest if we do want to implement this thing.
I will let @rudolf have a second opinion, but this looks good to me.
x-pack/plugins/spaces/server/saved_objects/spaces_saved_objects_client.test.ts
Outdated
Show resolved
Hide resolved
Updated docs to reflect latest changes.
Now uses consistent 'params' objects.
rudolf
left a comment
There was a problem hiding this comment.
First-pass, mostly left some documentation nits.
| Indicates a successful call. | ||
|
|
||
| [[saved-objects-api-import-example]] | ||
| ==== Examples |
There was a problem hiding this comment.
Thanks for raising this, I do think this is something we should address at some point. I personally find it very frustrating when documentation examples don't work.
| function getFieldsForTypes( | ||
| types: string[], | ||
| searchFields: string[] = [], | ||
| rootSearchFields: string[] = [] |
There was a problem hiding this comment.
In other places the repository uses a pattern of type.attributes.field vs type.field to distinguish between root fields/type fields. It would be more consistent if we could do it here too (even though it's a breaking change).
This inconsistency wasn't introduced by this PR, but it highlights the current shortcomings. So just leaving this as a note to the Platform team that this is something we should take a look at at some point.
Thanks, I believe I addressed them all in 9d7b755. |
|
@rudolf did you have any other concerns for now? Or would you like to take another pass on the final PR? |
💚 Build SucceededBuild metricsasync chunks size
page load bundle size
Saved Objects .kibana field count
History
To update your PR or re-run it, just comment with: |
pgayvallet
left a comment
There was a problem hiding this comment.
All points from previous reviews have been addressed, did not see anything else in the second pass. Congratulations, you are a real SO ninja now!
LGTM
(Naively) Hope the phase 2 will be smaller though 😅
Server-side component to #58139.
Introduces support for importing, exporting, and copying multi-namespace saved objects on the Kibana server.
Code owners except for
kibana-securityandkibana-platformmay be interested in waiting until a final PR is opened againstmaster.Commit Descriptions
I tried to break this PR down the smallest possible portions with individual commits. Each commit message is quite descriptive. I recommend any reviewers to check this PR commit-by-commit.
Notable Changes
originIdattribute for saved objects, which is used during importidToOverwritedestinationId, which is used to resolve inexact match conflicts and ambiguous conflictsAdded ability to Duplicate the object; this is mutually-exclusive with Overwrite, and instead it will create a new object with a random ID, unsetting anyoriginIdin the processconflict,ambiguous_conflict, andmissing_references. Unresolvable errors areunsupported_typeandunknown; these will not block object creation. E.g., if you import an NDJSON file with 10 objects that results in 1unsupported_typeerror, that object will be skipped but the other 9 will be created.Miscellaneous Notes
The majority of the code changes/additions are in the
src/core/server/saved_objects/importdirectory. Wherever it made sense, I abstracted logic out into separate sub-modules. I also wound up rewriting the unit tests in several files, partly because the existing tests did not separate concerns from sub-modules properly. I used module mocks liberally to reduce the testing concerns of each individual sub-module.Concerning integration tests: the existing X-Pack functional/integration tests largely focused on the combination of Spaces and Security plugins, but basically ignored testing import objects with references. The Core Jest integration tests, however, included a few cases to test different reference scenarios (including missing references and resolution). I followed this pattern, and did not attempt to write any new reference-focused X-Pack integration test cases.