Allow legacy imports size respect savedObjects.maxImportPayloadBytes config (#77409)

This commit is contained in:
Josh Dover 2020-09-16 08:52:42 -06:00 committed by GitHub
parent 78774e4925
commit 9b6edc5cd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 43 additions and 16 deletions

View file

@ -23,7 +23,7 @@ experimental[] Import dashboards and corresponding saved objects.
[[dashboard-api-import-request-body]]
==== Request body
Use the complete response body from the <<dashboard-api-export, Export dashboard API>> as the request body. Do not manually construct a payload to the endpoint.
Use the complete response body from the <<dashboard-api-export, Export dashboard API>> as the request body. Do not manually construct a payload to the endpoint. The max payload size is determined by the `savedObjects.maxImportPayloadBytes` configuration key.
[[dashboard-api-import-response-body]]
==== Response body

View file

@ -12,5 +12,6 @@ export declare type SharedGlobalConfig = RecursiveReadonly<{
kibana: Pick<KibanaConfigType, typeof SharedGlobalConfigKeys.kibana[number]>;
elasticsearch: Pick<ElasticsearchConfigType, typeof SharedGlobalConfigKeys.elasticsearch[number]>;
path: Pick<PathConfigType, typeof SharedGlobalConfigKeys.path[number]>;
savedObjects: Pick<SavedObjectsConfigType, typeof SharedGlobalConfigKeys.savedObjects[number]>;
}>;
```

View file

@ -18,6 +18,7 @@
*/
import { of } from 'rxjs';
import { duration } from 'moment';
import { ByteSizeValue } from '@kbn/config-schema';
import { PluginInitializerContext, CoreSetup, CoreStart, StartServicesAccessor } from '.';
import { loggingSystemMock } from './logging/logging_system.mock';
import { loggingServiceMock } from './logging/logging_service.mock';
@ -66,6 +67,9 @@ export function pluginInitializerContextConfigMock<T>(config: T) {
startupTimeout: duration('30s'),
},
path: { data: '/tmp' },
savedObjects: {
maxImportPayloadBytes: new ByteSizeValue(10485760),
},
};
const mock: jest.Mocked<PluginInitializerContext<T>['config']> = {

View file

@ -28,6 +28,7 @@ import { rawConfigServiceMock, getEnvOptions } from '../config/mocks';
import { PluginManifest } from './types';
import { Server } from '../server';
import { fromRoot } from '../utils';
import { ByteSizeValue } from '@kbn/config-schema';
const logger = loggingSystemMock.create();
@ -93,6 +94,7 @@ describe('createPluginInitializerContext', () => {
startupTimeout: duration(5, 's'),
},
path: { data: fromRoot('data') },
savedObjects: { maxImportPayloadBytes: new ByteSizeValue(10485760) },
});
});

View file

@ -35,6 +35,7 @@ import {
ElasticsearchConfigType,
config as elasticsearchConfig,
} from '../elasticsearch/elasticsearch_config';
import { SavedObjectsConfigType, savedObjectsConfig } from '../saved_objects/saved_objects_config';
import { CoreSetup, CoreStart } from '..';
export interface InstanceInfo {
@ -91,16 +92,18 @@ export function createPluginInitializerContext(
* Note: naming not final here, it will be renamed in a near future (https://github.com/elastic/kibana/issues/46240)
* @deprecated
*/
globalConfig$: combineLatest(
globalConfig$: combineLatest([
coreContext.configService.atPath<KibanaConfigType>(kibanaConfig.path),
coreContext.configService.atPath<ElasticsearchConfigType>(elasticsearchConfig.path),
coreContext.configService.atPath<PathConfigType>(pathConfig.path)
).pipe(
map(([kibana, elasticsearch, path]) =>
coreContext.configService.atPath<PathConfigType>(pathConfig.path),
coreContext.configService.atPath<SavedObjectsConfigType>(savedObjectsConfig.path),
]).pipe(
map(([kibana, elasticsearch, path, savedObjects]) =>
deepFreeze({
kibana: pick(kibana, SharedGlobalConfigKeys.kibana),
elasticsearch: pick(elasticsearch, SharedGlobalConfigKeys.elasticsearch),
path: pick(path, SharedGlobalConfigKeys.path),
savedObjects: pick(savedObjects, SharedGlobalConfigKeys.savedObjects),
})
)
),

View file

@ -26,6 +26,7 @@ import { ConfigPath, EnvironmentMode, PackageInfo, ConfigDeprecationProvider } f
import { LoggerFactory } from '../logging';
import { KibanaConfigType } from '../kibana_config';
import { ElasticsearchConfigType } from '../elasticsearch/elasticsearch_config';
import { SavedObjectsConfigType } from '../saved_objects/saved_objects_config';
import { CoreSetup, CoreStart } from '..';
/**
@ -263,6 +264,7 @@ export const SharedGlobalConfigKeys = {
kibana: ['index', 'autocompleteTerminateAfter', 'autocompleteTimeout'] as const,
elasticsearch: ['shardTimeout', 'requestTimeout', 'pingTimeout', 'startupTimeout'] as const,
path: ['data'] as const,
savedObjects: ['maxImportPayloadBytes'] as const,
};
/**
@ -272,6 +274,7 @@ export type SharedGlobalConfig = RecursiveReadonly<{
kibana: Pick<KibanaConfigType, typeof SharedGlobalConfigKeys.kibana[number]>;
elasticsearch: Pick<ElasticsearchConfigType, typeof SharedGlobalConfigKeys.elasticsearch[number]>;
path: Pick<PathConfigType, typeof SharedGlobalConfigKeys.path[number]>;
savedObjects: Pick<SavedObjectsConfigType, typeof SharedGlobalConfigKeys.savedObjects[number]>;
}>;
/**

View file

@ -2661,6 +2661,7 @@ export type SharedGlobalConfig = RecursiveReadonly<{
kibana: Pick<KibanaConfigType_2, typeof SharedGlobalConfigKeys.kibana[number]>;
elasticsearch: Pick<ElasticsearchConfigType, typeof SharedGlobalConfigKeys.elasticsearch[number]>;
path: Pick<PathConfigType, typeof SharedGlobalConfigKeys.path[number]>;
savedObjects: Pick<SavedObjectsConfigType, typeof SharedGlobalConfigKeys.savedObjects[number]>;
}>;
// @public
@ -2745,7 +2746,8 @@ export const validBodyOutput: readonly ["data", "stream"];
//
// src/core/server/http/router/response.ts:316:3 - (ae-forgotten-export) The symbol "KibanaResponse" needs to be exported by the entry point index.d.ts
// src/core/server/legacy/types.ts:135:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:272:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:272:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:274:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:274:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:277:3 - (ae-forgotten-export) The symbol "SavedObjectsConfigType" needs to be exported by the entry point index.d.ts
```

View file

@ -18,18 +18,23 @@
*/
import { Plugin, CoreSetup, PluginInitializerContext } from 'kibana/server';
import { first } from 'rxjs/operators';
import { registerRoutes } from './routes';
export class LegacyExportPlugin implements Plugin<{}, {}> {
private readonly kibanaVersion: string;
constructor(private readonly initContext: PluginInitializerContext) {}
constructor(context: PluginInitializerContext) {
this.kibanaVersion = context.env.packageInfo.version;
}
public async setup({ http }: CoreSetup) {
const globalConfig = await this.initContext.config.legacy.globalConfig$
.pipe(first())
.toPromise();
public setup({ http }: CoreSetup) {
const router = http.createRouter();
registerRoutes(router, this.kibanaVersion);
registerRoutes(
router,
this.initContext.env.packageInfo.version,
globalConfig.savedObjects.maxImportPayloadBytes.getValueInBytes()
);
return {};
}

View file

@ -21,7 +21,7 @@ import { schema } from '@kbn/config-schema';
import { IRouter, SavedObject } from 'src/core/server';
import { importDashboards } from '../lib';
export const registerImportRoute = (router: IRouter) => {
export const registerImportRoute = (router: IRouter, maxImportPayloadBytes: number) => {
router.post(
{
path: '/api/kibana/dashboards/import',
@ -39,6 +39,9 @@ export const registerImportRoute = (router: IRouter) => {
},
options: {
tags: ['api'],
body: {
maxBytes: maxImportPayloadBytes,
},
},
},
async (ctx, req, res) => {

View file

@ -21,7 +21,11 @@ import { IRouter } from 'src/core/server';
import { registerImportRoute } from './import';
import { registerExportRoute } from './export';
export const registerRoutes = (router: IRouter, kibanaVersion: string) => {
export const registerRoutes = (
router: IRouter,
kibanaVersion: string,
maxImportPayloadBytes: number
) => {
registerExportRoute(router, kibanaVersion);
registerImportRoute(router);
registerImportRoute(router, maxImportPayloadBytes);
};