mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
* [Code] code backend NP migration * Move code plugin config to NP config service * Move code plugin logger to NP logger service * minor type error * remove joi config * addressing comments * fix unit tests * Migrate to xpack feature service for NP * minor comments * fix code mocha test scripts * fix type * fix i18nrc.json for code
This commit is contained in:
parent
c3edee5415
commit
9ec4e89828
25 changed files with 354 additions and 204 deletions
|
@ -7,7 +7,7 @@
|
|||
"xpack.apm": "legacy/plugins/apm",
|
||||
"xpack.beatsManagement": "legacy/plugins/beats_management",
|
||||
"xpack.canvas": "legacy/plugins/canvas",
|
||||
"xpack.code": "legacy/plugins/code",
|
||||
"xpack.code": ["legacy/plugins/code", "plugins/code"],
|
||||
"xpack.crossClusterReplication": "legacy/plugins/cross_cluster_replication",
|
||||
"xpack.dashboardMode": "legacy/plugins/dashboard_mode",
|
||||
"xpack.features": "plugins/features",
|
||||
|
|
|
@ -7,14 +7,11 @@
|
|||
import { RequestQuery, ResponseToolkit, RouteOptions, ServerRoute } from 'hapi';
|
||||
import JoiNamespace from 'joi';
|
||||
import { Legacy } from 'kibana';
|
||||
import moment from 'moment';
|
||||
import { resolve } from 'path';
|
||||
import { CoreSetup } from 'src/core/server';
|
||||
|
||||
import { CoreSetup, PluginInitializerContext } from 'src/core/server';
|
||||
import { APP_TITLE } from './common/constants';
|
||||
import { codePlugin } from './server';
|
||||
import { DEFAULT_WATERMARK_LOW_PERCENTAGE } from './server/disk_watermark';
|
||||
import { LanguageServers, LanguageServersDeveloping } from './server/lsp/language_servers';
|
||||
|
||||
export type RequestFacade = Legacy.Request;
|
||||
export type RequestQueryFacade = RequestQuery;
|
||||
|
@ -25,7 +22,7 @@ export type ServerRouteFacade = ServerRoute;
|
|||
|
||||
export const code = (kibana: any) =>
|
||||
new kibana.Plugin({
|
||||
require: ['kibana', 'elasticsearch', 'xpack_main'],
|
||||
require: ['kibana', 'elasticsearch'],
|
||||
id: 'code',
|
||||
configPrefix: 'xpack.code',
|
||||
publicDir: resolve(__dirname, 'public'),
|
||||
|
@ -46,98 +43,29 @@ export const code = (kibana: any) =>
|
|||
hacks: ['plugins/code/hacks/toggle_app_link_in_nav'],
|
||||
},
|
||||
config(Joi: typeof JoiNamespace) {
|
||||
const langSwitches: any = {};
|
||||
LanguageServers.forEach(lang => {
|
||||
langSwitches[lang.name] = Joi.object({
|
||||
enabled: Joi.boolean().default(true),
|
||||
});
|
||||
});
|
||||
LanguageServersDeveloping.forEach(lang => {
|
||||
langSwitches[lang.name] = Joi.object({
|
||||
enabled: Joi.boolean().default(false),
|
||||
});
|
||||
});
|
||||
return Joi.object({
|
||||
// Still keep this config item here for the injectDefaultVars
|
||||
// in line 40 here.
|
||||
ui: Joi.object({
|
||||
enabled: Joi.boolean().default(true),
|
||||
}).default(),
|
||||
enabled: Joi.boolean().default(true),
|
||||
queueIndex: Joi.string().default('.code_internal-worker-queue'),
|
||||
// 1 hour by default.
|
||||
queueTimeoutMs: Joi.number().default(moment.duration(1, 'hour').asMilliseconds()),
|
||||
// The frequency which update scheduler executes. 1 minute by default.
|
||||
updateFrequencyMs: Joi.number().default(moment.duration(1, 'minute').asMilliseconds()),
|
||||
// The frequency which index scheduler executes. 1 day by default.
|
||||
indexFrequencyMs: Joi.number().default(moment.duration(1, 'day').asMilliseconds()),
|
||||
// The frequency which each repo tries to update. 5 minutes by default.
|
||||
updateRepoFrequencyMs: Joi.number().default(moment.duration(5, 'minute').asMilliseconds()),
|
||||
// The frequency which each repo tries to index. 1 day by default.
|
||||
indexRepoFrequencyMs: Joi.number().default(moment.duration(1, 'day').asMilliseconds()),
|
||||
// whether we want to show more logs
|
||||
verbose: Joi.boolean().default(false),
|
||||
lsp: Joi.object({
|
||||
...langSwitches,
|
||||
// timeout of a request
|
||||
requestTimeoutMs: Joi.number().default(moment.duration(10, 'second').asMilliseconds()),
|
||||
// if we want the language server run in seperately
|
||||
detach: Joi.boolean().default(false),
|
||||
// enable oom_score_adj on linux
|
||||
oomScoreAdj: Joi.boolean().default(true),
|
||||
}).default(),
|
||||
repos: Joi.array().default([]),
|
||||
security: Joi.object({
|
||||
enableMavenImport: Joi.boolean().default(true),
|
||||
enableGradleImport: Joi.boolean().default(false),
|
||||
installGoDependency: Joi.boolean().default(false),
|
||||
installNodeDependency: Joi.boolean().default(true),
|
||||
gitHostWhitelist: Joi.array()
|
||||
.items(Joi.string())
|
||||
.default([
|
||||
'github.com',
|
||||
'gitlab.com',
|
||||
'bitbucket.org',
|
||||
'gitbox.apache.org',
|
||||
'eclipse.org',
|
||||
]),
|
||||
gitProtocolWhitelist: Joi.array()
|
||||
.items(Joi.string())
|
||||
.default(['https', 'git', 'ssh']),
|
||||
enableGitCertCheck: Joi.boolean().default(true),
|
||||
}).default(),
|
||||
disk: Joi.object({
|
||||
thresholdEnabled: Joi.bool().default(true),
|
||||
watermarkLow: Joi.string().default(`${DEFAULT_WATERMARK_LOW_PERCENTAGE}%`),
|
||||
}).default(),
|
||||
maxWorkspace: Joi.number().default(5), // max workspace folder for each language server
|
||||
enableGlobalReference: Joi.boolean().default(false), // Global reference as optional feature for now
|
||||
enableCommitIndexing: Joi.boolean().default(false),
|
||||
codeNodeUrl: Joi.string(),
|
||||
clustering: Joi.object({
|
||||
enabled: Joi.bool().default(false),
|
||||
codeNodes: Joi.array()
|
||||
.items(
|
||||
Joi.object({
|
||||
id: Joi.string(),
|
||||
address: Joi.string(),
|
||||
})
|
||||
)
|
||||
.default([]),
|
||||
}).default(),
|
||||
}).default();
|
||||
},
|
||||
init(server: ServerFacade, options: any) {
|
||||
if (!options.ui.enabled) {
|
||||
async init(server: ServerFacade) {
|
||||
// @ts-ignore
|
||||
const initializerContext = server.newPlatform.setup.plugins.code;
|
||||
if (!initializerContext.legacy.config.ui.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const initializerContext = {} as PluginInitializerContext;
|
||||
const coreSetup = ({
|
||||
http: { server },
|
||||
} as any) as CoreSetup;
|
||||
|
||||
// Set up with the new platform plugin lifecycle API.
|
||||
const plugin = codePlugin(initializerContext);
|
||||
plugin.setup(coreSetup, options);
|
||||
plugin.setup(coreSetup);
|
||||
|
||||
// @ts-ignore
|
||||
const kbnServer = this.kbnServer;
|
||||
|
|
|
@ -3,8 +3,5 @@
|
|||
"version": "kibana",
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": [
|
||||
"elasticsearch",
|
||||
"xpack_main"
|
||||
]
|
||||
"requiredPlugins": ["elasticsearch"]
|
||||
}
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
require('./_helpers').runXPackScript('mocha', ['legacy/plugins/code/server/__tests__/*.{ts,tsx}']);
|
||||
require('./_helpers').runKibanaScript('mocha', ['x-pack/legacy/plugins/code/server/__tests__/*.{ts,tsx}']);
|
||||
|
|
|
@ -4,12 +4,11 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Server } from 'hapi';
|
||||
import { ServiceHandlerFor } from '../service_definition';
|
||||
import { WorkspaceHandler } from '../../lsp/workspace_handler';
|
||||
import { RepoConfig } from '../../../model';
|
||||
import { WorkspaceCommand } from '../../lsp/workspace_command';
|
||||
import { Logger } from '../../log';
|
||||
import { LoggerFactory as CodeLoggerFactory } from '../../utils/log_factory';
|
||||
|
||||
export const WorkspaceDefinition = {
|
||||
initCmd: {
|
||||
|
@ -19,7 +18,7 @@ export const WorkspaceDefinition = {
|
|||
};
|
||||
|
||||
export const getWorkspaceHandler = (
|
||||
server: Server,
|
||||
loggerFactory: CodeLoggerFactory,
|
||||
workspaceHandler: WorkspaceHandler
|
||||
): ServiceHandlerFor<typeof WorkspaceDefinition> => ({
|
||||
async initCmd({ repoUri, revision, repoConfig, force }) {
|
||||
|
@ -28,9 +27,13 @@ export const getWorkspaceHandler = (
|
|||
repoUri,
|
||||
revision
|
||||
);
|
||||
const log = new Logger(server, ['workspace', repoUri]);
|
||||
|
||||
const workspaceCmd = new WorkspaceCommand(repoConfig, workspaceDir, workspaceRevision, log);
|
||||
const workspaceCmd = new WorkspaceCommand(
|
||||
repoConfig,
|
||||
workspaceDir,
|
||||
workspaceRevision,
|
||||
loggerFactory.getLogger(['workspace', repoUri])
|
||||
);
|
||||
await workspaceCmd.runInit(force);
|
||||
return {};
|
||||
} catch (e) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Request, Server } from 'hapi';
|
||||
import { createTestHapiServer } from '../test_utils';
|
||||
import { LocalHandlerAdapter } from './local_handler_adapter';
|
||||
|
@ -13,9 +14,10 @@ import { DEFAULT_SERVICE_OPTION } from './service_handler_adapter';
|
|||
import { NonCodeNodeAdapter } from './multinode/non_code_node_adapter';
|
||||
import { CodeServices } from './code_services';
|
||||
import { Logger } from '../log';
|
||||
import { ConsoleLoggerFactory } from '../utils/console_logger_factory';
|
||||
|
||||
const log: Logger = new ConsoleLoggerFactory().getLogger(['test']);
|
||||
let hapiServer: Server = createTestHapiServer();
|
||||
const log = new Logger(hapiServer);
|
||||
|
||||
let server: CodeServerRouter = new CodeServerRouter(hapiServer);
|
||||
beforeEach(async () => {
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { PluginInitializerContext } from 'src/core/server';
|
||||
|
||||
import * as constants from '../common/constants';
|
||||
import { CodePlugin } from './plugin';
|
||||
import { PluginSetupContract } from '../../../../plugins/code/server/index';
|
||||
|
||||
export const codePlugin = (initializerContext: PluginInitializerContext) =>
|
||||
export const codePlugin = (initializerContext: PluginSetupContract) =>
|
||||
new CodePlugin(initializerContext);
|
||||
|
||||
export { constants };
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
*/
|
||||
|
||||
import { Server } from 'hapi';
|
||||
|
||||
import { LoggerFactory } from 'src/core/server';
|
||||
import { ServerOptions } from './server_options';
|
||||
import { CodeServices } from './distributed/code_services';
|
||||
import { EsClient } from './lib/esqueue';
|
||||
import { RepositoryConfigController } from './repository_config_controller';
|
||||
import { GitOperations } from './git_operations';
|
||||
import { Logger } from './log';
|
||||
import {
|
||||
getGitServiceHandler,
|
||||
getLspServiceHandler,
|
||||
|
@ -29,7 +30,7 @@ import { ServerLoggerFactory } from './utils/server_logger_factory';
|
|||
|
||||
export function initLocalService(
|
||||
server: Server,
|
||||
log: Logger,
|
||||
loggerFactory: LoggerFactory,
|
||||
serverOptions: ServerOptions,
|
||||
codeServices: CodeServices,
|
||||
esClient: EsClient,
|
||||
|
@ -43,6 +44,7 @@ export function initLocalService(
|
|||
GitServiceDefinitionOption
|
||||
);
|
||||
|
||||
const serverLoggerFactory = new ServerLoggerFactory(loggerFactory, serverOptions.verbose);
|
||||
const installManager = new InstallManager(server, serverOptions);
|
||||
const lspService = new LspService(
|
||||
'127.0.0.1',
|
||||
|
@ -50,11 +52,11 @@ export function initLocalService(
|
|||
gitOps,
|
||||
esClient,
|
||||
installManager,
|
||||
new ServerLoggerFactory(server),
|
||||
serverLoggerFactory,
|
||||
repoConfigController
|
||||
);
|
||||
server.events.on('stop', async () => {
|
||||
log.debug('shutdown lsp process');
|
||||
loggerFactory.get().debug('shutdown lsp process');
|
||||
await lspService.shutdown();
|
||||
await gitOps.cleanAllRepo();
|
||||
});
|
||||
|
@ -65,7 +67,7 @@ export function initLocalService(
|
|||
);
|
||||
codeServices.registerHandler(
|
||||
WorkspaceDefinition,
|
||||
getWorkspaceHandler(server, lspService.workspaceHandler)
|
||||
getWorkspaceHandler(serverLoggerFactory, lspService.workspaceHandler)
|
||||
);
|
||||
codeServices.registerHandler(SetupDefinition, setupServiceHandler);
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Server } from 'hapi';
|
||||
import { EsClient, Esqueue } from './lib/esqueue';
|
||||
import { Logger } from './log';
|
||||
import { ServerOptions } from './server_options';
|
||||
|
||||
export function initQueue(server: Server, log: Logger, esClient: EsClient) {
|
||||
const queueIndex: string = server.config().get('xpack.code.queueIndex');
|
||||
const queueTimeoutMs: number = server.config().get('xpack.code.queueTimeoutMs');
|
||||
export function initQueue(serverOptions: ServerOptions, log: Logger, esClient: EsClient) {
|
||||
const queueIndex: string = serverOptions.queueIndex;
|
||||
const queueTimeoutMs: number = serverOptions.queueTimeoutMs;
|
||||
const queue = new Esqueue(queueIndex, {
|
||||
client: esClient,
|
||||
timeout: queueTimeoutMs,
|
||||
|
|
|
@ -7,19 +7,22 @@
|
|||
import { inspect } from 'util';
|
||||
import { Logger as VsLogger } from 'vscode-jsonrpc';
|
||||
|
||||
import { ServerFacade } from '..';
|
||||
import { Logger as KibanaLogger, LoggerFactory } from 'src/core/server';
|
||||
|
||||
export class Logger implements VsLogger {
|
||||
private readonly verbose: boolean = false;
|
||||
constructor(private server: ServerFacade, private baseTags: string[] = ['code']) {
|
||||
if (server) {
|
||||
this.verbose = this.server.config().get('xpack.code.verbose');
|
||||
}
|
||||
private logger: KibanaLogger;
|
||||
|
||||
constructor(
|
||||
private readonly loggerFactory: LoggerFactory,
|
||||
private readonly verbose: boolean = false,
|
||||
private readonly baseTags: string[] = []
|
||||
) {
|
||||
this.logger = this.loggerFactory.get(...this.baseTags);
|
||||
}
|
||||
|
||||
// Return a new logger with new tags
|
||||
public addTags(tags: string[]): Logger {
|
||||
return new Logger(this.server, this.baseTags.concat(tags));
|
||||
return new Logger(this.loggerFactory, this.verbose, this.baseTags.concat(tags));
|
||||
}
|
||||
|
||||
public info(msg: string | any) {
|
||||
|
@ -28,7 +31,7 @@ export class Logger implements VsLogger {
|
|||
colors: process.stdout.isTTY,
|
||||
});
|
||||
}
|
||||
this.server.log([...this.baseTags, 'info'], msg);
|
||||
this.logger.info(msg);
|
||||
}
|
||||
|
||||
public error(msg: string | any) {
|
||||
|
@ -42,11 +45,11 @@ export class Logger implements VsLogger {
|
|||
});
|
||||
}
|
||||
|
||||
this.server.log([...this.baseTags, 'error'], msg);
|
||||
this.logger.error(msg);
|
||||
}
|
||||
|
||||
public log(message: string): void {
|
||||
this.info(message);
|
||||
public log(msg: string): void {
|
||||
this.logger.info(msg);
|
||||
}
|
||||
|
||||
public debug(msg: string | any) {
|
||||
|
@ -56,9 +59,9 @@ export class Logger implements VsLogger {
|
|||
});
|
||||
}
|
||||
if (this.verbose) {
|
||||
this.server.log([...this.baseTags, 'info'], msg);
|
||||
this.logger.info(msg);
|
||||
} else {
|
||||
this.server.log([...this.baseTags, 'debug'], msg);
|
||||
this.logger.debug(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +76,7 @@ export class Logger implements VsLogger {
|
|||
});
|
||||
}
|
||||
|
||||
this.server.log([...this.baseTags, 'warning'], msg);
|
||||
this.logger.warn(msg);
|
||||
}
|
||||
|
||||
// Log subprocess stdout
|
||||
|
@ -84,9 +87,9 @@ export class Logger implements VsLogger {
|
|||
});
|
||||
}
|
||||
if (this.verbose) {
|
||||
this.server.log([...this.baseTags, 'info', 'stdout'], msg);
|
||||
this.logger.info(msg);
|
||||
} else {
|
||||
this.server.log([...this.baseTags, 'debug', 'stdout'], msg);
|
||||
this.logger.debug(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,9 +101,9 @@ export class Logger implements VsLogger {
|
|||
});
|
||||
}
|
||||
if (this.verbose) {
|
||||
this.server.log([...this.baseTags, 'error', 'stderr'], msg);
|
||||
this.logger.error(msg);
|
||||
} else {
|
||||
this.server.log([...this.baseTags, 'debug', 'stderr'], msg);
|
||||
this.logger.debug(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,21 @@ const workspaceDir = path.join(baseDir, 'workspace');
|
|||
// @ts-ignore
|
||||
const options: ServerOptions = sinon.createStubInstance(ServerOptions);
|
||||
// @ts-ignore
|
||||
options.lsp = { detach: false };
|
||||
options.lsp = {
|
||||
TypeScript: {
|
||||
enabled: true,
|
||||
},
|
||||
Java: {
|
||||
enabled: true,
|
||||
},
|
||||
Go: {
|
||||
enabled: true,
|
||||
},
|
||||
Ctags: {
|
||||
enabled: true,
|
||||
},
|
||||
detach: false,
|
||||
};
|
||||
// @ts-ignore
|
||||
options.maxWorkspace = 2;
|
||||
const server = createTestHapiServer();
|
||||
|
|
|
@ -57,7 +57,7 @@ export class LanguageServerController implements ILanguageServerHandler {
|
|||
readonly repoConfigController: RepositoryConfigController
|
||||
) {
|
||||
this.log = loggerFactory.getLogger([]);
|
||||
this.languageServers = enabledLanguageServers(installManager.server).map(def => ({
|
||||
this.languageServers = enabledLanguageServers(options).map(def => ({
|
||||
definition: def,
|
||||
builtinWorkspaceFolders: def.builtinWorkspaceFolders,
|
||||
languages: def.languages,
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ServerFacade } from '../..';
|
||||
import { InstallationType } from '../../common/installation';
|
||||
import { CTAGS_SUPPORT_LANGS, LanguageServer } from '../../common/language_server';
|
||||
import { ServerOptions } from '../server_options';
|
||||
import { CtagsLauncher } from './ctags_launcher';
|
||||
import { GoServerLauncher } from './go_launcher';
|
||||
import { JavaLauncher } from './java_launcher';
|
||||
|
@ -72,12 +72,13 @@ export const CTAGS: LanguageServerDefinition = {
|
|||
export const LanguageServers: LanguageServerDefinition[] = [TYPESCRIPT, JAVA, GO, CTAGS];
|
||||
export const LanguageServersDeveloping: LanguageServerDefinition[] = [];
|
||||
|
||||
export function enabledLanguageServers(server: ServerFacade) {
|
||||
const devMode: boolean = server.config().get('env.dev');
|
||||
export function enabledLanguageServers(serverOptions: ServerOptions) {
|
||||
const devMode: boolean = serverOptions.devMode;
|
||||
|
||||
function isEnabled(lang: LanguageServerDefinition, defaultEnabled: boolean) {
|
||||
const name = lang.name;
|
||||
const enabled = server.config().get(`xpack.code.lsp.${name}.enabled`);
|
||||
// @ts-ignore
|
||||
const enabled = serverOptions.lsp[name] && serverOptions.lsp[name].enabled;
|
||||
return enabled === undefined ? defaultEnabled : enabled;
|
||||
}
|
||||
const results = LanguageServers.filter(lang => isEnabled(lang, true));
|
||||
|
|
|
@ -4,12 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import crypto from 'crypto';
|
||||
import * as _ from 'lodash';
|
||||
import { CoreSetup, PluginInitializerContext } from 'src/core/server';
|
||||
import { CoreSetup } from 'src/core/server';
|
||||
|
||||
import { XPackMainPlugin } from '../../xpack_main/xpack_main';
|
||||
import { GitOperations } from './git_operations';
|
||||
import { RepositoryIndexInitializerFactory, tryMigrateIndices } from './indexer';
|
||||
import { Esqueue } from './lib/esqueue';
|
||||
|
@ -56,6 +54,7 @@ import { initWorkers } from './init_workers';
|
|||
import { ClusterNodeAdapter } from './distributed/cluster/cluster_node_adapter';
|
||||
import { NodeRepositoriesService } from './distributed/cluster/node_repositories_service';
|
||||
import { initCodeUsageCollector } from './usage_collector';
|
||||
import { PluginSetupContract } from '../../../../plugins/code/server/index';
|
||||
|
||||
export class CodePlugin {
|
||||
private isCodeNode = false;
|
||||
|
@ -70,50 +69,15 @@ export class CodePlugin {
|
|||
private codeServices: CodeServices | null = null;
|
||||
private nodeService: NodeRepositoriesService | null = null;
|
||||
|
||||
constructor(initializerContext: PluginInitializerContext) {
|
||||
constructor(private readonly initContext: PluginSetupContract) {
|
||||
this.log = {} as Logger;
|
||||
this.serverOptions = {} as ServerOptions;
|
||||
}
|
||||
|
||||
// TODO: options is not a valid param for the setup() api
|
||||
// of the new platform. Will need to pass through the configs
|
||||
// correctly in the new platform.
|
||||
public setup(core: CoreSetup, options: any) {
|
||||
public setup(core: CoreSetup) {
|
||||
const { server } = core.http as any;
|
||||
|
||||
this.log = new Logger(server);
|
||||
this.serverOptions = new ServerOptions(options, server.config());
|
||||
|
||||
const xpackMainPlugin: XPackMainPlugin = server.plugins.xpack_main;
|
||||
xpackMainPlugin.registerFeature({
|
||||
id: 'code',
|
||||
name: i18n.translate('xpack.code.featureRegistry.codeFeatureName', {
|
||||
defaultMessage: 'Code',
|
||||
}),
|
||||
icon: 'codeApp',
|
||||
navLinkId: 'code',
|
||||
app: ['code', 'kibana'],
|
||||
catalogue: [], // TODO add catalogue here
|
||||
privileges: {
|
||||
all: {
|
||||
excludeFromBasePrivileges: true,
|
||||
api: ['code_user', 'code_admin'],
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: ['config'],
|
||||
},
|
||||
ui: ['show', 'user', 'admin'],
|
||||
},
|
||||
read: {
|
||||
api: ['code_user'],
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: ['config'],
|
||||
},
|
||||
ui: ['show', 'user'],
|
||||
},
|
||||
},
|
||||
});
|
||||
this.serverOptions = new ServerOptions(this.initContext.legacy.config, server.config());
|
||||
this.log = new Logger(this.initContext.legacy.logger, this.serverOptions.verbose);
|
||||
}
|
||||
|
||||
// TODO: CodeStart will not have the register route api.
|
||||
|
@ -165,11 +129,11 @@ export class CodePlugin {
|
|||
|
||||
const codeServices = new CodeServices(clusterNodeAdapter);
|
||||
|
||||
this.queue = initQueue(server, this.log, esClient);
|
||||
this.queue = initQueue(this.serverOptions, this.log, esClient);
|
||||
|
||||
const { gitOps, lspService } = initLocalService(
|
||||
server,
|
||||
this.log,
|
||||
this.initContext.legacy.logger,
|
||||
this.serverOptions,
|
||||
codeServices,
|
||||
esClient,
|
||||
|
@ -213,11 +177,11 @@ export class CodePlugin {
|
|||
this.log
|
||||
);
|
||||
|
||||
this.queue = initQueue(server, this.log, esClient);
|
||||
this.queue = initQueue(this.serverOptions, this.log, esClient);
|
||||
|
||||
const { gitOps, lspService } = initLocalService(
|
||||
server,
|
||||
this.log,
|
||||
this.initContext.legacy.logger,
|
||||
this.serverOptions,
|
||||
codeServices,
|
||||
esClient,
|
||||
|
@ -293,7 +257,8 @@ export class CodePlugin {
|
|||
codeServices,
|
||||
repoIndexInitializerFactory,
|
||||
repoConfigController,
|
||||
this.serverOptions
|
||||
this.serverOptions,
|
||||
this.log
|
||||
);
|
||||
repositorySearchRoute(codeServerRouter, this.log);
|
||||
if (this.serverOptions.enableCommitIndexing) {
|
||||
|
@ -304,8 +269,8 @@ export class CodePlugin {
|
|||
fileRoute(codeServerRouter, codeServices);
|
||||
workspaceRoute(codeServerRouter, this.serverOptions, codeServices);
|
||||
symbolByQnameRoute(codeServerRouter, this.log);
|
||||
installRoute(codeServerRouter, codeServices);
|
||||
lspRoute(codeServerRouter, codeServices, this.serverOptions);
|
||||
installRoute(codeServerRouter, codeServices, this.serverOptions);
|
||||
lspRoute(codeServerRouter, codeServices, this.serverOptions, this.log);
|
||||
setupRoute(codeServerRouter, codeServices);
|
||||
statusRoute(codeServerRouter, codeServices);
|
||||
}
|
||||
|
@ -342,7 +307,7 @@ export class CodePlugin {
|
|||
|
||||
private initDevMode(server: any) {
|
||||
// @ts-ignore
|
||||
const devMode: boolean = server.config().get('env.dev');
|
||||
const devMode: boolean = this.serverOptions.devMode;
|
||||
server.injectUiAppVars('code', () => ({
|
||||
enableLangserversDeveloping: devMode,
|
||||
}));
|
||||
|
|
|
@ -12,8 +12,13 @@ import { CodeServerRouter } from '../security';
|
|||
import { CodeServices } from '../distributed/code_services';
|
||||
import { LspServiceDefinition } from '../distributed/apis';
|
||||
import { Endpoint } from '../distributed/resource_locator';
|
||||
import { ServerOptions } from '../server_options';
|
||||
|
||||
export function installRoute(router: CodeServerRouter, codeServices: CodeServices) {
|
||||
export function installRoute(
|
||||
router: CodeServerRouter,
|
||||
codeServices: CodeServices,
|
||||
options: ServerOptions
|
||||
) {
|
||||
const lspService = codeServices.serviceFor(LspServiceDefinition);
|
||||
const kibanaVersion = router.server.config().get('pkg.version') as string;
|
||||
const status = async (endpoint: Endpoint, def: LanguageServerDefinition) => ({
|
||||
|
@ -32,9 +37,7 @@ export function installRoute(router: CodeServerRouter, codeServices: CodeService
|
|||
path: '/api/code/install',
|
||||
async handler(req: RequestFacade) {
|
||||
const endpoint = await codeServices.locate(req, '');
|
||||
return await Promise.all(
|
||||
enabledLanguageServers(router.server).map(def => status(endpoint, def))
|
||||
);
|
||||
return await Promise.all(enabledLanguageServers(options).map(def => status(endpoint, def)));
|
||||
},
|
||||
method: 'GET',
|
||||
});
|
||||
|
@ -43,7 +46,7 @@ export function installRoute(router: CodeServerRouter, codeServices: CodeService
|
|||
path: '/api/code/install/{name}',
|
||||
async handler(req: RequestFacade) {
|
||||
const name = req.params.name;
|
||||
const def = enabledLanguageServers(router.server).find(d => d.name === name);
|
||||
const def = enabledLanguageServers(options).find(d => d.name === name);
|
||||
const endpoint = await codeServices.locate(req, '');
|
||||
if (def) {
|
||||
return await status(endpoint, def);
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
import Boom from 'boom';
|
||||
import { ResponseError } from 'vscode-jsonrpc';
|
||||
import { ResponseMessage } from 'vscode-jsonrpc/lib/messages';
|
||||
|
||||
import { SymbolLocator } from '@elastic/lsp-extension';
|
||||
|
||||
import {
|
||||
LanguageServerStartFailed,
|
||||
ServerNotInitialized,
|
||||
|
@ -32,9 +32,9 @@ const LANG_SERVER_ERROR = 'language server error';
|
|||
export function lspRoute(
|
||||
server: CodeServerRouter,
|
||||
codeServices: CodeServices,
|
||||
serverOptions: ServerOptions
|
||||
serverOptions: ServerOptions,
|
||||
log: Logger
|
||||
) {
|
||||
const log = new Logger(server.server);
|
||||
const lspService = codeServices.serviceFor(LspServiceDefinition);
|
||||
const gitService = codeServices.serviceFor(GitServiceDefinition);
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ export function repositoryRoute(
|
|||
codeServices: CodeServices,
|
||||
repoIndexInitializerFactory: RepositoryIndexInitializerFactory,
|
||||
repoConfigController: RepositoryConfigController,
|
||||
options: ServerOptions
|
||||
options: ServerOptions,
|
||||
log: Logger
|
||||
) {
|
||||
const repositoryService = codeServices.serviceFor(RepositoryServiceDefinition);
|
||||
// Clone a git repository
|
||||
|
@ -35,7 +36,6 @@ export function repositoryRoute(
|
|||
method: 'POST',
|
||||
async handler(req: RequestFacade, h: ResponseToolkitFacade) {
|
||||
const repoUrl: string = (req.payload as any).url;
|
||||
const log = new Logger(req.server);
|
||||
|
||||
// Reject the request if the url is an invalid git url.
|
||||
try {
|
||||
|
@ -104,7 +104,6 @@ export function repositoryRoute(
|
|||
method: 'DELETE',
|
||||
async handler(req: RequestFacade, h: ResponseToolkitFacade) {
|
||||
const repoUri: string = req.params.uri as string;
|
||||
const log = new Logger(req.server);
|
||||
const repoObjectClient = new RepositoryObjectClient(new EsClientWithRequest(req));
|
||||
try {
|
||||
// Check if the repository already exists. If not, an error will be thrown.
|
||||
|
@ -146,7 +145,6 @@ export function repositoryRoute(
|
|||
method: 'GET',
|
||||
async handler(req: RequestFacade) {
|
||||
const repoUri = req.params.uri as string;
|
||||
const log = new Logger(req.server);
|
||||
try {
|
||||
const repoObjectClient = new RepositoryObjectClient(new EsClientWithRequest(req));
|
||||
return await repoObjectClient.getRepository(repoUri);
|
||||
|
@ -164,7 +162,6 @@ export function repositoryRoute(
|
|||
method: 'GET',
|
||||
async handler(req: RequestFacade) {
|
||||
const repoUri = req.params.uri as string;
|
||||
const log = new Logger(req.server);
|
||||
try {
|
||||
const repoObjectClient = new RepositoryObjectClient(new EsClientWithRequest(req));
|
||||
let gitStatus = null;
|
||||
|
@ -206,7 +203,6 @@ export function repositoryRoute(
|
|||
path: '/api/code/repos',
|
||||
method: 'GET',
|
||||
async handler(req: RequestFacade) {
|
||||
const log = new Logger(req.server);
|
||||
try {
|
||||
const repoObjectClient = new RepositoryObjectClient(new EsClientWithRequest(req));
|
||||
return await repoObjectClient.getAllRepositories();
|
||||
|
@ -228,7 +224,6 @@ export function repositoryRoute(
|
|||
requireAdmin: true,
|
||||
async handler(req: RequestFacade) {
|
||||
const repoUri = req.params.uri as string;
|
||||
const log = new Logger(req.server);
|
||||
const reindex: boolean = (req.payload as any).reindex;
|
||||
try {
|
||||
const repoObjectClient = new RepositoryObjectClient(new EsClientWithRequest(req));
|
||||
|
@ -259,7 +254,6 @@ export function repositoryRoute(
|
|||
async handler(req: RequestFacade) {
|
||||
const config: RepositoryConfig = req.payload as RepositoryConfig;
|
||||
const repoUri: RepositoryUri = config.uri;
|
||||
const log = new Logger(req.server);
|
||||
const repoObjectClient = new RepositoryObjectClient(new EsClientWithRequest(req));
|
||||
|
||||
try {
|
||||
|
|
|
@ -30,6 +30,8 @@ export interface DiskOptions {
|
|||
}
|
||||
|
||||
export class ServerOptions {
|
||||
public readonly devMode: boolean = this.config.get('env.dev');
|
||||
|
||||
public readonly workspacePath = resolve(this.config.get('path.data'), 'code/workspace');
|
||||
|
||||
public readonly repoPath = resolve(this.config.get('path.data'), 'code/repos');
|
||||
|
@ -76,8 +78,13 @@ export class ServerOptions {
|
|||
|
||||
public readonly clusterEnabled: boolean = this.options.clustering.enabled;
|
||||
|
||||
public readonly verbose: boolean = this.options.verbose;
|
||||
|
||||
public readonly codeNodes: CodeNode[] = this.options.clustering.codeNodes;
|
||||
|
||||
public readonly queueIndex: string = this.options.queueIndex;
|
||||
public readonly queueTimeoutMs: number = this.options.queueTimeoutMs;
|
||||
|
||||
constructor(private options: any, private config: any) {}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,8 +9,11 @@ import { Logger } from '../log';
|
|||
|
||||
export class ConsoleLogger extends Logger {
|
||||
constructor() {
|
||||
// @ts-ignore
|
||||
super(undefined);
|
||||
super({
|
||||
get: (...contextParts: string[]) => {
|
||||
return console as any;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public info(msg: string | any) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import { ConsoleLogger } from './console_logger';
|
|||
import { LoggerFactory } from './log_factory';
|
||||
|
||||
export class ConsoleLoggerFactory implements LoggerFactory {
|
||||
public getLogger(tags: string[]): Logger {
|
||||
public getLogger(tags: string[] = []): Logger {
|
||||
return new ConsoleLogger();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { LoggerFactory } from 'src/core/server';
|
||||
import { Logger } from '../log';
|
||||
import { LoggerFactory } from './log_factory';
|
||||
import { ServerFacade } from '../..';
|
||||
import { LoggerFactory as CodeLoggerFactory } from './log_factory';
|
||||
|
||||
export class ServerLoggerFactory implements LoggerFactory {
|
||||
constructor(private readonly server: ServerFacade) {}
|
||||
export class ServerLoggerFactory implements CodeLoggerFactory {
|
||||
constructor(private readonly loggerFactory: LoggerFactory, private readonly verbose: boolean) {}
|
||||
|
||||
public getLogger(tags: string[]): Logger {
|
||||
return new Logger(this.server, tags);
|
||||
public getLogger(tags: string[] = []): Logger {
|
||||
return new Logger(this.loggerFactory, this.verbose, tags);
|
||||
}
|
||||
}
|
||||
|
|
9
x-pack/plugins/code/kibana.json
Normal file
9
x-pack/plugins/code/kibana.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"id": "code",
|
||||
"version": "8.0.0",
|
||||
"kibanaVersion": "kibana",
|
||||
"configPath": ["x-pack", "code"],
|
||||
"server": true,
|
||||
"ui": false,
|
||||
"requiredPlugins": ["features"]
|
||||
}
|
112
x-pack/plugins/code/server/config.ts
Normal file
112
x-pack/plugins/code/server/config.ts
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import moment from 'moment';
|
||||
|
||||
// TODO: update these legacy imports to new ones.
|
||||
import {
|
||||
LanguageServers,
|
||||
LanguageServersDeveloping,
|
||||
} from '../../../legacy/plugins/code/server/lsp/language_servers';
|
||||
import { DEFAULT_WATERMARK_LOW_PERCENTAGE } from '../../../legacy/plugins/code/server/disk_watermark';
|
||||
|
||||
const createCodeConfigSchema = () => {
|
||||
const langSwitches: any = {};
|
||||
LanguageServers.forEach(lang => {
|
||||
langSwitches[lang.name] = schema.object({
|
||||
enabled: schema.boolean({ defaultValue: true }),
|
||||
});
|
||||
});
|
||||
LanguageServersDeveloping.forEach(lang => {
|
||||
langSwitches[lang.name] = schema.object({
|
||||
enabled: schema.boolean({ defaultValue: false }),
|
||||
});
|
||||
});
|
||||
|
||||
return schema.object({
|
||||
ui: schema.object({
|
||||
enabled: schema.boolean({ defaultValue: true }),
|
||||
}),
|
||||
enabled: schema.boolean({ defaultValue: true }),
|
||||
queueIndex: schema.string({ defaultValue: '.code_internal-worker-queue' }),
|
||||
// 1 hour by default.
|
||||
queueTimeoutMs: schema.number({
|
||||
defaultValue: moment.duration(1, 'hour').asMilliseconds(),
|
||||
}),
|
||||
// The frequency which update scheduler executes. 1 minute by default.
|
||||
updateFrequencyMs: schema.number({
|
||||
defaultValue: moment.duration(1, 'minute').asMilliseconds(),
|
||||
}),
|
||||
// The frequency which index scheduler executes. 1 day by default.
|
||||
indexFrequencyMs: schema.number({
|
||||
defaultValue: moment.duration(1, 'day').asMilliseconds(),
|
||||
}),
|
||||
// The frequency which each repo tries to update. 5 minutes by default.
|
||||
updateRepoFrequencyMs: schema.number({
|
||||
defaultValue: moment.duration(5, 'minute').asMilliseconds(),
|
||||
}),
|
||||
// The frequency which each repo tries to index. 1 day by default.
|
||||
indexRepoFrequencyMs: schema.number({
|
||||
defaultValue: moment.duration(1, 'day').asMilliseconds(),
|
||||
}),
|
||||
// whether we want to show more logs
|
||||
verbose: schema.boolean({ defaultValue: false }),
|
||||
lsp: schema.object({
|
||||
...langSwitches,
|
||||
// timeout of a request
|
||||
requestTimeoutMs: schema.number({
|
||||
defaultValue: moment.duration(10, 'second').asMilliseconds(),
|
||||
}),
|
||||
// if we want the language server run in seperately
|
||||
detach: schema.boolean({ defaultValue: false }),
|
||||
// enable oom_score_adj on linux
|
||||
oomScoreAdj: schema.boolean({ defaultValue: true }),
|
||||
}),
|
||||
repos: schema.arrayOf(schema.string(), { defaultValue: [] }),
|
||||
security: schema.object({
|
||||
enableMavenImport: schema.boolean({ defaultValue: true }),
|
||||
enableGradleImport: schema.boolean({ defaultValue: false }),
|
||||
installGoDependency: schema.boolean({ defaultValue: false }),
|
||||
installNodeDependency: schema.boolean({ defaultValue: true }),
|
||||
gitHostWhitelist: schema.arrayOf(schema.string(), {
|
||||
defaultValue: [
|
||||
'github.com',
|
||||
'gitlab.com',
|
||||
'bitbucket.org',
|
||||
'gitbox.apache.org',
|
||||
'eclipse.org',
|
||||
],
|
||||
}),
|
||||
gitProtocolWhitelist: schema.arrayOf(schema.string(), {
|
||||
defaultValue: ['https', 'git', 'ssh'],
|
||||
}),
|
||||
enableGitCertCheck: schema.boolean({ defaultValue: true }),
|
||||
}),
|
||||
disk: schema.object({
|
||||
thresholdEnabled: schema.boolean({ defaultValue: true }),
|
||||
watermarkLow: schema.string({ defaultValue: `${DEFAULT_WATERMARK_LOW_PERCENTAGE}%` }),
|
||||
}),
|
||||
maxWorkspace: schema.number({ defaultValue: 5 }), // max workspace folder for each language server
|
||||
enableGlobalReference: schema.boolean({ defaultValue: false }), // Global reference as optional feature for now
|
||||
enableCommitIndexing: schema.boolean({ defaultValue: false }),
|
||||
codeNodeUrl: schema.maybe(schema.string()),
|
||||
clustering: schema.object({
|
||||
enabled: schema.boolean({ defaultValue: false }),
|
||||
codeNodes: schema.arrayOf(
|
||||
schema.object({
|
||||
id: schema.string(),
|
||||
address: schema.string(),
|
||||
}),
|
||||
{
|
||||
defaultValue: [],
|
||||
}
|
||||
),
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
export const CodeConfigSchema = createCodeConfigSchema();
|
15
x-pack/plugins/code/server/index.ts
Normal file
15
x-pack/plugins/code/server/index.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { PluginInitializerContext } from 'src/core/server';
|
||||
import { CodeConfigSchema } from './config';
|
||||
import { CodePlugin } from './plugin';
|
||||
|
||||
export { PluginSetupContract } from './plugin';
|
||||
|
||||
export const config = { schema: CodeConfigSchema };
|
||||
export const plugin = (initializerContext: PluginInitializerContext) =>
|
||||
new CodePlugin(initializerContext);
|
92
x-pack/plugins/code/server/plugin.ts
Normal file
92
x-pack/plugins/code/server/plugin.ts
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { TypeOf } from '@kbn/config-schema';
|
||||
import {
|
||||
CoreSetup,
|
||||
LoggerFactory,
|
||||
PluginInitializerContext,
|
||||
RecursiveReadonly,
|
||||
} from 'src/core/server';
|
||||
import { deepFreeze } from '../../../../src/core/utils';
|
||||
import { PluginSetupContract as FeaturesSetupContract } from '../../features/server';
|
||||
import { CodeConfigSchema } from './config';
|
||||
|
||||
/**
|
||||
* Describes public Code plugin contract returned at the `setup` stage.
|
||||
*/
|
||||
export interface PluginSetupContract {
|
||||
/** @deprecated */
|
||||
legacy: {
|
||||
config: TypeOf<typeof CodeConfigSchema>;
|
||||
logger: LoggerFactory;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents Code Plugin instance that will be managed by the Kibana plugin system.
|
||||
*/
|
||||
export class CodePlugin {
|
||||
constructor(private readonly initializerContext: PluginInitializerContext) {}
|
||||
|
||||
public async setup(
|
||||
coreSetup: CoreSetup,
|
||||
{ features }: { features: FeaturesSetupContract }
|
||||
): Promise<RecursiveReadonly<PluginSetupContract>> {
|
||||
const config = await this.initializerContext.config
|
||||
.create<TypeOf<typeof CodeConfigSchema>>()
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
features.registerFeature({
|
||||
id: 'code',
|
||||
name: i18n.translate('xpack.code.featureRegistry.codeFeatureName', {
|
||||
defaultMessage: 'Code',
|
||||
}),
|
||||
icon: 'codeApp',
|
||||
navLinkId: 'code',
|
||||
app: ['code', 'kibana'],
|
||||
catalogue: [], // TODO add catalogue here
|
||||
privileges: {
|
||||
all: {
|
||||
excludeFromBasePrivileges: true,
|
||||
api: ['code_user', 'code_admin'],
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: ['config'],
|
||||
},
|
||||
ui: ['show', 'user', 'admin'],
|
||||
},
|
||||
read: {
|
||||
api: ['code_user'],
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: ['config'],
|
||||
},
|
||||
ui: ['show', 'user'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return deepFreeze({
|
||||
/** @deprecated */
|
||||
legacy: {
|
||||
config,
|
||||
logger: this.initializerContext.logger,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public start() {
|
||||
this.initializerContext.logger.get().debug('Starting Code plugin');
|
||||
}
|
||||
|
||||
public stop() {
|
||||
this.initializerContext.logger.get().debug('Stopping Code plugin');
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue