Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into migrate/url-short…
Browse files Browse the repository at this point in the history
…ener
  • Loading branch information
flash1293 committed Dec 3, 2019
2 parents cf2b6a9 + a3a6b84 commit 9df3cc4
Show file tree
Hide file tree
Showing 81 changed files with 954 additions and 811 deletions.
6 changes: 0 additions & 6 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,6 @@ module.exports = {
'jsx-a11y/click-events-have-key-events': 'off',
},
},
{
files: ['x-pack/legacy/plugins/graph/**/*.{js,ts,tsx}'],
rules: {
'react-hooks/exhaustive-deps': 'off',
},
},
{
files: ['x-pack/legacy/plugins/index_management/**/*.{js,ts,tsx}'],
rules: {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@
"lodash": "npm:@elastic/[email protected]",
"lodash.clonedeep": "^4.5.0",
"lru-cache": "4.1.5",
"markdown-it": "^8.4.1",
"markdown-it": "^10.0.0",
"mini-css-extract-plugin": "0.8.0",
"minimatch": "^3.0.4",
"moment": "^2.24.0",
Expand Down
57 changes: 0 additions & 57 deletions src/cli/serve/integration_tests/invalid_config.test.js

This file was deleted.

70 changes: 70 additions & 0 deletions src/cli/serve/integration_tests/invalid_config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* 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 { spawnSync } from 'child_process';
import { resolve } from 'path';

const ROOT_DIR = resolve(__dirname, '../../../../');
const INVALID_CONFIG_PATH = resolve(__dirname, '__fixtures__/invalid_config.yml');

interface LogEntry {
message: string;
tags: string[];
type: string;
}

describe('cli invalid config support', function() {
it(
'exits with statusCode 64 and logs a single line when config is invalid',
function() {
// Unused keys only throw once LegacyService starts, so disable migrations so that Core
// will finish the start lifecycle without a running Elasticsearch instance.
const { error, status, stdout } = spawnSync(
process.execPath,
['src/cli', '--config', INVALID_CONFIG_PATH, '--migrations.skip=true'],
{
cwd: ROOT_DIR,
}
);

const [fatalLogLine] = stdout
.toString('utf8')
.split('\n')
.filter(Boolean)
.map(line => JSON.parse(line) as LogEntry)
.filter(line => line.tags.includes('fatal'))
.map(obj => ({
...obj,
pid: '## PID ##',
'@timestamp': '## @timestamp ##',
error: '## Error with stack trace ##',
}));

expect(error).toBe(undefined);
expect(status).toBe(64);
expect(fatalLogLine.message).toContain(
'Error: Unknown configuration key(s): "unknown.key", "other.unknown.key", "other.third", "some.flat.key", ' +
'"some.array". Check for spelling errors and ensure that expected plugins are installed.'
);
expect(fatalLogLine.tags).toEqual(['fatal', 'root']);
expect(fatalLogLine.type).toEqual('log');
},
20 * 1000
);
});
5 changes: 4 additions & 1 deletion src/core/server/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { isMaster } from 'cluster';
import { CliArgs, Env, RawConfigService } from './config';
import { LegacyObjectToConfigAdapter } from './legacy';
import { Root } from './root';
import { CriticalError } from './errors';

interface KibanaFeatures {
// Indicates whether we can run Kibana in a so called cluster mode in which
Expand Down Expand Up @@ -112,7 +113,9 @@ function onRootShutdown(reason?: any) {
// mirror such fatal errors in standard output with `console.error`.
// eslint-disable-next-line
console.error(`\n${chalk.white.bgRed(' FATAL ')} ${reason}\n`);

process.exit(reason instanceof CriticalError ? reason.processExitCode : 1);
}

process.exit(reason === undefined ? 0 : (reason as any).processExitCode || 1);
process.exit(0);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@
* under the License.
*/

export default function ({ loadTestFile }) {
describe('search', () => {
loadTestFile(require.resolve('./count'));
});
export class CriticalError extends Error {
constructor(
message: string,
public code: string,
public processExitCode: number,
public cause?: Error
) {
super(message);
Object.setPrototypeOf(this, CriticalError.prototype);
}
}
75 changes: 75 additions & 0 deletions src/core/server/legacy/config/ensure_valid_configuration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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 { ensureValidConfiguration } from './ensure_valid_configuration';
import { getUnusedConfigKeys } from './get_unused_config_keys';
import { configServiceMock } from '../../config/config_service.mock';

jest.mock('./get_unused_config_keys');

describe('ensureValidConfiguration', () => {
let configService: ReturnType<typeof configServiceMock.create>;

beforeEach(() => {
jest.clearAllMocks();
configService = configServiceMock.create();
configService.getUsedPaths.mockReturnValue(Promise.resolve(['core', 'elastic']));

(getUnusedConfigKeys as any).mockImplementation(() => []);
});

it('calls getUnusedConfigKeys with correct parameters', async () => {
await ensureValidConfiguration(
configService as any,
{
settings: 'settings',
pluginSpecs: 'pluginSpecs',
disabledPluginSpecs: 'disabledPluginSpecs',
pluginExtendedConfig: 'pluginExtendedConfig',
uiExports: 'uiExports',
} as any
);
expect(getUnusedConfigKeys).toHaveBeenCalledTimes(1);
expect(getUnusedConfigKeys).toHaveBeenCalledWith({
coreHandledConfigPaths: ['core', 'elastic'],
pluginSpecs: 'pluginSpecs',
disabledPluginSpecs: 'disabledPluginSpecs',
inputSettings: 'settings',
legacyConfig: 'pluginExtendedConfig',
});
});

it('returns normally when there is no unused keys', async () => {
await expect(
ensureValidConfiguration(configService as any, {} as any)
).resolves.toBeUndefined();

expect(getUnusedConfigKeys).toHaveBeenCalledTimes(1);
});

it('throws when there are some unused keys', async () => {
(getUnusedConfigKeys as any).mockImplementation(() => ['some.key', 'some.other.key']);

await expect(
ensureValidConfiguration(configService as any, {} as any)
).rejects.toMatchInlineSnapshot(
`[Error: Unknown configuration key(s): "some.key", "some.other.key". Check for spelling errors and ensure that expected plugins are installed.]`
);
});
});
50 changes: 50 additions & 0 deletions src/core/server/legacy/config/ensure_valid_configuration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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 { getUnusedConfigKeys } from './get_unused_config_keys';
import { ConfigService } from '../../config';
import { LegacyServiceDiscoverPlugins } from '../legacy_service';
import { CriticalError } from '../../errors';

export async function ensureValidConfiguration(
configService: ConfigService,
{ pluginSpecs, disabledPluginSpecs, pluginExtendedConfig, settings }: LegacyServiceDiscoverPlugins
) {
const unusedConfigKeys = await getUnusedConfigKeys({
coreHandledConfigPaths: await configService.getUsedPaths(),
pluginSpecs,
disabledPluginSpecs,
inputSettings: settings,
legacyConfig: pluginExtendedConfig,
});

if (unusedConfigKeys.length > 0) {
const message = `Unknown configuration key(s): ${unusedConfigKeys
.map(key => `"${key}"`)
.join(', ')}. Check for spelling errors and ensure that expected plugins are installed.`;
throw new InvalidConfigurationError(message);
}
}

class InvalidConfigurationError extends CriticalError {
constructor(message: string) {
super(message, 'InvalidConfig', 64);
Object.setPrototypeOf(this, InvalidConfigurationError.prototype);
}
}
Loading

0 comments on commit 9df3cc4

Please sign in to comment.