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

Run SO migration after plugins setup phase. #55012

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5419124
change setClientFactory api to setClientFactoryProvider
pgayvallet Jan 16, 2020
3a45728
cleanup and add test for service
pgayvallet Jan 16, 2020
3b6a092
change the signatures of SO start/setup
pgayvallet Jan 16, 2020
a5e0b12
fix registerCoreContext by accessing stored start contract reference
pgayvallet Jan 17, 2020
8e2394c
move migration inside `start`
pgayvallet Jan 17, 2020
2ebe9dd
adapt and add service tests
pgayvallet Jan 17, 2020
14d36c6
add doc and export new types
pgayvallet Jan 17, 2020
7860fc5
Merge remote-tracking branch 'upstream/master' into kbn-52071-so-migr…
pgayvallet Jan 20, 2020
098b522
adapt plugins code
pgayvallet Jan 20, 2020
a8070c9
update generated doc
pgayvallet Jan 20, 2020
cab3e6c
Merge remote-tracking branch 'upstream/master' into kbn-52071-so-migr…
pgayvallet Jan 21, 2020
fed6d58
better core access
pgayvallet Jan 21, 2020
798deae
address some review comments
pgayvallet Jan 21, 2020
511c4fa
remove parametrized type from SavedObjectsClientFactory, use KibanaRe…
pgayvallet Jan 21, 2020
ceec182
add logs when starting and ending so migration
pgayvallet Jan 21, 2020
e20a6de
Merge remote-tracking branch 'upstream/master' into kbn-52071-so-migr…
pgayvallet Jan 21, 2020
51c0ec0
fix KibanaRequest imports
pgayvallet Jan 21, 2020
d4b16db
Merge remote-tracking branch 'upstream/master' into kbn-52071-so-migr…
pgayvallet Jan 22, 2020
961fec1
NITs and review comments
pgayvallet Jan 22, 2020
8c213a0
fix alerting FTR test
pgayvallet Jan 22, 2020
ba749ba
review comments
pgayvallet Jan 23, 2020
f7a4051
Merge remote-tracking branch 'upstream/master' into kbn-52071-so-migr…
pgayvallet Jan 23, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/core/server/legacy/legacy_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,8 @@ export class LegacyService implements CoreService {
isTlsEnabled: setupDeps.core.http.isTlsEnabled,
},
savedObjects: {
setClientFactory: setupDeps.core.savedObjects.setClientFactory,
setClientFactoryProvider: setupDeps.core.savedObjects.setClientFactoryProvider,
addClientWrapper: setupDeps.core.savedObjects.addClientWrapper,
createInternalRepository: setupDeps.core.savedObjects.createInternalRepository,
createScopedRepository: setupDeps.core.savedObjects.createScopedRepository,
},
uiSettings: {
register: setupDeps.core.uiSettings.register,
Expand All @@ -287,7 +285,11 @@ export class LegacyService implements CoreService {
};
const coreStart: CoreStart = {
capabilities: startDeps.core.capabilities,
savedObjects: { getScopedClient: startDeps.core.savedObjects.getScopedClient },
savedObjects: {
getScopedClient: startDeps.core.savedObjects.getScopedClient,
createInternalRepository: startDeps.core.savedObjects.createInternalRepository,
createScopedRepository: startDeps.core.savedObjects.createScopedRepository,
},
uiSettings: { asScopedToClient: startDeps.core.uiSettings.asScopedToClient },
};

Expand Down
6 changes: 3 additions & 3 deletions src/core/server/plugins/plugin_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,8 @@ export function createPluginSetupContext<TPlugin, TPluginDependencies>(
isTlsEnabled: deps.http.isTlsEnabled,
},
savedObjects: {
setClientFactory: deps.savedObjects.setClientFactory,
setClientFactoryProvider: deps.savedObjects.setClientFactoryProvider,
addClientWrapper: deps.savedObjects.addClientWrapper,
createInternalRepository: deps.savedObjects.createInternalRepository,
createScopedRepository: deps.savedObjects.createScopedRepository,
},
uiSettings: {
register: deps.uiSettings.register,
Expand Down Expand Up @@ -202,6 +200,8 @@ export function createPluginStartContext<TPlugin, TPluginDependencies>(
},
savedObjects: {
getScopedClient: deps.savedObjects.getScopedClient,
createInternalRepository: deps.savedObjects.createInternalRepository,
createScopedRepository: deps.savedObjects.createScopedRepository,
},
uiSettings: {
asScopedToClient: deps.uiSettings.asScopedToClient,
Expand Down
21 changes: 10 additions & 11 deletions src/core/server/saved_objects/saved_objects_service.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,31 +33,30 @@ const createStartContractMock = () => {
const startContract: jest.Mocked<InternalSavedObjectsServiceStart> = {
clientProvider: savedObjectsClientProviderMock.create(),
getScopedClient: jest.fn(),
createInternalRepository: jest.fn(),
createScopedRepository: jest.fn(),
migrator: mockKibanaMigrator.create(),
};

startContract.getScopedClient.mockReturnValue(savedObjectsClientMock.create());
startContract.createInternalRepository.mockReturnValue(savedObjectsRepositoryMock.create());
startContract.createScopedRepository.mockReturnValue(savedObjectsRepositoryMock.create());

return startContract;
};

const createSetupContractMock = () => {
const setupContract: jest.Mocked<InternalSavedObjectsServiceSetup> = {
getScopedClient: jest.fn(),
setClientFactory: jest.fn(),
setClientFactoryProvider: jest.fn(),
addClientWrapper: jest.fn(),
createInternalRepository: jest.fn(),
createScopedRepository: jest.fn(),
};

setupContract.getScopedClient.mockReturnValue(savedObjectsClientMock.create());
setupContract.createInternalRepository.mockReturnValue(savedObjectsRepositoryMock.create());
setupContract.createScopedRepository.mockReturnValue(savedObjectsRepositoryMock.create());

return setupContract;
};

const createsavedObjectsServiceMock = () => {
const createSavedObjectsServiceMock = () => {
const mocked: jest.Mocked<SavedObjectsServiceContract> = {
setup: jest.fn(),
runMigration: jest.fn(),
start: jest.fn(),
stop: jest.fn(),
};
Expand All @@ -69,7 +68,7 @@ const createsavedObjectsServiceMock = () => {
};

export const savedObjectsServiceMock = {
create: createsavedObjectsServiceMock,
create: createSavedObjectsServiceMock,
createSetupContract: createSetupContractMock,
createStartContract: createStartContractMock,
};
32 changes: 32 additions & 0 deletions src/core/server/saved_objects/saved_objects_service.test.mocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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 { mockKibanaMigrator } from './migrations/kibana/kibana_migrator.mock';
import { savedObjectsClientProviderMock } from './service/lib/scoped_client_provider.mock';

export const migratorInstanceMock = mockKibanaMigrator.create();
export const KibanaMigratorMock = jest.fn().mockImplementation(() => migratorInstanceMock);
jest.doMock('./migrations/kibana/kibana_migrator', () => ({
KibanaMigrator: KibanaMigratorMock,
}));

export const clientProviderInstanceMock = savedObjectsClientProviderMock.create();
jest.doMock('./service/lib/scoped_client_provider', () => ({
SavedObjectsClientProvider: jest.fn().mockImplementation(() => clientProviderInstanceMock),
}));
72 changes: 39 additions & 33 deletions src/core/server/saved_objects/saved_objects_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,32 @@
* under the License.
*/

jest.mock('./migrations/kibana/kibana_migrator');
import {
KibanaMigratorMock,
migratorInstanceMock,
clientProviderInstanceMock,
} from './saved_objects_service.test.mocks';

import { SavedObjectsService, SavedObjectsSetupDeps } from './saved_objects_service';
import { mockCoreContext } from '../core_context.mock';
// @ts-ignore Typescript doesn't know about the jest mock
import { KibanaMigrator, mockKibanaMigratorInstance } from './migrations/kibana/kibana_migrator';
import * as legacyElasticsearch from 'elasticsearch';
import { Env } from '../config';
import { configServiceMock } from '../mocks';
import { SavedObjectsClientFactoryProvider } from './service/lib';
import { KibanaRequest } from '../http';

afterEach(() => {
jest.clearAllMocks();
});

describe('SavedObjectsService', () => {
const createSetupDeps = ({ clusterClient = { callAsInternalUser: jest.fn() } }) => {
return ({
elasticsearch: { adminClient: clusterClient },
mshustov marked this conversation as resolved.
Show resolved Hide resolved
legacyPlugins: { uiExports: { savedObjectMappings: [] }, pluginExtendedConfig: {} },
} as unknown) as SavedObjectsSetupDeps;
};

describe('#setup()', () => {
it('creates a KibanaMigrator which retries NoConnections errors from callAsInternalUser', async () => {
const coreContext = mockCoreContext.create();
Expand All @@ -47,16 +58,25 @@ describe('SavedObjectsService', () => {
};

const soService = new SavedObjectsService(coreContext);
const coreSetup = ({
elasticsearch: { adminClient: clusterClient },
legacyPlugins: { uiExports: { savedObjectMappings: [] }, pluginExtendedConfig: {} },
} as unknown) as SavedObjectsSetupDeps;
const coreSetup = createSetupDeps({ clusterClient });

await soService.setup(coreSetup, 1);

return expect((KibanaMigrator as jest.Mock).mock.calls[0][0].callCluster()).resolves.toMatch(
'success'
);
return expect(KibanaMigratorMock.mock.calls[0][0].callCluster()).resolves.toMatch('success');
});

describe('#setClientFactoryProvider', () => {
it('registers the factory to the clientProvider', async () => {
const coreContext = mockCoreContext.create();
const soService = new SavedObjectsService(coreContext);
const setup = await soService.setup(createSetupDeps({}));

const factory = jest.fn();
const factoryProvider: SavedObjectsClientFactoryProvider<KibanaRequest> = () => factory;

setup.setClientFactoryProvider(factoryProvider);
expect(clientProviderInstanceMock.setClientFactory).toHaveBeenCalledWith(factory);
});
});
});

Expand All @@ -66,46 +86,32 @@ describe('SavedObjectsService', () => {
env: ({ cliArgs: { optimize: true }, packageInfo: { version: 'x.x.x' } } as unknown) as Env,
});
const soService = new SavedObjectsService(coreContext);
const coreSetup = ({
elasticsearch: { adminClient: { callAsInternalUser: jest.fn() } },
legacyPlugins: { uiExports: {}, pluginExtendedConfig: {} },
} as unknown) as SavedObjectsSetupDeps;

await soService.setup(coreSetup);
await soService.setup(createSetupDeps({}));
await soService.start({});
expect(mockKibanaMigratorInstance.runMigrations).toHaveBeenCalledWith(true);
expect(migratorInstanceMock.runMigrations).toHaveBeenCalledWith(true);
});

it('skips KibanaMigrator migrations when migrations.skip=true', async () => {
const configService = configServiceMock.create({ atPath: { skip: true } });
const coreContext = mockCoreContext.create({ configService });
const soService = new SavedObjectsService(coreContext);
const coreSetup = ({
elasticsearch: { adminClient: { callAsInternalUser: jest.fn() } },
legacyPlugins: { uiExports: {}, pluginExtendedConfig: {} },
} as unknown) as SavedObjectsSetupDeps;

await soService.setup(coreSetup);
await soService.setup(createSetupDeps({}));
await soService.start({});
expect(mockKibanaMigratorInstance.runMigrations).toHaveBeenCalledWith(true);
expect(migratorInstanceMock.runMigrations).toHaveBeenCalledWith(true);
});

it('resolves with KibanaMigrator after waiting for migrations to complete', async () => {
const configService = configServiceMock.create({ atPath: { skip: false } });
const coreContext = mockCoreContext.create({ configService });
const soService = new SavedObjectsService(coreContext);
const coreSetup = ({
elasticsearch: { adminClient: { callAsInternalUser: jest.fn() } },
legacyPlugins: { uiExports: {}, pluginExtendedConfig: {} },
} as unknown) as SavedObjectsSetupDeps;

await soService.setup(coreSetup);
expect(mockKibanaMigratorInstance.runMigrations).toHaveBeenCalledTimes(0);
await soService.setup(createSetupDeps({}));
expect(migratorInstanceMock.runMigrations).toHaveBeenCalledTimes(0);

const startContract = await soService.start({});
expect(startContract.migrator).toBe(mockKibanaMigratorInstance);
expect(mockKibanaMigratorInstance.runMigrations).toHaveBeenCalledWith(false);
expect(mockKibanaMigratorInstance.runMigrations).toHaveBeenCalledTimes(1);
expect(startContract.migrator).toBe(migratorInstanceMock);
expect(migratorInstanceMock.runMigrations).toHaveBeenCalledWith(false);
expect(migratorInstanceMock.runMigrations).toHaveBeenCalledTimes(1);
});
});
});
Loading