Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate savedObjects routes to core #56734

Merged
merged 41 commits into from
Feb 18, 2020

Conversation

pgayvallet
Copy link
Contributor

@pgayvallet pgayvallet commented Feb 4, 2020

Summary

Fix #50321

Migrate the /api/saved_objects/* routes fromlegacy to core

Checklist

For maintainers

@pgayvallet pgayvallet added v7.7.0 release_note:skip Skip the PR/issue when compiling release notes Feature:New Platform Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc labels Feb 4, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-platform (Team:Platform)

Comment on lines +87 to +89
if ((types?.length ?? 0) > 0 && (objects?.length ?? 0) > 0) {
throw Boom.badRequest(`Can't specify both "types" and "objects" properties when exporting`);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The route validation was using an nand(types, objects). As we don't have the equivalent in config-schema (probably for the best), I moved this check in the actual service method. This probably is it's place anyway.

I also had to fix some calls that were actually sending both (with types being used as they are exclude in the business logic)

Comment on lines -495 to 497
types: ['index-pattern', 'search'],
objects: [
{
type: 'index-pattern',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment on get_sorted_objects_for_export.ts

src/core/server/saved_objects/routes/bulk_create.test.ts Outdated Show resolved Hide resolved
Comment on lines +47 to +50
router.handleLegacyErrors(async (context, req, res) => {
const savedObject = await context.core.savedObjects.client.bulkUpdate(req.body);
return res.ok({ body: savedObject });
})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The savedObject service actually throws boom errors. I had to wrap the handlers using handleLegacyErrors.

Comment on lines +22 to +26
import {
createPromiseFromStreams,
createMapStream,
createConcatStream,
} from '../../../../legacy/utils/streams';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole SO import/export APIs rely on our legacy stream utilities. As we don't want to loose the (not yet used but anyway) http streaming feature for the export and import, I kept using them (changing that would mean some structural changes in the getSortedObjectsForExport method and it's underlying components. This is not the first time we are importing this in core SO code though. We probably will have to move it to core at some point (FTR services also uses them, so this will not be removed when we remove legacy, at least no without rewrite), but the PR is already big, did not want to do it here.

Comment on lines 36 to 42
export const savedObjectsConfig = {
path: 'savedObjects',
schema: schema.object({
maxImportPayloadBytes: schema.number({ defaultValue: 10485760 }),
maxImportExportSize: schema.number({ defaultValue: 10000 }),
}),
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the import/export routes, I now need the 'real' savedObject config. What we called that previously was the config for the migrations config namespace. I created the SavedObjectConfig class to 'merge' them. I kept the migrations properties as an underlying object to avoid breaking every signature in the SO migrator code, and also because I think this isolation makes sense.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a blocker, just curious: Do we want to move migrations --> savedObjects.migration in the future? Will we have migrations fields in v8 with saved objects v2? @rudolf

Comment on lines +20 to +21
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { SavedObjectReference } from '../../../../core/server';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is server code (SO migrations), but outside of the server folder, which explains the disabled rule

Comment on lines 23 to -24
loadTestFile(require.resolve('./csp'));
loadTestFile(require.resolve('./prototype_pollution'));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was using a legacy SO endpoint to test against prototype pollution. We don't have yet that kind of protection in NP. After discussion with @legrego, we agreed to delete the test, and to properly reimplement it when the feature would lands to NP.

Comment on lines 40 to 42
objects: options.objects,
savedObjectsClient,
types: eligibleTypes,
types: options.objects.length > 0 ? undefined : eligibleTypes,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As explained in a previous comment, When sending both objects and types, only objects were used. However the validation to not send both was performed in the route handler. As I moved it to the service, I had to adapt some calls to no longer send both.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@legrego do you happen to recall why we used to always be passing in eligibleTypes here? It looks like this was being ignored... I'm tempted to say we should just always pass in undefined here if that's the case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intent was to prevent namespace agnostic types from being specified, but that's handled on the subsequent call to importSavedObjects, so I agree we should just always pass undefined here, rather than eligibleTypes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, will just remove the types parameter from the call then

Comment on lines -188 to -198
describe('Routes', () => {
it('should create 12 routes', () => {
savedObjectsMixin(mockKbnServer, mockServer);
expect(mockServer.route).toHaveBeenCalledTimes(12);
});
it('should add POST /api/saved_objects/_bulk_create', () => {
savedObjectsMixin(mockKbnServer, mockServer);
expect(mockServer.route).toHaveBeenCalledWith(
expect.objectContaining({ path: '/api/saved_objects/_bulk_create', method: 'POST' })
);
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already covered by the API integration tests, so I did not move these tests to core. Tell me if I should.

@pgayvallet pgayvallet marked this pull request as ready for review February 11, 2020 12:44
@pgayvallet pgayvallet requested review from a team as code owners February 11, 2020 12:44
src/core/server/saved_objects/routes/bulk_create.test.ts Outdated Show resolved Hide resolved

return server;
}
httpSetup.registerRouteHandlerContext(coreId, 'core', async (ctx, req, res) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you already created the mock, we can expose it and document a usage example. can be done in a separate PR ofc

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created #57844

src/core/server/saved_objects/routes/find.ts Show resolved Hide resolved
router.handleLegacyErrors(async (context, req, res) => {
const { overwrite } = req.query;
const file = req.body.file as FileStream;
const fileExtension = extname(file.hapi.filename).toLowerCase();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't checked, but believe we should be able to access filename via Content-Disposition header https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Content-Disposition is not a header in multipart/form-data, it's included in the actual payload. The only way to get the file name is to access the parsed payload, and HAPI do the parsing and exposes the name in this property. We can't do differently without tricky changes.

FYI, an example of such request in a 'json' format is

const request = {
      method: 'POST',
      url: '/api/saved_objects/_import',
      payload: [
        '--EXAMPLE',
        'Content-Disposition: form-data; name="file"; filename="export.ndjson"',
        'Content-Type: application/ndjson',
        '',
        '{"type":"index-pattern","id":"my-pattern","attributes":{"title":"my-pattern-*"}}',
        '--EXAMPLE--',
      ].join('\r\n'),
      headers: {
        'content-Type': 'multipart/form-data; boundary=EXAMPLE',
      },
    };

Copy link
Contributor

@mshustov mshustov Feb 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commented in #56944 let's merge as is

src/core/server/saved_objects/saved_objects_config.ts Outdated Show resolved Hide resolved
Comment on lines 36 to 42
export const savedObjectsConfig = {
path: 'savedObjects',
schema: schema.object({
maxImportPayloadBytes: schema.number({ defaultValue: 10485760 }),
maxImportExportSize: schema.number({ defaultValue: 10000 }),
}),
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a blocker, just curious: Do we want to move migrations --> savedObjects.migration in the future? Will we have migrations fields in v8 with saved objects v2? @rudolf

src/core/server/saved_objects/routes/import.test.ts Outdated Show resolved Hide resolved
@kibanamachine
Copy link
Contributor

💚 Build Succeeded

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@mshustov mshustov merged commit 055c611 into elastic:master Feb 18, 2020
mshustov added a commit to mshustov/kibana that referenced this pull request Feb 18, 2020
* migrate `get` route

* migrate `create` route

* migrate `delete` route

* migrate `find` route

* migrate `update` route

* migrate `bulk_get` route

* migrate `bulk_create` route

* remove route-related mixin tests

* migrate `bulk_update` route

* fix expectTypeRequired assertion

* migrate `log_legacy_imports` route

* migrate `export` route

* fix karma tests

* array is better than object in some situations.

* remove prototype pollution tests

* adapt ftr assertions

* adapt ftr assertions

* adapt yet more ftr assertions

* migrate `import` route

* fix test tests

* fix getSortedObjectsForExport usages

* fix snapshots

* fix so ui exports usages due to merge

* create router with prefix

* creates `savedObjects` namespace config in addition to `migrations`

* migrate `resolve_import_errors` route

* remove old types file

* fix FTR assertion

* remove types parameter from copy_to_space

* move route tests to integration_tests

* use byteSize instead of number

* fix unit tests

* add has_reference query parameter

Co-authored-by: Mikhail Shustov <[email protected]>
mshustov added a commit that referenced this pull request Feb 18, 2020
* migrate `get` route

* migrate `create` route

* migrate `delete` route

* migrate `find` route

* migrate `update` route

* migrate `bulk_get` route

* migrate `bulk_create` route

* remove route-related mixin tests

* migrate `bulk_update` route

* fix expectTypeRequired assertion

* migrate `log_legacy_imports` route

* migrate `export` route

* fix karma tests

* array is better than object in some situations.

* remove prototype pollution tests

* adapt ftr assertions

* adapt ftr assertions

* adapt yet more ftr assertions

* migrate `import` route

* fix test tests

* fix getSortedObjectsForExport usages

* fix snapshots

* fix so ui exports usages due to merge

* create router with prefix

* creates `savedObjects` namespace config in addition to `migrations`

* migrate `resolve_import_errors` route

* remove old types file

* fix FTR assertion

* remove types parameter from copy_to_space

* move route tests to integration_tests

* use byteSize instead of number

* fix unit tests

* add has_reference query parameter

Co-authored-by: Mikhail Shustov <[email protected]>

Co-authored-by: Pierre Gayvallet <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backported Feature:New Platform release_note:skip Skip the PR/issue when compiling release notes Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v7.7.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Platform] Move SavedObject routes to Core
7 participants