mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Migrate data folder creation from legacy to KP (#75527)
* rename uuid service to environment service * adapt resolve_uuid to directly use the configurations * move data folder creation to core * update generated doc * fix types * fix monitoring tests * move instanceUuid to plugin initializer context * update generated doc
This commit is contained in:
parent
61550b7ce0
commit
eee139295d
39 changed files with 504 additions and 252 deletions
|
@ -26,5 +26,4 @@ export interface CoreSetup<TPluginsStart extends object = object, TStart = unkno
|
|||
| [savedObjects](./kibana-plugin-core-server.coresetup.savedobjects.md) | <code>SavedObjectsServiceSetup</code> | [SavedObjectsServiceSetup](./kibana-plugin-core-server.savedobjectsservicesetup.md) |
|
||||
| [status](./kibana-plugin-core-server.coresetup.status.md) | <code>StatusServiceSetup</code> | [StatusServiceSetup](./kibana-plugin-core-server.statusservicesetup.md) |
|
||||
| [uiSettings](./kibana-plugin-core-server.coresetup.uisettings.md) | <code>UiSettingsServiceSetup</code> | [UiSettingsServiceSetup](./kibana-plugin-core-server.uisettingsservicesetup.md) |
|
||||
| [uuid](./kibana-plugin-core-server.coresetup.uuid.md) | <code>UuidServiceSetup</code> | [UuidServiceSetup](./kibana-plugin-core-server.uuidservicesetup.md) |
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [CoreSetup](./kibana-plugin-core-server.coresetup.md) > [uuid](./kibana-plugin-core-server.coresetup.uuid.md)
|
||||
|
||||
## CoreSetup.uuid property
|
||||
|
||||
[UuidServiceSetup](./kibana-plugin-core-server.uuidservicesetup.md)
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
uuid: UuidServiceSetup;
|
||||
```
|
|
@ -214,7 +214,6 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
| [UiSettingsServiceStart](./kibana-plugin-core-server.uisettingsservicestart.md) | |
|
||||
| [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) | We define our own typings because the current version of @<!-- -->types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". |
|
||||
| [UserProvidedValues](./kibana-plugin-core-server.userprovidedvalues.md) | Describes the values explicitly set by user. |
|
||||
| [UuidServiceSetup](./kibana-plugin-core-server.uuidservicesetup.md) | APIs to access the application's instance uuid. |
|
||||
|
||||
## Variables
|
||||
|
||||
|
|
|
@ -10,5 +10,6 @@
|
|||
env: {
|
||||
mode: EnvironmentMode;
|
||||
packageInfo: Readonly<PackageInfo>;
|
||||
instanceUuid: string;
|
||||
};
|
||||
```
|
||||
|
|
|
@ -17,7 +17,7 @@ export interface PluginInitializerContext<ConfigSchema = unknown>
|
|||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [config](./kibana-plugin-core-server.plugininitializercontext.config.md) | <code>{</code><br/><code> legacy: {</code><br/><code> globalConfig$: Observable<SharedGlobalConfig>;</code><br/><code> };</code><br/><code> create: <T = ConfigSchema>() => Observable<T>;</code><br/><code> createIfExists: <T = ConfigSchema>() => Observable<T | undefined>;</code><br/><code> }</code> | |
|
||||
| [env](./kibana-plugin-core-server.plugininitializercontext.env.md) | <code>{</code><br/><code> mode: EnvironmentMode;</code><br/><code> packageInfo: Readonly<PackageInfo>;</code><br/><code> }</code> | |
|
||||
| [env](./kibana-plugin-core-server.plugininitializercontext.env.md) | <code>{</code><br/><code> mode: EnvironmentMode;</code><br/><code> packageInfo: Readonly<PackageInfo>;</code><br/><code> instanceUuid: string;</code><br/><code> }</code> | |
|
||||
| [logger](./kibana-plugin-core-server.plugininitializercontext.logger.md) | <code>LoggerFactory</code> | |
|
||||
| [opaqueId](./kibana-plugin-core-server.plugininitializercontext.opaqueid.md) | <code>PluginOpaqueId</code> | |
|
||||
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [UuidServiceSetup](./kibana-plugin-core-server.uuidservicesetup.md) > [getInstanceUuid](./kibana-plugin-core-server.uuidservicesetup.getinstanceuuid.md)
|
||||
|
||||
## UuidServiceSetup.getInstanceUuid() method
|
||||
|
||||
Retrieve the Kibana instance uuid.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
getInstanceUuid(): string;
|
||||
```
|
||||
<b>Returns:</b>
|
||||
|
||||
`string`
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [UuidServiceSetup](./kibana-plugin-core-server.uuidservicesetup.md)
|
||||
|
||||
## UuidServiceSetup interface
|
||||
|
||||
APIs to access the application's instance uuid.
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface UuidServiceSetup
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
| Method | Description |
|
||||
| --- | --- |
|
||||
| [getInstanceUuid()](./kibana-plugin-core-server.uuidservicesetup.getinstanceuuid.md) | Retrieve the Kibana instance uuid. |
|
||||
|
79
src/core/server/environment/create_data_folder.test.ts
Normal file
79
src/core/server/environment/create_data_folder.test.ts
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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 { PathConfigType } from '../path';
|
||||
import { createDataFolder } from './create_data_folder';
|
||||
import { mkdir } from './fs';
|
||||
import { loggingSystemMock } from '../logging/logging_system.mock';
|
||||
|
||||
jest.mock('./fs', () => ({
|
||||
mkdir: jest.fn(() => Promise.resolve('')),
|
||||
}));
|
||||
|
||||
const mkdirMock = mkdir as jest.Mock;
|
||||
|
||||
describe('createDataFolder', () => {
|
||||
let logger: ReturnType<typeof loggingSystemMock.createLogger>;
|
||||
let pathConfig: PathConfigType;
|
||||
|
||||
beforeEach(() => {
|
||||
logger = loggingSystemMock.createLogger();
|
||||
pathConfig = {
|
||||
data: '/path/to/data/folder',
|
||||
};
|
||||
mkdirMock.mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('calls `mkdir` with the correct parameters', async () => {
|
||||
await createDataFolder({ pathConfig, logger });
|
||||
expect(mkdirMock).toHaveBeenCalledTimes(1);
|
||||
expect(mkdirMock).toHaveBeenCalledWith(pathConfig.data, { recursive: true });
|
||||
});
|
||||
|
||||
it('does not log error if the `mkdir` call is successful', async () => {
|
||||
await createDataFolder({ pathConfig, logger });
|
||||
expect(logger.error).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('throws an error if the `mkdir` call fails', async () => {
|
||||
mkdirMock.mockRejectedValue('some-error');
|
||||
await expect(() => createDataFolder({ pathConfig, logger })).rejects.toMatchInlineSnapshot(
|
||||
`"some-error"`
|
||||
);
|
||||
});
|
||||
|
||||
it('logs an error message if the `mkdir` call fails', async () => {
|
||||
mkdirMock.mockRejectedValue('some-error');
|
||||
try {
|
||||
await createDataFolder({ pathConfig, logger });
|
||||
} catch (e) {
|
||||
/* trap */
|
||||
}
|
||||
expect(logger.error).toHaveBeenCalledTimes(1);
|
||||
expect(logger.error.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"Error trying to create data folder at /path/to/data/folder: some-error",
|
||||
]
|
||||
`);
|
||||
});
|
||||
});
|
40
src/core/server/environment/create_data_folder.ts
Normal file
40
src/core/server/environment/create_data_folder.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 { mkdir } from './fs';
|
||||
import { Logger } from '../logging';
|
||||
import { PathConfigType } from '../path';
|
||||
|
||||
export async function createDataFolder({
|
||||
pathConfig,
|
||||
logger,
|
||||
}: {
|
||||
pathConfig: PathConfigType;
|
||||
logger: Logger;
|
||||
}): Promise<void> {
|
||||
const dataFolder = pathConfig.data;
|
||||
try {
|
||||
// Create the data directory (recursively, if the a parent dir doesn't exist).
|
||||
// If it already exists, does nothing.
|
||||
await mkdir(dataFolder, { recursive: true });
|
||||
} catch (e) {
|
||||
logger.error(`Error trying to create data folder at ${dataFolder}: ${e}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
|
@ -17,25 +17,25 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { UuidService, UuidServiceSetup } from './uuid_service';
|
||||
import { EnvironmentService, InternalEnvironmentServiceSetup } from './environment_service';
|
||||
|
||||
const createSetupContractMock = () => {
|
||||
const setupContract: jest.Mocked<UuidServiceSetup> = {
|
||||
getInstanceUuid: jest.fn().mockImplementation(() => 'uuid'),
|
||||
const setupContract: jest.Mocked<InternalEnvironmentServiceSetup> = {
|
||||
instanceUuid: 'uuid',
|
||||
};
|
||||
return setupContract;
|
||||
};
|
||||
|
||||
type UuidServiceContract = PublicMethodsOf<UuidService>;
|
||||
type EnvironmentServiceContract = PublicMethodsOf<EnvironmentService>;
|
||||
const createMock = () => {
|
||||
const mocked: jest.Mocked<UuidServiceContract> = {
|
||||
const mocked: jest.Mocked<EnvironmentServiceContract> = {
|
||||
setup: jest.fn(),
|
||||
};
|
||||
mocked.setup.mockResolvedValue(createSetupContractMock());
|
||||
return mocked;
|
||||
};
|
||||
|
||||
export const uuidServiceMock = {
|
||||
export const environmentServiceMock = {
|
||||
create: createMock,
|
||||
createSetupContract: createSetupContractMock,
|
||||
};
|
|
@ -17,10 +17,13 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { UuidService } from './uuid_service';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { EnvironmentService } from './environment_service';
|
||||
import { resolveInstanceUuid } from './resolve_uuid';
|
||||
import { createDataFolder } from './create_data_folder';
|
||||
import { CoreContext } from '../core_context';
|
||||
|
||||
import { configServiceMock } from '../config/config_service.mock';
|
||||
import { loggingSystemMock } from '../logging/logging_system.mock';
|
||||
import { mockCoreContext } from '../core_context.mock';
|
||||
|
||||
|
@ -28,31 +31,69 @@ jest.mock('./resolve_uuid', () => ({
|
|||
resolveInstanceUuid: jest.fn().mockResolvedValue('SOME_UUID'),
|
||||
}));
|
||||
|
||||
jest.mock('./create_data_folder', () => ({
|
||||
createDataFolder: jest.fn(),
|
||||
}));
|
||||
|
||||
const pathConfig = {
|
||||
data: 'data-folder',
|
||||
};
|
||||
const serverConfig = {
|
||||
uuid: 'SOME_UUID',
|
||||
};
|
||||
|
||||
const getConfigService = () => {
|
||||
const configService = configServiceMock.create();
|
||||
configService.atPath.mockImplementation((path) => {
|
||||
if (path === 'path') {
|
||||
return new BehaviorSubject(pathConfig);
|
||||
}
|
||||
if (path === 'server') {
|
||||
return new BehaviorSubject(serverConfig);
|
||||
}
|
||||
return new BehaviorSubject({});
|
||||
});
|
||||
return configService;
|
||||
};
|
||||
|
||||
describe('UuidService', () => {
|
||||
let logger: ReturnType<typeof loggingSystemMock.create>;
|
||||
let configService: ReturnType<typeof configServiceMock.create>;
|
||||
let coreContext: CoreContext;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
logger = loggingSystemMock.create();
|
||||
coreContext = mockCoreContext.create({ logger });
|
||||
configService = getConfigService();
|
||||
coreContext = mockCoreContext.create({ logger, configService });
|
||||
});
|
||||
|
||||
describe('#setup()', () => {
|
||||
it('calls resolveInstanceUuid with core configuration service', async () => {
|
||||
const service = new UuidService(coreContext);
|
||||
it('calls resolveInstanceUuid with correct parameters', async () => {
|
||||
const service = new EnvironmentService(coreContext);
|
||||
await service.setup();
|
||||
expect(resolveInstanceUuid).toHaveBeenCalledTimes(1);
|
||||
expect(resolveInstanceUuid).toHaveBeenCalledWith({
|
||||
configService: coreContext.configService,
|
||||
pathConfig,
|
||||
serverConfig,
|
||||
logger: logger.get('uuid'),
|
||||
});
|
||||
});
|
||||
|
||||
it('calls createDataFolder with correct parameters', async () => {
|
||||
const service = new EnvironmentService(coreContext);
|
||||
await service.setup();
|
||||
expect(createDataFolder).toHaveBeenCalledTimes(1);
|
||||
expect(createDataFolder).toHaveBeenCalledWith({
|
||||
pathConfig,
|
||||
logger: logger.get('uuid'),
|
||||
});
|
||||
});
|
||||
|
||||
it('returns the uuid resolved from resolveInstanceUuid', async () => {
|
||||
const service = new UuidService(coreContext);
|
||||
const service = new EnvironmentService(coreContext);
|
||||
const setup = await service.setup();
|
||||
expect(setup.getInstanceUuid()).toEqual('SOME_UUID');
|
||||
expect(setup.instanceUuid).toEqual('SOME_UUID');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -17,25 +17,27 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { resolveInstanceUuid } from './resolve_uuid';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { CoreContext } from '../core_context';
|
||||
import { Logger } from '../logging';
|
||||
import { IConfigService } from '../config';
|
||||
import { PathConfigType, config as pathConfigDef } from '../path';
|
||||
import { HttpConfigType, config as httpConfigDef } from '../http';
|
||||
import { resolveInstanceUuid } from './resolve_uuid';
|
||||
import { createDataFolder } from './create_data_folder';
|
||||
|
||||
/**
|
||||
* APIs to access the application's instance uuid.
|
||||
*
|
||||
* @public
|
||||
* @internal
|
||||
*/
|
||||
export interface UuidServiceSetup {
|
||||
export interface InternalEnvironmentServiceSetup {
|
||||
/**
|
||||
* Retrieve the Kibana instance uuid.
|
||||
*/
|
||||
getInstanceUuid(): string;
|
||||
instanceUuid: string;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export class UuidService {
|
||||
export class EnvironmentService {
|
||||
private readonly log: Logger;
|
||||
private readonly configService: IConfigService;
|
||||
private uuid: string = '';
|
||||
|
@ -46,13 +48,21 @@ export class UuidService {
|
|||
}
|
||||
|
||||
public async setup() {
|
||||
const [pathConfig, serverConfig] = await Promise.all([
|
||||
this.configService.atPath<PathConfigType>(pathConfigDef.path).pipe(take(1)).toPromise(),
|
||||
this.configService.atPath<HttpConfigType>(httpConfigDef.path).pipe(take(1)).toPromise(),
|
||||
]);
|
||||
|
||||
await createDataFolder({ pathConfig, logger: this.log });
|
||||
|
||||
this.uuid = await resolveInstanceUuid({
|
||||
configService: this.configService,
|
||||
pathConfig,
|
||||
serverConfig,
|
||||
logger: this.log,
|
||||
});
|
||||
|
||||
return {
|
||||
getInstanceUuid: () => this.uuid,
|
||||
instanceUuid: this.uuid,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -22,3 +22,4 @@ import { promisify } from 'util';
|
|||
|
||||
export const readFile = promisify(Fs.readFile);
|
||||
export const writeFile = promisify(Fs.writeFile);
|
||||
export const mkdir = promisify(Fs.mkdir);
|
|
@ -17,4 +17,4 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export { UuidService, UuidServiceSetup } from './uuid_service';
|
||||
export { EnvironmentService, InternalEnvironmentServiceSetup } from './environment_service';
|
|
@ -18,12 +18,11 @@
|
|||
*/
|
||||
|
||||
import { join } from 'path';
|
||||
import { loggingSystemMock } from '../logging/logging_system.mock';
|
||||
import { readFile, writeFile } from './fs';
|
||||
import { resolveInstanceUuid, UUID_7_6_0_BUG } from './resolve_uuid';
|
||||
import { configServiceMock } from '../config/config_service.mock';
|
||||
import { loggingSystemMock } from '../logging/logging_system.mock';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { Logger } from '../logging';
|
||||
import { PathConfigType } from '../path';
|
||||
import { HttpConfigType } from '../http';
|
||||
|
||||
jest.mock('uuid', () => ({
|
||||
v4: () => 'NEW_UUID',
|
||||
|
@ -66,40 +65,34 @@ const mockWriteFile = (error?: object) => {
|
|||
});
|
||||
};
|
||||
|
||||
const getConfigService = (serverUuid: string | undefined) => {
|
||||
const configService = configServiceMock.create();
|
||||
configService.atPath.mockImplementation((path) => {
|
||||
if (path === 'path') {
|
||||
return new BehaviorSubject({
|
||||
data: 'data-folder',
|
||||
});
|
||||
}
|
||||
if (path === 'server') {
|
||||
return new BehaviorSubject({
|
||||
uuid: serverUuid,
|
||||
});
|
||||
}
|
||||
return new BehaviorSubject({});
|
||||
});
|
||||
return configService;
|
||||
const createServerConfig = (serverUuid: string | undefined) => {
|
||||
return {
|
||||
uuid: serverUuid,
|
||||
} as HttpConfigType;
|
||||
};
|
||||
|
||||
describe('resolveInstanceUuid', () => {
|
||||
let configService: ReturnType<typeof configServiceMock.create>;
|
||||
let logger: jest.Mocked<Logger>;
|
||||
let logger: ReturnType<typeof loggingSystemMock.createLogger>;
|
||||
let pathConfig: PathConfigType;
|
||||
let serverConfig: HttpConfigType;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
mockReadFile({ uuid: DEFAULT_FILE_UUID });
|
||||
mockWriteFile();
|
||||
configService = getConfigService(DEFAULT_CONFIG_UUID);
|
||||
logger = loggingSystemMock.create().get() as any;
|
||||
|
||||
pathConfig = {
|
||||
data: 'data-folder',
|
||||
};
|
||||
serverConfig = createServerConfig(DEFAULT_CONFIG_UUID);
|
||||
|
||||
logger = loggingSystemMock.createLogger();
|
||||
});
|
||||
|
||||
describe('when file is present and config property is set', () => {
|
||||
describe('when they mismatch', () => {
|
||||
it('writes to file and returns the config uuid', async () => {
|
||||
const uuid = await resolveInstanceUuid({ configService, logger });
|
||||
const uuid = await resolveInstanceUuid({ pathConfig, serverConfig, logger });
|
||||
expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
|
||||
expect(writeFile).toHaveBeenCalledWith(
|
||||
join('data-folder', 'uuid'),
|
||||
|
@ -118,7 +111,7 @@ describe('resolveInstanceUuid', () => {
|
|||
describe('when they match', () => {
|
||||
it('does not write to file', async () => {
|
||||
mockReadFile({ uuid: DEFAULT_CONFIG_UUID });
|
||||
const uuid = await resolveInstanceUuid({ configService, logger });
|
||||
const uuid = await resolveInstanceUuid({ pathConfig, serverConfig, logger });
|
||||
expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
|
||||
expect(writeFile).not.toHaveBeenCalled();
|
||||
expect(logger.debug).toHaveBeenCalledTimes(1);
|
||||
|
@ -134,7 +127,7 @@ describe('resolveInstanceUuid', () => {
|
|||
describe('when file is not present and config property is set', () => {
|
||||
it('writes the uuid to file and returns the config uuid', async () => {
|
||||
mockReadFile({ error: fileNotFoundError });
|
||||
const uuid = await resolveInstanceUuid({ configService, logger });
|
||||
const uuid = await resolveInstanceUuid({ pathConfig, serverConfig, logger });
|
||||
expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
|
||||
expect(writeFile).toHaveBeenCalledWith(
|
||||
join('data-folder', 'uuid'),
|
||||
|
@ -152,8 +145,8 @@ describe('resolveInstanceUuid', () => {
|
|||
|
||||
describe('when file is present and config property is not set', () => {
|
||||
it('does not write to file and returns the file uuid', async () => {
|
||||
configService = getConfigService(undefined);
|
||||
const uuid = await resolveInstanceUuid({ configService, logger });
|
||||
serverConfig = createServerConfig(undefined);
|
||||
const uuid = await resolveInstanceUuid({ pathConfig, serverConfig, logger });
|
||||
expect(uuid).toEqual(DEFAULT_FILE_UUID);
|
||||
expect(writeFile).not.toHaveBeenCalled();
|
||||
expect(logger.debug).toHaveBeenCalledTimes(1);
|
||||
|
@ -169,8 +162,8 @@ describe('resolveInstanceUuid', () => {
|
|||
describe('when config property is not set', () => {
|
||||
it('writes new uuid to file and returns new uuid', async () => {
|
||||
mockReadFile({ uuid: UUID_7_6_0_BUG });
|
||||
configService = getConfigService(undefined);
|
||||
const uuid = await resolveInstanceUuid({ configService, logger });
|
||||
serverConfig = createServerConfig(undefined);
|
||||
const uuid = await resolveInstanceUuid({ pathConfig, serverConfig, logger });
|
||||
expect(uuid).not.toEqual(UUID_7_6_0_BUG);
|
||||
expect(uuid).toEqual('NEW_UUID');
|
||||
expect(writeFile).toHaveBeenCalledWith(
|
||||
|
@ -195,8 +188,8 @@ describe('resolveInstanceUuid', () => {
|
|||
describe('when config property is set', () => {
|
||||
it('writes config uuid to file and returns config uuid', async () => {
|
||||
mockReadFile({ uuid: UUID_7_6_0_BUG });
|
||||
configService = getConfigService(DEFAULT_CONFIG_UUID);
|
||||
const uuid = await resolveInstanceUuid({ configService, logger });
|
||||
serverConfig = createServerConfig(DEFAULT_CONFIG_UUID);
|
||||
const uuid = await resolveInstanceUuid({ pathConfig, serverConfig, logger });
|
||||
expect(uuid).not.toEqual(UUID_7_6_0_BUG);
|
||||
expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
|
||||
expect(writeFile).toHaveBeenCalledWith(
|
||||
|
@ -221,9 +214,9 @@ describe('resolveInstanceUuid', () => {
|
|||
|
||||
describe('when file is not present and config property is not set', () => {
|
||||
it('generates a new uuid and write it to file', async () => {
|
||||
configService = getConfigService(undefined);
|
||||
serverConfig = createServerConfig(undefined);
|
||||
mockReadFile({ error: fileNotFoundError });
|
||||
const uuid = await resolveInstanceUuid({ configService, logger });
|
||||
const uuid = await resolveInstanceUuid({ pathConfig, serverConfig, logger });
|
||||
expect(uuid).toEqual('NEW_UUID');
|
||||
expect(writeFile).toHaveBeenCalledWith(
|
||||
join('data-folder', 'uuid'),
|
||||
|
@ -243,7 +236,7 @@ describe('resolveInstanceUuid', () => {
|
|||
it('throws an explicit error for file read errors', async () => {
|
||||
mockReadFile({ error: permissionError });
|
||||
await expect(
|
||||
resolveInstanceUuid({ configService, logger })
|
||||
resolveInstanceUuid({ pathConfig, serverConfig, logger })
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"Unable to read Kibana UUID file, please check the uuid.server configuration value in kibana.yml and ensure Kibana has sufficient permissions to read / write to this file. Error was: EACCES"`
|
||||
);
|
||||
|
@ -251,7 +244,7 @@ describe('resolveInstanceUuid', () => {
|
|||
it('throws an explicit error for file write errors', async () => {
|
||||
mockWriteFile(isDirectoryError);
|
||||
await expect(
|
||||
resolveInstanceUuid({ configService, logger })
|
||||
resolveInstanceUuid({ pathConfig, serverConfig, logger })
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"Unable to write Kibana UUID file, please check the uuid.server configuration value in kibana.yml and ensure Kibana has sufficient permissions to read / write to this file. Error was: EISDIR"`
|
||||
);
|
|
@ -19,11 +19,9 @@
|
|||
|
||||
import uuid from 'uuid';
|
||||
import { join } from 'path';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { readFile, writeFile } from './fs';
|
||||
import { IConfigService } from '../config';
|
||||
import { PathConfigType, config as pathConfigDef } from '../path';
|
||||
import { HttpConfigType, config as httpConfigDef } from '../http';
|
||||
import { PathConfigType } from '../path';
|
||||
import { HttpConfigType } from '../http';
|
||||
import { Logger } from '../logging';
|
||||
|
||||
const FILE_ENCODING = 'utf8';
|
||||
|
@ -35,19 +33,15 @@ const FILE_NAME = 'uuid';
|
|||
export const UUID_7_6_0_BUG = `ce42b997-a913-4d58-be46-bb1937feedd6`;
|
||||
|
||||
export async function resolveInstanceUuid({
|
||||
configService,
|
||||
pathConfig,
|
||||
serverConfig,
|
||||
logger,
|
||||
}: {
|
||||
configService: IConfigService;
|
||||
pathConfig: PathConfigType;
|
||||
serverConfig: HttpConfigType;
|
||||
logger: Logger;
|
||||
}): Promise<string> {
|
||||
const [pathConfig, serverConfig] = await Promise.all([
|
||||
configService.atPath<PathConfigType>(pathConfigDef.path).pipe(take(1)).toPromise(),
|
||||
configService.atPath<HttpConfigType>(httpConfigDef.path).pipe(take(1)).toPromise(),
|
||||
]);
|
||||
|
||||
const uuidFilePath = join(pathConfig.data, FILE_NAME);
|
||||
|
||||
const uuidFromFile = await readUuidFromFile(uuidFilePath, logger);
|
||||
const uuidFromConfig = serverConfig.uuid;
|
||||
|
|
@ -60,7 +60,6 @@ import {
|
|||
SavedObjectsServiceStart,
|
||||
} from './saved_objects';
|
||||
import { CapabilitiesSetup, CapabilitiesStart } from './capabilities';
|
||||
import { UuidServiceSetup } from './uuid';
|
||||
import { MetricsServiceStart } from './metrics';
|
||||
import { StatusServiceSetup } from './status';
|
||||
import { Auditor, AuditTrailSetup, AuditTrailStart } from './audit_trail';
|
||||
|
@ -432,8 +431,6 @@ export interface CoreSetup<TPluginsStart extends object = object, TStart = unkno
|
|||
status: StatusServiceSetup;
|
||||
/** {@link UiSettingsServiceSetup} */
|
||||
uiSettings: UiSettingsServiceSetup;
|
||||
/** {@link UuidServiceSetup} */
|
||||
uuid: UuidServiceSetup;
|
||||
/** {@link StartServicesAccessor} */
|
||||
getStartServices: StartServicesAccessor<TPluginsStart, TStart>;
|
||||
/** {@link AuditTrailSetup} */
|
||||
|
@ -483,7 +480,6 @@ export {
|
|||
PluginsServiceSetup,
|
||||
PluginsServiceStart,
|
||||
PluginOpaqueId,
|
||||
UuidServiceSetup,
|
||||
AuditTrailStart,
|
||||
};
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ import {
|
|||
InternalSavedObjectsServiceStart,
|
||||
} from './saved_objects';
|
||||
import { InternalUiSettingsServiceSetup, InternalUiSettingsServiceStart } from './ui_settings';
|
||||
import { UuidServiceSetup } from './uuid';
|
||||
import { InternalEnvironmentServiceSetup } from './environment';
|
||||
import { InternalMetricsServiceStart } from './metrics';
|
||||
import { InternalRenderingServiceSetup } from './rendering';
|
||||
import { InternalHttpResourcesSetup } from './http_resources';
|
||||
|
@ -49,7 +49,7 @@ export interface InternalCoreSetup {
|
|||
savedObjects: InternalSavedObjectsServiceSetup;
|
||||
status: InternalStatusServiceSetup;
|
||||
uiSettings: InternalUiSettingsServiceSetup;
|
||||
uuid: UuidServiceSetup;
|
||||
environment: InternalEnvironmentServiceSetup;
|
||||
rendering: InternalRenderingServiceSetup;
|
||||
httpResources: InternalHttpResourcesSetup;
|
||||
auditTrail: AuditTrailSetup;
|
||||
|
|
|
@ -45,7 +45,7 @@ import { savedObjectsServiceMock } from '../saved_objects/saved_objects_service.
|
|||
import { capabilitiesServiceMock } from '../capabilities/capabilities_service.mock';
|
||||
import { httpResourcesMock } from '../http_resources/http_resources_service.mock';
|
||||
import { setupMock as renderingServiceMock } from '../rendering/__mocks__/rendering_service';
|
||||
import { uuidServiceMock } from '../uuid/uuid_service.mock';
|
||||
import { environmentServiceMock } from '../environment/environment_service.mock';
|
||||
import { findLegacyPluginSpecs } from './plugins';
|
||||
import { LegacyVars, LegacyServiceSetupDeps, LegacyServiceStartDeps } from './types';
|
||||
import { LegacyService } from './legacy_service';
|
||||
|
@ -66,13 +66,13 @@ let startDeps: LegacyServiceStartDeps;
|
|||
|
||||
const logger = loggingSystemMock.create();
|
||||
let configService: ReturnType<typeof configServiceMock.create>;
|
||||
let uuidSetup: ReturnType<typeof uuidServiceMock.createSetupContract>;
|
||||
let environmentSetup: ReturnType<typeof environmentServiceMock.createSetupContract>;
|
||||
|
||||
beforeEach(() => {
|
||||
coreId = Symbol();
|
||||
env = Env.createDefault(getEnvOptions());
|
||||
configService = configServiceMock.create();
|
||||
uuidSetup = uuidServiceMock.createSetupContract();
|
||||
environmentSetup = environmentServiceMock.createSetupContract();
|
||||
|
||||
findLegacyPluginSpecsMock.mockClear();
|
||||
MockKbnServer.prototype.ready = jest.fn().mockReturnValue(Promise.resolve());
|
||||
|
@ -97,7 +97,7 @@ beforeEach(() => {
|
|||
contracts: new Map([['plugin-id', 'plugin-value']]),
|
||||
},
|
||||
rendering: renderingServiceMock,
|
||||
uuid: uuidSetup,
|
||||
environment: environmentSetup,
|
||||
status: statusServiceMock.createInternalSetupContract(),
|
||||
auditTrail: auditTrailServiceMock.createSetupContract(),
|
||||
logging: loggingServiceMock.createInternalSetupContract(),
|
||||
|
@ -523,7 +523,7 @@ test('Sets the server.uuid property on the legacy configuration', async () => {
|
|||
configService: configService as any,
|
||||
});
|
||||
|
||||
uuidSetup.getInstanceUuid.mockImplementation(() => 'UUID_FROM_SERVICE');
|
||||
environmentSetup.instanceUuid = 'UUID_FROM_SERVICE';
|
||||
|
||||
const configSetMock = jest.fn();
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ export class LegacyService implements CoreService {
|
|||
}
|
||||
|
||||
// propagate the instance uuid to the legacy config, as it was the legacy way to access it.
|
||||
this.legacyRawConfig!.set('server.uuid', setupDeps.core.uuid.getInstanceUuid());
|
||||
this.legacyRawConfig!.set('server.uuid', setupDeps.core.environment.instanceUuid);
|
||||
this.setupDeps = setupDeps;
|
||||
this.legacyInternals = new LegacyInternals(
|
||||
this.legacyPlugins.uiExports,
|
||||
|
@ -327,9 +327,6 @@ export class LegacyService implements CoreService {
|
|||
uiSettings: {
|
||||
register: setupDeps.core.uiSettings.register,
|
||||
},
|
||||
uuid: {
|
||||
getInstanceUuid: setupDeps.core.uuid.getInstanceUuid,
|
||||
},
|
||||
auditTrail: setupDeps.core.auditTrail,
|
||||
getStartServices: () => Promise.resolve([coreStart, startDeps.plugins, {}]),
|
||||
};
|
||||
|
|
|
@ -33,7 +33,7 @@ import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock';
|
|||
import { SharedGlobalConfig } from './plugins';
|
||||
import { capabilitiesServiceMock } from './capabilities/capabilities_service.mock';
|
||||
import { metricsServiceMock } from './metrics/metrics_service.mock';
|
||||
import { uuidServiceMock } from './uuid/uuid_service.mock';
|
||||
import { environmentServiceMock } from './environment/environment_service.mock';
|
||||
import { statusServiceMock } from './status/status_service.mock';
|
||||
import { auditTrailServiceMock } from './audit_trail/audit_trail_service.mock';
|
||||
|
||||
|
@ -94,6 +94,7 @@ function pluginInitializerContextMock<T>(config: T = {} as T) {
|
|||
buildSha: 'buildSha',
|
||||
dist: false,
|
||||
},
|
||||
instanceUuid: 'instance-uuid',
|
||||
},
|
||||
config: pluginInitializerContextConfigMock<T>(config),
|
||||
};
|
||||
|
@ -130,7 +131,6 @@ function createCoreSetupMock({
|
|||
savedObjects: savedObjectsServiceMock.createInternalSetupContract(),
|
||||
status: statusServiceMock.createSetupContract(),
|
||||
uiSettings: uiSettingsMock,
|
||||
uuid: uuidServiceMock.createSetupContract(),
|
||||
auditTrail: auditTrailServiceMock.createSetupContract(),
|
||||
logging: loggingServiceMock.createSetupContract(),
|
||||
getStartServices: jest
|
||||
|
@ -163,7 +163,7 @@ function createInternalCoreSetupMock() {
|
|||
http: httpServiceMock.createInternalSetupContract(),
|
||||
savedObjects: savedObjectsServiceMock.createInternalSetupContract(),
|
||||
status: statusServiceMock.createInternalSetupContract(),
|
||||
uuid: uuidServiceMock.createSetupContract(),
|
||||
environment: environmentServiceMock.createSetupContract(),
|
||||
httpResources: httpResourcesMock.createSetupContract(),
|
||||
rendering: renderingMock.createSetupContract(),
|
||||
uiSettings: uiSettingsServiceMock.createSetupContract(),
|
||||
|
|
|
@ -26,6 +26,7 @@ import { resolve } from 'path';
|
|||
import { ConfigService, Env } from '../../config';
|
||||
import { getEnvOptions } from '../../config/__mocks__/env';
|
||||
import { PluginsConfig, PluginsConfigType, config } from '../plugins_config';
|
||||
import type { InstanceInfo } from '../plugin_context';
|
||||
import { discover } from './plugins_discovery';
|
||||
import { rawConfigServiceMock } from '../../config/raw_config_service.mock';
|
||||
import { CoreContext } from '../../core_context';
|
||||
|
@ -77,6 +78,7 @@ const manifestPath = (...pluginPath: string[]) =>
|
|||
|
||||
describe('plugins discovery system', () => {
|
||||
let logger: ReturnType<typeof loggingSystemMock.create>;
|
||||
let instanceInfo: InstanceInfo;
|
||||
let env: Env;
|
||||
let configService: ConfigService;
|
||||
let pluginConfig: PluginsConfigType;
|
||||
|
@ -87,6 +89,10 @@ describe('plugins discovery system', () => {
|
|||
|
||||
mockPackage.raw = packageMock;
|
||||
|
||||
instanceInfo = {
|
||||
uuid: 'instance-uuid',
|
||||
};
|
||||
|
||||
env = Env.createDefault(
|
||||
getEnvOptions({
|
||||
cliArgs: { envName: 'development' },
|
||||
|
@ -127,7 +133,7 @@ describe('plugins discovery system', () => {
|
|||
});
|
||||
|
||||
it('discovers plugins in the search locations', async () => {
|
||||
const { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext);
|
||||
const { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext, instanceInfo);
|
||||
|
||||
mockFs(
|
||||
{
|
||||
|
@ -146,7 +152,11 @@ describe('plugins discovery system', () => {
|
|||
});
|
||||
|
||||
it('return errors when the manifest is invalid or incompatible', async () => {
|
||||
const { plugin$, error$ } = discover(new PluginsConfig(pluginConfig, env), coreContext);
|
||||
const { plugin$, error$ } = discover(
|
||||
new PluginsConfig(pluginConfig, env),
|
||||
coreContext,
|
||||
instanceInfo
|
||||
);
|
||||
|
||||
mockFs(
|
||||
{
|
||||
|
@ -184,7 +194,11 @@ describe('plugins discovery system', () => {
|
|||
});
|
||||
|
||||
it('return errors when the plugin search path is not accessible', async () => {
|
||||
const { plugin$, error$ } = discover(new PluginsConfig(pluginConfig, env), coreContext);
|
||||
const { plugin$, error$ } = discover(
|
||||
new PluginsConfig(pluginConfig, env),
|
||||
coreContext,
|
||||
instanceInfo
|
||||
);
|
||||
|
||||
mockFs(
|
||||
{
|
||||
|
@ -219,7 +233,11 @@ describe('plugins discovery system', () => {
|
|||
});
|
||||
|
||||
it('return an error when the manifest file is not accessible', async () => {
|
||||
const { plugin$, error$ } = discover(new PluginsConfig(pluginConfig, env), coreContext);
|
||||
const { plugin$, error$ } = discover(
|
||||
new PluginsConfig(pluginConfig, env),
|
||||
coreContext,
|
||||
instanceInfo
|
||||
);
|
||||
|
||||
mockFs(
|
||||
{
|
||||
|
@ -250,7 +268,11 @@ describe('plugins discovery system', () => {
|
|||
});
|
||||
|
||||
it('discovers plugins in nested directories', async () => {
|
||||
const { plugin$, error$ } = discover(new PluginsConfig(pluginConfig, env), coreContext);
|
||||
const { plugin$, error$ } = discover(
|
||||
new PluginsConfig(pluginConfig, env),
|
||||
coreContext,
|
||||
instanceInfo
|
||||
);
|
||||
|
||||
mockFs(
|
||||
{
|
||||
|
@ -287,7 +309,7 @@ describe('plugins discovery system', () => {
|
|||
});
|
||||
|
||||
it('does not discover plugins nested inside another plugin', async () => {
|
||||
const { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext);
|
||||
const { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext, instanceInfo);
|
||||
|
||||
mockFs(
|
||||
{
|
||||
|
@ -306,7 +328,7 @@ describe('plugins discovery system', () => {
|
|||
});
|
||||
|
||||
it('stops scanning when reaching `maxDepth`', async () => {
|
||||
const { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext);
|
||||
const { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext, instanceInfo);
|
||||
|
||||
mockFs(
|
||||
{
|
||||
|
@ -332,7 +354,7 @@ describe('plugins discovery system', () => {
|
|||
});
|
||||
|
||||
it('works with symlinks', async () => {
|
||||
const { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext);
|
||||
const { plugin$ } = discover(new PluginsConfig(pluginConfig, env), coreContext, instanceInfo);
|
||||
|
||||
const pluginFolder = resolve(KIBANA_ROOT, '..', 'ext-plugins');
|
||||
|
||||
|
@ -365,12 +387,16 @@ describe('plugins discovery system', () => {
|
|||
})
|
||||
);
|
||||
|
||||
discover(new PluginsConfig({ ...pluginConfig, paths: [extraPluginTestPath] }, env), {
|
||||
coreId: Symbol(),
|
||||
configService,
|
||||
env,
|
||||
logger,
|
||||
});
|
||||
discover(
|
||||
new PluginsConfig({ ...pluginConfig, paths: [extraPluginTestPath] }, env),
|
||||
{
|
||||
coreId: Symbol(),
|
||||
configService,
|
||||
env,
|
||||
logger,
|
||||
},
|
||||
instanceInfo
|
||||
);
|
||||
|
||||
expect(loggingSystemMock.collect(logger).warn).toEqual([
|
||||
[
|
||||
|
@ -388,12 +414,16 @@ describe('plugins discovery system', () => {
|
|||
})
|
||||
);
|
||||
|
||||
discover(new PluginsConfig({ ...pluginConfig, paths: [extraPluginTestPath] }, env), {
|
||||
coreId: Symbol(),
|
||||
configService,
|
||||
env,
|
||||
logger,
|
||||
});
|
||||
discover(
|
||||
new PluginsConfig({ ...pluginConfig, paths: [extraPluginTestPath] }, env),
|
||||
{
|
||||
coreId: Symbol(),
|
||||
configService,
|
||||
env,
|
||||
logger,
|
||||
},
|
||||
instanceInfo
|
||||
);
|
||||
|
||||
expect(loggingSystemMock.collect(logger).warn).toEqual([]);
|
||||
});
|
||||
|
|
|
@ -24,7 +24,7 @@ import { catchError, filter, map, mergeMap, shareReplay } from 'rxjs/operators';
|
|||
import { CoreContext } from '../../core_context';
|
||||
import { Logger } from '../../logging';
|
||||
import { PluginWrapper } from '../plugin';
|
||||
import { createPluginInitializerContext } from '../plugin_context';
|
||||
import { createPluginInitializerContext, InstanceInfo } from '../plugin_context';
|
||||
import { PluginsConfig } from '../plugins_config';
|
||||
import { PluginDiscoveryError } from './plugin_discovery_error';
|
||||
import { parseManifest } from './plugin_manifest_parser';
|
||||
|
@ -49,7 +49,11 @@ interface PluginSearchPathEntry {
|
|||
* @param coreContext Kibana core values.
|
||||
* @internal
|
||||
*/
|
||||
export function discover(config: PluginsConfig, coreContext: CoreContext) {
|
||||
export function discover(
|
||||
config: PluginsConfig,
|
||||
coreContext: CoreContext,
|
||||
instanceInfo: InstanceInfo
|
||||
) {
|
||||
const log = coreContext.logger.get('plugins-discovery');
|
||||
log.debug('Discovering plugins...');
|
||||
|
||||
|
@ -65,7 +69,7 @@ export function discover(config: PluginsConfig, coreContext: CoreContext) {
|
|||
).pipe(
|
||||
mergeMap((pluginPathOrError) => {
|
||||
return typeof pluginPathOrError === 'string'
|
||||
? createPlugin$(pluginPathOrError, log, coreContext)
|
||||
? createPlugin$(pluginPathOrError, log, coreContext, instanceInfo)
|
||||
: [pluginPathOrError];
|
||||
}),
|
||||
shareReplay()
|
||||
|
@ -180,7 +184,12 @@ function mapSubdirectories(
|
|||
* @param log Plugin discovery logger instance.
|
||||
* @param coreContext Kibana core context.
|
||||
*/
|
||||
function createPlugin$(path: string, log: Logger, coreContext: CoreContext) {
|
||||
function createPlugin$(
|
||||
path: string,
|
||||
log: Logger,
|
||||
coreContext: CoreContext,
|
||||
instanceInfo: InstanceInfo
|
||||
) {
|
||||
return from(parseManifest(path, coreContext.env.packageInfo, log)).pipe(
|
||||
map((manifest) => {
|
||||
log.debug(`Successfully discovered plugin "${manifest.id}" at "${path}"`);
|
||||
|
@ -189,7 +198,12 @@ function createPlugin$(path: string, log: Logger, coreContext: CoreContext) {
|
|||
path,
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
}),
|
||||
catchError((err) => [err])
|
||||
|
|
|
@ -28,12 +28,14 @@ import { BehaviorSubject, from } from 'rxjs';
|
|||
import { rawConfigServiceMock } from '../../config/raw_config_service.mock';
|
||||
import { config } from '../plugins_config';
|
||||
import { loggingSystemMock } from '../../logging/logging_system.mock';
|
||||
import { environmentServiceMock } from '../../environment/environment_service.mock';
|
||||
import { coreMock } from '../../mocks';
|
||||
import { Plugin } from '../types';
|
||||
import { PluginWrapper } from '../plugin';
|
||||
|
||||
describe('PluginsService', () => {
|
||||
const logger = loggingSystemMock.create();
|
||||
const environmentSetup = environmentServiceMock.createSetupContract();
|
||||
let pluginsService: PluginsService;
|
||||
|
||||
const createPlugin = (
|
||||
|
@ -158,7 +160,7 @@ describe('PluginsService', () => {
|
|||
}
|
||||
);
|
||||
|
||||
await pluginsService.discover();
|
||||
await pluginsService.discover({ environment: environmentSetup });
|
||||
|
||||
const setupDeps = coreMock.createInternalSetup();
|
||||
await pluginsService.setup(setupDeps);
|
||||
|
|
|
@ -30,7 +30,11 @@ import { loggingSystemMock } from '../logging/logging_system.mock';
|
|||
|
||||
import { PluginWrapper } from './plugin';
|
||||
import { PluginManifest } from './types';
|
||||
import { createPluginInitializerContext, createPluginSetupContext } from './plugin_context';
|
||||
import {
|
||||
createPluginInitializerContext,
|
||||
createPluginSetupContext,
|
||||
InstanceInfo,
|
||||
} from './plugin_context';
|
||||
|
||||
const mockPluginInitializer = jest.fn();
|
||||
const logger = loggingSystemMock.create();
|
||||
|
@ -67,12 +71,16 @@ configService.atPath.mockReturnValue(new BehaviorSubject({ initialize: true }));
|
|||
let coreId: symbol;
|
||||
let env: Env;
|
||||
let coreContext: CoreContext;
|
||||
let instanceInfo: InstanceInfo;
|
||||
|
||||
const setupDeps = coreMock.createInternalSetup();
|
||||
|
||||
beforeEach(() => {
|
||||
coreId = Symbol('core');
|
||||
env = Env.createDefault(getEnvOptions());
|
||||
instanceInfo = {
|
||||
uuid: 'instance-uuid',
|
||||
};
|
||||
|
||||
coreContext = { coreId, env, logger, configService: configService as any };
|
||||
});
|
||||
|
@ -88,7 +96,12 @@ test('`constructor` correctly initializes plugin instance', () => {
|
|||
path: 'some-plugin-path',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
|
||||
expect(plugin.name).toBe('some-plugin-id');
|
||||
|
@ -105,7 +118,12 @@ test('`setup` fails if `plugin` initializer is not exported', async () => {
|
|||
path: 'plugin-without-initializer-path',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
|
||||
await expect(
|
||||
|
@ -122,7 +140,12 @@ test('`setup` fails if plugin initializer is not a function', async () => {
|
|||
path: 'plugin-with-wrong-initializer-path',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
|
||||
await expect(
|
||||
|
@ -139,7 +162,12 @@ test('`setup` fails if initializer does not return object', async () => {
|
|||
path: 'plugin-with-initializer-path',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
|
||||
mockPluginInitializer.mockReturnValue(null);
|
||||
|
@ -158,7 +186,12 @@ test('`setup` fails if object returned from initializer does not define `setup`
|
|||
path: 'plugin-with-initializer-path',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
|
||||
const mockPluginInstance = { run: jest.fn() };
|
||||
|
@ -174,7 +207,12 @@ test('`setup` fails if object returned from initializer does not define `setup`
|
|||
test('`setup` initializes plugin and calls appropriate lifecycle hook', async () => {
|
||||
const manifest = createPluginManifest();
|
||||
const opaqueId = Symbol();
|
||||
const initializerContext = createPluginInitializerContext(coreContext, opaqueId, manifest);
|
||||
const initializerContext = createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
);
|
||||
const plugin = new PluginWrapper({
|
||||
path: 'plugin-with-initializer-path',
|
||||
manifest,
|
||||
|
@ -203,7 +241,12 @@ test('`start` fails if setup is not called first', async () => {
|
|||
path: 'some-plugin-path',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
|
||||
await expect(plugin.start({} as any, {} as any)).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
|
@ -218,7 +261,12 @@ test('`start` calls plugin.start with context and dependencies', async () => {
|
|||
path: 'plugin-with-initializer-path',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
const context = { any: 'thing' } as any;
|
||||
const deps = { otherDep: 'value' };
|
||||
|
@ -247,7 +295,12 @@ test("`start` resolves `startDependencies` Promise after plugin's start", async
|
|||
path: 'plugin-with-initializer-path',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
const startContext = { any: 'thing' } as any;
|
||||
const pluginDeps = { someDep: 'value' };
|
||||
|
@ -286,7 +339,12 @@ test('`stop` fails if plugin is not set up', async () => {
|
|||
path: 'plugin-with-initializer-path',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
|
||||
const mockPluginInstance = { setup: jest.fn(), stop: jest.fn() };
|
||||
|
@ -305,7 +363,12 @@ test('`stop` does nothing if plugin does not define `stop` function', async () =
|
|||
path: 'plugin-with-initializer-path',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
|
||||
mockPluginInitializer.mockReturnValue({ setup: jest.fn() });
|
||||
|
@ -321,7 +384,12 @@ test('`stop` calls `stop` defined by the plugin instance', async () => {
|
|||
path: 'plugin-with-initializer-path',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
|
||||
const mockPluginInstance = { setup: jest.fn(), stop: jest.fn() };
|
||||
|
@ -351,7 +419,12 @@ describe('#getConfigSchema()', () => {
|
|||
path: 'plugin-with-schema',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
|
||||
expect(plugin.getConfigDescriptor()).toBe(configDescriptor);
|
||||
|
@ -365,7 +438,12 @@ describe('#getConfigSchema()', () => {
|
|||
path: 'plugin-with-no-definition',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
expect(plugin.getConfigDescriptor()).toBe(null);
|
||||
});
|
||||
|
@ -377,7 +455,12 @@ describe('#getConfigSchema()', () => {
|
|||
path: 'plugin-with-no-definition',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
expect(plugin.getConfigDescriptor()).toBe(null);
|
||||
});
|
||||
|
@ -400,7 +483,12 @@ describe('#getConfigSchema()', () => {
|
|||
path: 'plugin-invalid-schema',
|
||||
manifest,
|
||||
opaqueId,
|
||||
initializerContext: createPluginInitializerContext(coreContext, opaqueId, manifest),
|
||||
initializerContext: createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
),
|
||||
});
|
||||
expect(() => plugin.getConfigDescriptor()).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Configuration schema expected to be an instance of Type"`
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import { duration } from 'moment';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { createPluginInitializerContext } from './plugin_context';
|
||||
import { createPluginInitializerContext, InstanceInfo } from './plugin_context';
|
||||
import { CoreContext } from '../core_context';
|
||||
import { Env } from '../config';
|
||||
import { loggingSystemMock } from '../logging/logging_system.mock';
|
||||
|
@ -35,6 +35,7 @@ let coreId: symbol;
|
|||
let env: Env;
|
||||
let coreContext: CoreContext;
|
||||
let server: Server;
|
||||
let instanceInfo: InstanceInfo;
|
||||
|
||||
function createPluginManifest(manifestProps: Partial<PluginManifest> = {}): PluginManifest {
|
||||
return {
|
||||
|
@ -51,9 +52,12 @@ function createPluginManifest(manifestProps: Partial<PluginManifest> = {}): Plug
|
|||
};
|
||||
}
|
||||
|
||||
describe('Plugin Context', () => {
|
||||
describe('createPluginInitializerContext', () => {
|
||||
beforeEach(async () => {
|
||||
coreId = Symbol('core');
|
||||
instanceInfo = {
|
||||
uuid: 'instance-uuid',
|
||||
};
|
||||
env = Env.createDefault(getEnvOptions());
|
||||
const config$ = rawConfigServiceMock.create({ rawConfig: {} });
|
||||
server = new Server(config$, env, logger);
|
||||
|
@ -67,7 +71,8 @@ describe('Plugin Context', () => {
|
|||
const pluginInitializerContext = createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest
|
||||
manifest,
|
||||
instanceInfo
|
||||
);
|
||||
|
||||
expect(pluginInitializerContext.config.legacy.globalConfig$).toBeDefined();
|
||||
|
@ -90,4 +95,19 @@ describe('Plugin Context', () => {
|
|||
path: { data: fromRoot('data') },
|
||||
});
|
||||
});
|
||||
|
||||
it('allow to access the provided instance uuid', () => {
|
||||
const manifest = createPluginManifest();
|
||||
const opaqueId = Symbol();
|
||||
instanceInfo = {
|
||||
uuid: 'kibana-uuid',
|
||||
};
|
||||
const pluginInitializerContext = createPluginInitializerContext(
|
||||
coreContext,
|
||||
opaqueId,
|
||||
manifest,
|
||||
instanceInfo
|
||||
);
|
||||
expect(pluginInitializerContext.env.instanceUuid).toBe('kibana-uuid');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -37,6 +37,10 @@ import {
|
|||
import { pick, deepFreeze } from '../../utils';
|
||||
import { CoreSetup, CoreStart } from '..';
|
||||
|
||||
export interface InstanceInfo {
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a facade for `CoreContext` that will be exposed to the plugin initializer.
|
||||
* This facade should be safe to use across entire plugin lifespan.
|
||||
|
@ -53,7 +57,8 @@ import { CoreSetup, CoreStart } from '..';
|
|||
export function createPluginInitializerContext(
|
||||
coreContext: CoreContext,
|
||||
opaqueId: PluginOpaqueId,
|
||||
pluginManifest: PluginManifest
|
||||
pluginManifest: PluginManifest,
|
||||
instanceInfo: InstanceInfo
|
||||
): PluginInitializerContext {
|
||||
return {
|
||||
opaqueId,
|
||||
|
@ -64,6 +69,7 @@ export function createPluginInitializerContext(
|
|||
env: {
|
||||
mode: coreContext.env.mode,
|
||||
packageInfo: coreContext.env.packageInfo,
|
||||
instanceUuid: instanceInfo.uuid,
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -183,9 +189,6 @@ export function createPluginSetupContext<TPlugin, TPluginDependencies>(
|
|||
uiSettings: {
|
||||
register: deps.uiSettings.register,
|
||||
},
|
||||
uuid: {
|
||||
getInstanceUuid: deps.uuid.getInstanceUuid,
|
||||
},
|
||||
getStartServices: () => plugin.startDependencies,
|
||||
auditTrail: deps.auditTrail,
|
||||
};
|
||||
|
|
|
@ -29,6 +29,7 @@ import { rawConfigServiceMock } from '../config/raw_config_service.mock';
|
|||
import { getEnvOptions } from '../config/__mocks__/env';
|
||||
import { coreMock } from '../mocks';
|
||||
import { loggingSystemMock } from '../logging/logging_system.mock';
|
||||
import { environmentServiceMock } from '../environment/environment_service.mock';
|
||||
import { PluginDiscoveryError } from './discovery';
|
||||
import { PluginWrapper } from './plugin';
|
||||
import { PluginsService } from './plugins_service';
|
||||
|
@ -45,6 +46,7 @@ let configService: ConfigService;
|
|||
let coreId: symbol;
|
||||
let env: Env;
|
||||
let mockPluginSystem: jest.Mocked<PluginsSystem>;
|
||||
let environmentSetup: ReturnType<typeof environmentServiceMock.createSetupContract>;
|
||||
|
||||
const setupDeps = coreMock.createInternalSetup();
|
||||
const logger = loggingSystemMock.create();
|
||||
|
@ -124,6 +126,8 @@ describe('PluginsService', () => {
|
|||
|
||||
[mockPluginSystem] = MockPluginsSystem.mock.instances as any;
|
||||
mockPluginSystem.uiPlugins.mockReturnValue(new Map());
|
||||
|
||||
environmentSetup = environmentServiceMock.createSetupContract();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -137,7 +141,8 @@ describe('PluginsService', () => {
|
|||
plugin$: from([]),
|
||||
});
|
||||
|
||||
await expect(pluginsService.discover()).rejects.toMatchInlineSnapshot(`
|
||||
await expect(pluginsService.discover({ environment: environmentSetup })).rejects
|
||||
.toMatchInlineSnapshot(`
|
||||
[Error: Failed to initialize plugins:
|
||||
Invalid JSON (invalid-manifest, path-1)]
|
||||
`);
|
||||
|
@ -158,7 +163,8 @@ describe('PluginsService', () => {
|
|||
plugin$: from([]),
|
||||
});
|
||||
|
||||
await expect(pluginsService.discover()).rejects.toMatchInlineSnapshot(`
|
||||
await expect(pluginsService.discover({ environment: environmentSetup })).rejects
|
||||
.toMatchInlineSnapshot(`
|
||||
[Error: Failed to initialize plugins:
|
||||
Incompatible version (incompatible-version, path-3)]
|
||||
`);
|
||||
|
@ -192,7 +198,9 @@ describe('PluginsService', () => {
|
|||
]),
|
||||
});
|
||||
|
||||
await expect(pluginsService.discover()).rejects.toMatchInlineSnapshot(
|
||||
await expect(
|
||||
pluginsService.discover({ environment: environmentSetup })
|
||||
).rejects.toMatchInlineSnapshot(
|
||||
`[Error: Plugin with id "conflicting-id" is already registered!]`
|
||||
);
|
||||
|
||||
|
@ -253,7 +261,7 @@ describe('PluginsService', () => {
|
|||
]),
|
||||
});
|
||||
|
||||
await pluginsService.discover();
|
||||
await pluginsService.discover({ environment: environmentSetup });
|
||||
const setup = await pluginsService.setup(setupDeps);
|
||||
|
||||
expect(setup.contracts).toBeInstanceOf(Map);
|
||||
|
@ -300,7 +308,7 @@ describe('PluginsService', () => {
|
|||
plugin$: from([firstPlugin, secondPlugin]),
|
||||
});
|
||||
|
||||
const { pluginTree } = await pluginsService.discover();
|
||||
const { pluginTree } = await pluginsService.discover({ environment: environmentSetup });
|
||||
expect(pluginTree).toBeUndefined();
|
||||
|
||||
expect(mockDiscover).toHaveBeenCalledTimes(1);
|
||||
|
@ -336,7 +344,7 @@ describe('PluginsService', () => {
|
|||
plugin$: from([firstPlugin, secondPlugin, thirdPlugin, lastPlugin, missingDepsPlugin]),
|
||||
});
|
||||
|
||||
const { pluginTree } = await pluginsService.discover();
|
||||
const { pluginTree } = await pluginsService.discover({ environment: environmentSetup });
|
||||
expect(pluginTree).toBeUndefined();
|
||||
|
||||
expect(mockDiscover).toHaveBeenCalledTimes(1);
|
||||
|
@ -369,7 +377,7 @@ describe('PluginsService', () => {
|
|||
plugin$: from([firstPlugin, secondPlugin]),
|
||||
});
|
||||
|
||||
await pluginsService.discover();
|
||||
await pluginsService.discover({ environment: environmentSetup });
|
||||
expect(mockPluginSystem.addPlugin).toHaveBeenCalledTimes(2);
|
||||
expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(firstPlugin);
|
||||
expect(mockPluginSystem.addPlugin).toHaveBeenCalledWith(secondPlugin);
|
||||
|
@ -386,7 +394,8 @@ describe('PluginsService', () => {
|
|||
resolve(process.cwd(), '..', 'kibana-extra'),
|
||||
],
|
||||
},
|
||||
{ coreId, env, logger, configService }
|
||||
{ coreId, env, logger, configService },
|
||||
{ uuid: 'uuid' }
|
||||
);
|
||||
|
||||
const logs = loggingSystemMock.collect(logger);
|
||||
|
@ -417,7 +426,7 @@ describe('PluginsService', () => {
|
|||
}),
|
||||
]),
|
||||
});
|
||||
await pluginsService.discover();
|
||||
await pluginsService.discover({ environment: environmentSetup });
|
||||
expect(configService.setSchema).toBeCalledWith('path', configSchema);
|
||||
});
|
||||
|
||||
|
@ -448,7 +457,7 @@ describe('PluginsService', () => {
|
|||
}),
|
||||
]),
|
||||
});
|
||||
await pluginsService.discover();
|
||||
await pluginsService.discover({ environment: environmentSetup });
|
||||
expect(configService.addDeprecationProvider).toBeCalledWith(
|
||||
'config-path',
|
||||
deprecationProvider
|
||||
|
@ -496,7 +505,7 @@ describe('PluginsService', () => {
|
|||
});
|
||||
mockPluginSystem.uiPlugins.mockReturnValue(new Map([pluginToDiscoveredEntry(plugin)]));
|
||||
|
||||
const { uiPlugins } = await pluginsService.discover();
|
||||
const { uiPlugins } = await pluginsService.discover({ environment: environmentSetup });
|
||||
const uiConfig$ = uiPlugins.browserConfigs.get('plugin-with-expose');
|
||||
expect(uiConfig$).toBeDefined();
|
||||
|
||||
|
@ -532,7 +541,7 @@ describe('PluginsService', () => {
|
|||
});
|
||||
mockPluginSystem.uiPlugins.mockReturnValue(new Map([pluginToDiscoveredEntry(plugin)]));
|
||||
|
||||
const { uiPlugins } = await pluginsService.discover();
|
||||
const { uiPlugins } = await pluginsService.discover({ environment: environmentSetup });
|
||||
expect([...uiPlugins.browserConfigs.entries()]).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
@ -561,7 +570,7 @@ describe('PluginsService', () => {
|
|||
describe('uiPlugins.internal', () => {
|
||||
it('includes disabled plugins', async () => {
|
||||
config$.next({ plugins: { initialize: true }, plugin1: { enabled: false } });
|
||||
const { uiPlugins } = await pluginsService.discover();
|
||||
const { uiPlugins } = await pluginsService.discover({ environment: environmentSetup });
|
||||
expect(uiPlugins.internal).toMatchInlineSnapshot(`
|
||||
Map {
|
||||
"plugin-1" => Object {
|
||||
|
@ -582,7 +591,7 @@ describe('PluginsService', () => {
|
|||
describe('plugin initialization', () => {
|
||||
it('does initialize if plugins.initialize is true', async () => {
|
||||
config$.next({ plugins: { initialize: true } });
|
||||
await pluginsService.discover();
|
||||
await pluginsService.discover({ environment: environmentSetup });
|
||||
const { initialized } = await pluginsService.setup(setupDeps);
|
||||
expect(mockPluginSystem.setupPlugins).toHaveBeenCalled();
|
||||
expect(initialized).toBe(true);
|
||||
|
@ -590,7 +599,7 @@ describe('PluginsService', () => {
|
|||
|
||||
it('does not initialize if plugins.initialize is false', async () => {
|
||||
config$.next({ plugins: { initialize: false } });
|
||||
await pluginsService.discover();
|
||||
await pluginsService.discover({ environment: environmentSetup });
|
||||
const { initialized } = await pluginsService.setup(setupDeps);
|
||||
expect(mockPluginSystem.setupPlugins).not.toHaveBeenCalled();
|
||||
expect(initialized).toBe(false);
|
||||
|
|
|
@ -32,6 +32,7 @@ import { PluginsSystem } from './plugins_system';
|
|||
import { InternalCoreSetup, InternalCoreStart } from '../internal_types';
|
||||
import { IConfigService } from '../config';
|
||||
import { pick } from '../../utils';
|
||||
import { InternalEnvironmentServiceSetup } from '../environment';
|
||||
|
||||
/** @internal */
|
||||
export interface PluginsServiceSetup {
|
||||
|
@ -72,6 +73,11 @@ export type PluginsServiceSetupDeps = InternalCoreSetup;
|
|||
/** @internal */
|
||||
export type PluginsServiceStartDeps = InternalCoreStart;
|
||||
|
||||
/** @internal */
|
||||
export interface PluginsServiceDiscoverDeps {
|
||||
environment: InternalEnvironmentServiceSetup;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export class PluginsService implements CoreService<PluginsServiceSetup, PluginsServiceStart> {
|
||||
private readonly log: Logger;
|
||||
|
@ -90,12 +96,14 @@ export class PluginsService implements CoreService<PluginsServiceSetup, PluginsS
|
|||
.pipe(map((rawConfig) => new PluginsConfig(rawConfig, coreContext.env)));
|
||||
}
|
||||
|
||||
public async discover() {
|
||||
public async discover({ environment }: PluginsServiceDiscoverDeps) {
|
||||
this.log.debug('Discovering plugins');
|
||||
|
||||
const config = await this.config$.pipe(first()).toPromise();
|
||||
|
||||
const { error$, plugin$ } = discover(config, this.coreContext);
|
||||
const { error$, plugin$ } = discover(config, this.coreContext, {
|
||||
uuid: environment.instanceUuid,
|
||||
});
|
||||
await this.handleDiscoveryErrors(error$);
|
||||
await this.handleDiscoveredPlugins(plugin$);
|
||||
|
||||
|
|
|
@ -278,6 +278,7 @@ export interface PluginInitializerContext<ConfigSchema = unknown> {
|
|||
env: {
|
||||
mode: EnvironmentMode;
|
||||
packageInfo: Readonly<PackageInfo>;
|
||||
instanceUuid: string;
|
||||
};
|
||||
logger: LoggerFactory;
|
||||
config: {
|
||||
|
|
|
@ -499,8 +499,6 @@ export interface CoreSetup<TPluginsStart extends object = object, TStart = unkno
|
|||
status: StatusServiceSetup;
|
||||
// (undocumented)
|
||||
uiSettings: UiSettingsServiceSetup;
|
||||
// (undocumented)
|
||||
uuid: UuidServiceSetup;
|
||||
}
|
||||
|
||||
// @public
|
||||
|
@ -1778,6 +1776,7 @@ export interface PluginInitializerContext<ConfigSchema = unknown> {
|
|||
env: {
|
||||
mode: EnvironmentMode;
|
||||
packageInfo: Readonly<PackageInfo>;
|
||||
instanceUuid: string;
|
||||
};
|
||||
// (undocumented)
|
||||
logger: LoggerFactory;
|
||||
|
@ -2883,11 +2882,6 @@ export interface UserProvidedValues<T = any> {
|
|||
userValue?: T;
|
||||
}
|
||||
|
||||
// @public
|
||||
export interface UuidServiceSetup {
|
||||
getInstanceUuid(): string;
|
||||
}
|
||||
|
||||
// @public
|
||||
export const validBodyOutput: readonly ["data", "stream"];
|
||||
|
||||
|
|
|
@ -74,10 +74,10 @@ import { RenderingService, mockRenderingService } from './rendering/__mocks__/re
|
|||
export { mockRenderingService };
|
||||
jest.doMock('./rendering/rendering_service', () => ({ RenderingService }));
|
||||
|
||||
import { uuidServiceMock } from './uuid/uuid_service.mock';
|
||||
export const mockUuidService = uuidServiceMock.create();
|
||||
jest.doMock('./uuid/uuid_service', () => ({
|
||||
UuidService: jest.fn(() => mockUuidService),
|
||||
import { environmentServiceMock } from './environment/environment_service.mock';
|
||||
export const mockEnvironmentService = environmentServiceMock.create();
|
||||
jest.doMock('./environment/environment_service', () => ({
|
||||
EnvironmentService: jest.fn(() => mockEnvironmentService),
|
||||
}));
|
||||
|
||||
import { metricsServiceMock } from './metrics/metrics_service.mock';
|
||||
|
|
|
@ -31,7 +31,7 @@ import { PluginsService, config as pluginsConfig } from './plugins';
|
|||
import { SavedObjectsService } from '../server/saved_objects';
|
||||
import { MetricsService, opsConfig } from './metrics';
|
||||
import { CapabilitiesService } from './capabilities';
|
||||
import { UuidService } from './uuid';
|
||||
import { EnvironmentService } from './environment';
|
||||
import { StatusService } from './status/status_service';
|
||||
|
||||
import { config as cspConfig } from './csp';
|
||||
|
@ -64,7 +64,7 @@ export class Server {
|
|||
private readonly plugins: PluginsService;
|
||||
private readonly savedObjects: SavedObjectsService;
|
||||
private readonly uiSettings: UiSettingsService;
|
||||
private readonly uuid: UuidService;
|
||||
private readonly environment: EnvironmentService;
|
||||
private readonly metrics: MetricsService;
|
||||
private readonly httpResources: HttpResourcesService;
|
||||
private readonly status: StatusService;
|
||||
|
@ -95,7 +95,7 @@ export class Server {
|
|||
this.savedObjects = new SavedObjectsService(core);
|
||||
this.uiSettings = new UiSettingsService(core);
|
||||
this.capabilities = new CapabilitiesService(core);
|
||||
this.uuid = new UuidService(core);
|
||||
this.environment = new EnvironmentService(core);
|
||||
this.metrics = new MetricsService(core);
|
||||
this.status = new StatusService(core);
|
||||
this.coreApp = new CoreApp(core);
|
||||
|
@ -107,8 +107,12 @@ export class Server {
|
|||
public async setup() {
|
||||
this.log.debug('setting up server');
|
||||
|
||||
const environmentSetup = await this.environment.setup();
|
||||
|
||||
// Discover any plugins before continuing. This allows other systems to utilize the plugin dependency graph.
|
||||
const { pluginTree, uiPlugins } = await this.plugins.discover();
|
||||
const { pluginTree, uiPlugins } = await this.plugins.discover({
|
||||
environment: environmentSetup,
|
||||
});
|
||||
const legacyPlugins = await this.legacy.discoverPlugins();
|
||||
|
||||
// Immediately terminate in case of invalid configuration
|
||||
|
@ -124,7 +128,6 @@ export class Server {
|
|||
});
|
||||
|
||||
const auditTrailSetup = this.auditTrail.setup();
|
||||
const uuidSetup = await this.uuid.setup();
|
||||
|
||||
const httpSetup = await this.http.setup({
|
||||
context: contextServiceSetup,
|
||||
|
@ -174,11 +177,11 @@ export class Server {
|
|||
capabilities: capabilitiesSetup,
|
||||
context: contextServiceSetup,
|
||||
elasticsearch: elasticsearchServiceSetup,
|
||||
environment: environmentSetup,
|
||||
http: httpSetup,
|
||||
savedObjects: savedObjectsSetup,
|
||||
status: statusSetup,
|
||||
uiSettings: uiSettingsSetup,
|
||||
uuid: uuidSetup,
|
||||
rendering: renderingSetup,
|
||||
httpResources: httpResourcesSetup,
|
||||
auditTrail: auditTrailSetup,
|
||||
|
|
|
@ -17,13 +17,8 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import Fs from 'fs';
|
||||
import { promisify } from 'util';
|
||||
|
||||
import { getUiSettingDefaults } from './server/ui_setting_defaults';
|
||||
|
||||
const mkdirAsync = promisify(Fs.mkdir);
|
||||
|
||||
export default function (kibana) {
|
||||
return new kibana.Plugin({
|
||||
id: 'kibana',
|
||||
|
@ -40,17 +35,5 @@ export default function (kibana) {
|
|||
uiExports: {
|
||||
uiSettingDefaults: getUiSettingDefaults(),
|
||||
},
|
||||
|
||||
preInit: async function (server) {
|
||||
try {
|
||||
// Create the data directory (recursively, if the a parent dir doesn't exist).
|
||||
// If it already exists, does nothing.
|
||||
await mkdirAsync(server.config().get('path.data'), { recursive: true });
|
||||
} catch (err) {
|
||||
server.log(['error', 'init'], err);
|
||||
// Stop the server startup with a fatal error
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ export class Plugin implements CorePlugin<IEventLogService, IEventLogClientServi
|
|||
config,
|
||||
esContext: this.esContext,
|
||||
systemLogger: this.systemLogger,
|
||||
kibanaUUID: core.uuid.getInstanceUuid(),
|
||||
kibanaUUID: this.context.env.instanceUuid,
|
||||
savedObjectProviderRegistry: this.savedObjectProviderRegistry,
|
||||
});
|
||||
|
||||
|
|
|
@ -65,9 +65,6 @@ describe('Monitoring plugin', () => {
|
|||
serverBasePath: '',
|
||||
},
|
||||
},
|
||||
uuid: {
|
||||
getInstanceUuid: jest.fn(),
|
||||
},
|
||||
elasticsearch: {
|
||||
legacy: {
|
||||
client: {},
|
||||
|
|
|
@ -92,7 +92,7 @@ export class Plugin {
|
|||
const router = core.http.createRouter();
|
||||
this.legacyShimDependencies = {
|
||||
router,
|
||||
instanceUuid: core.uuid.getInstanceUuid(),
|
||||
instanceUuid: this.initializerContext.env.instanceUuid,
|
||||
esDataClient: core.elasticsearch.legacy.client,
|
||||
kibanaStatsCollector: plugins.usageCollection?.getCollectorByType(
|
||||
KIBANA_STATS_TYPE_MONITORING
|
||||
|
@ -159,7 +159,7 @@ export class Plugin {
|
|||
config,
|
||||
log: kibanaMonitoringLog,
|
||||
kibanaStats: {
|
||||
uuid: core.uuid.getInstanceUuid(),
|
||||
uuid: this.initializerContext.env.instanceUuid,
|
||||
name: serverInfo.name,
|
||||
index: get(legacyConfig, 'kibana.index'),
|
||||
host: serverInfo.hostname,
|
||||
|
|
|
@ -75,7 +75,7 @@ export const buildConfig = async (
|
|||
host: serverInfo.hostname,
|
||||
name: serverInfo.name,
|
||||
port: serverInfo.port,
|
||||
uuid: core.uuid.getInstanceUuid(),
|
||||
uuid: initContext.env.instanceUuid,
|
||||
protocol: serverInfo.protocol,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -42,7 +42,7 @@ export class TaskManagerPlugin
|
|||
.toPromise();
|
||||
|
||||
setupSavedObjects(core.savedObjects, this.config);
|
||||
this.taskManagerId = core.uuid.getInstanceUuid();
|
||||
this.taskManagerId = this.initContext.env.instanceUuid;
|
||||
|
||||
return {
|
||||
addMiddleware: (middleware: Middleware) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue