Skip to content

Commit

Permalink
migrate savedObjects routes to core (elastic#56734)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
pgayvallet and mshustov committed Feb 18, 2020
1 parent 7efe873 commit ff7cd43
Show file tree
Hide file tree
Showing 74 changed files with 2,091 additions and 2,509 deletions.
11 changes: 6 additions & 5 deletions src/core/server/http/test_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,14 @@ const defaultContext: CoreContext = {
configService,
};

export const createCoreContext = (overrides: Partial<CoreContext> = {}): CoreContext => ({
...defaultContext,
...overrides,
});

/**
* Creates a concrete HttpServer with a mocked context.
*/
export const createHttpServer = (overrides: Partial<CoreContext> = {}): HttpService => {
const context = {
...defaultContext,
...overrides,
};
return new HttpService(context);
return new HttpService(createCoreContext(overrides));
};
1 change: 1 addition & 0 deletions src/core/server/legacy/legacy_service.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const createDiscoverPluginsMock = (): LegacyServiceDiscoverPlugins => ({
savedObjectMappings: [],
savedObjectMigrations: {},
savedObjectValidations: {},
savedObjectsManagement: {},
},
navLinks: [],
pluginExtendedConfig: {
Expand Down
1 change: 1 addition & 0 deletions src/core/server/legacy/plugins/get_nav_links.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const createLegacyExports = ({
savedObjectSchemas: {},
savedObjectMigrations: {},
savedObjectValidations: {},
savedObjectsManagement: {},
});

const createPluginSpecs = (...ids: string[]): LegacyPluginSpec[] =>
Expand Down
23 changes: 22 additions & 1 deletion src/core/server/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { elasticsearchServiceMock } from './elasticsearch/elasticsearch_service.
import { httpServiceMock } from './http/http_service.mock';
import { contextServiceMock } from './context/context_service.mock';
import { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock';
import { savedObjectsClientMock } from './saved_objects/service/saved_objects_client.mock';
import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock';
import { SharedGlobalConfig } from './plugins';
import { InternalCoreSetup, InternalCoreStart } from './internal_types';
Expand All @@ -36,7 +37,6 @@ export { configServiceMock } from './config/config_service.mock';
export { elasticsearchServiceMock } from './elasticsearch/elasticsearch_service.mock';
export { httpServiceMock } from './http/http_service.mock';
export { loggingServiceMock } from './logging/logging_service.mock';
export { savedObjectsClientMock } from './saved_objects/service/saved_objects_client.mock';
export { savedObjectsRepositoryMock } from './saved_objects/service/lib/repository.mock';
export { typeRegistryMock as savedObjectsTypeRegistryMock } from './saved_objects/saved_objects_type_registry.mock';
export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock';
Expand Down Expand Up @@ -168,10 +168,31 @@ function createInternalCoreStartMock() {
return startDeps;
}

function createCoreRequestHandlerContextMock() {
return {
rendering: {
render: jest.fn(),
},
savedObjects: {
client: savedObjectsClientMock.create(),
},
elasticsearch: {
adminClient: elasticsearchServiceMock.createScopedClusterClient(),
dataClient: elasticsearchServiceMock.createScopedClusterClient(),
},
uiSettings: {
client: uiSettingsServiceMock.createClient(),
},
};
}

export const coreMock = {
createSetup: createCoreSetupMock,
createStart: createCoreStartMock,
createInternalSetup: createInternalCoreSetupMock,
createInternalStart: createInternalCoreStartMock,
createPluginInitializerContext: pluginInitializerContextMock,
createRequestHandlerContext: createCoreRequestHandlerContextMock,
};

export { savedObjectsClientMock };
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,6 @@ describe('getSortedObjectsForExport()', () => {
const exportStream = await getSortedObjectsForExport({
exportSizeLimit: 10000,
savedObjectsClient,
types: ['index-pattern', 'search'],
objects: [
{
type: 'index-pattern',
Expand Down Expand Up @@ -591,7 +590,6 @@ describe('getSortedObjectsForExport()', () => {
const exportStream = await getSortedObjectsForExport({
exportSizeLimit: 10000,
savedObjectsClient,
types: ['index-pattern', 'search'],
objects: [
{
type: 'search',
Expand Down Expand Up @@ -672,7 +670,6 @@ describe('getSortedObjectsForExport()', () => {
const exportOpts = {
exportSizeLimit: 1,
savedObjectsClient,
types: ['index-pattern', 'search'],
objects: [
{
type: 'index-pattern',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ async function fetchObjectsToExport({
savedObjectsClient: SavedObjectsClientContract;
namespace?: string;
}) {
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`);
Expand Down
2 changes: 1 addition & 1 deletion src/core/server/saved_objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ export { SavedObjectMigrationMap, SavedObjectMigrationFn } from './migrations';

export { SavedObjectsType } from './types';

export { config } from './saved_objects_config';
export { savedObjectsConfig, savedObjectsMigrationConfig } from './saved_objects_config';
export { SavedObjectTypeRegistry, ISavedObjectTypeRegistry } from './saved_objects_type_registry';
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ import { docValidator, PropertyValidators } from '../../validation';
import { buildActiveMappings, CallCluster, IndexMigrator } from '../core';
import { DocumentMigrator, VersionedTransformer } from '../core/document_migrator';
import { createIndexMap } from '../core/build_index_map';
import { SavedObjectsConfigType } from '../../saved_objects_config';
import { SavedObjectsMigrationConfigType } from '../../saved_objects_config';
import { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry';
import { SavedObjectsType } from '../../types';

export interface KibanaMigratorOptions {
callCluster: CallCluster;
typeRegistry: ISavedObjectTypeRegistry;
savedObjectsConfig: SavedObjectsConfigType;
savedObjectsConfig: SavedObjectsMigrationConfigType;
kibanaConfig: KibanaConfigType;
kibanaVersion: string;
logger: Logger;
Expand All @@ -51,7 +51,7 @@ export type IKibanaMigrator = Pick<KibanaMigrator, keyof KibanaMigrator>;
*/
export class KibanaMigrator {
private readonly callCluster: CallCluster;
private readonly savedObjectsConfig: SavedObjectsConfigType;
private readonly savedObjectsConfig: SavedObjectsMigrationConfigType;
private readonly documentMigrator: VersionedTransformer;
private readonly kibanaConfig: KibanaConfigType;
private readonly log: Logger;
Expand Down
57 changes: 57 additions & 0 deletions src/core/server/saved_objects/routes/bulk_create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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 { schema } from '@kbn/config-schema';
import { IRouter } from '../../http';

export const registerBulkCreateRoute = (router: IRouter) => {
router.post(
{
path: '/_bulk_create',
validate: {
query: schema.object({
overwrite: schema.boolean({ defaultValue: false }),
}),
body: schema.arrayOf(
schema.object({
type: schema.string(),
id: schema.maybe(schema.string()),
attributes: schema.recordOf(schema.string(), schema.any()),
version: schema.maybe(schema.string()),
migrationVersion: schema.maybe(schema.recordOf(schema.string(), schema.string())),
references: schema.maybe(
schema.arrayOf(
schema.object({
name: schema.string(),
type: schema.string(),
id: schema.string(),
})
)
),
})
),
},
},
router.handleLegacyErrors(async (context, req, res) => {
const { overwrite } = req.query;
const result = await context.core.savedObjects.client.bulkCreate(req.body, { overwrite });
return res.ok({ body: result });
})
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,26 @@
* under the License.
*/

export { createBulkCreateRoute } from './bulk_create';
export { createBulkGetRoute } from './bulk_get';
export { createCreateRoute } from './create';
export { createDeleteRoute } from './delete';
export { createFindRoute } from './find';
export { createGetRoute } from './get';
export { createImportRoute } from './import';
export { createLogLegacyImportRoute } from './log_legacy_import';
export { createResolveImportErrorsRoute } from './resolve_import_errors';
export { createUpdateRoute } from './update';
export { createBulkUpdateRoute } from './bulk_update';
export { createExportRoute } from './export';
import { schema } from '@kbn/config-schema';
import { IRouter } from '../../http';

export const registerBulkGetRoute = (router: IRouter) => {
router.post(
{
path: '/_bulk_get',
validate: {
body: schema.arrayOf(
schema.object({
type: schema.string(),
id: schema.string(),
fields: schema.maybe(schema.arrayOf(schema.string())),
})
),
},
},
router.handleLegacyErrors(async (context, req, res) => {
const result = await context.core.savedObjects.client.bulkGet(req.body);
return res.ok({ body: result });
})
);
};
52 changes: 52 additions & 0 deletions src/core/server/saved_objects/routes/bulk_update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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 { schema } from '@kbn/config-schema';
import { IRouter } from '../../http';

export const registerBulkUpdateRoute = (router: IRouter) => {
router.put(
{
path: '/_bulk_update',
validate: {
body: schema.arrayOf(
schema.object({
type: schema.string(),
id: schema.string(),
attributes: schema.recordOf(schema.string(), schema.any()),
version: schema.maybe(schema.string()),
references: schema.maybe(
schema.arrayOf(
schema.object({
name: schema.string(),
type: schema.string(),
id: schema.string(),
})
)
),
})
),
},
},
router.handleLegacyErrors(async (context, req, res) => {
const savedObject = await context.core.savedObjects.client.bulkUpdate(req.body);
return res.ok({ body: savedObject });
})
);
};
60 changes: 60 additions & 0 deletions src/core/server/saved_objects/routes/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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 { schema } from '@kbn/config-schema';
import { IRouter } from '../../http';

export const registerCreateRoute = (router: IRouter) => {
router.post(
{
path: '/{type}/{id?}',
validate: {
params: schema.object({
type: schema.string(),
id: schema.maybe(schema.string()),
}),
query: schema.object({
overwrite: schema.boolean({ defaultValue: false }),
}),
body: schema.object({
attributes: schema.recordOf(schema.string(), schema.any()),
migrationVersion: schema.maybe(schema.recordOf(schema.string(), schema.string())),
references: schema.maybe(
schema.arrayOf(
schema.object({
name: schema.string(),
type: schema.string(),
id: schema.string(),
})
)
),
}),
},
},
router.handleLegacyErrors(async (context, req, res) => {
const { type, id } = req.params;
const { overwrite } = req.query;
const { attributes, migrationVersion, references } = req.body;

const options = { id, overwrite, migrationVersion, references };
const result = await context.core.savedObjects.client.create(type, attributes, options);
return res.ok({ body: result });
})
);
};
Loading

0 comments on commit ff7cd43

Please sign in to comment.