Skip to content

Commit

Permalink
[cli/serve] simplify deprecated config check by doing it after merge()
Browse files Browse the repository at this point in the history
  • Loading branch information
spalger committed Apr 13, 2016
1 parent 23e4902 commit 5a100b3
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 135 deletions.
97 changes: 32 additions & 65 deletions src/cli/serve/__tests__/deprecated_config.js
Original file line number Diff line number Diff line change
@@ -1,81 +1,48 @@
import expect from 'expect.js';
import { rewriteDeprecatedConfig } from '../deprecated_config';
import { set } from 'lodash';
import { checkForDeprecatedConfig } from '../deprecated_config';
import sinon from 'auto-release-sinon';

describe('cli/serve/deprecated_config', function () {
it('returns a clone of the input', function () {
const file = {};
const output = rewriteDeprecatedConfig(file);
expect(output).to.not.be(file);
it('passes original config through', function () {
const config = {};
set(config, 'server.xsrf.token', 'xxtokenxx');
const output = checkForDeprecatedConfig(config);
expect(output).to.be(config);
expect(output.server).to.be(config.server);
expect(output.server.xsrf).to.be(config.server.xsrf);
expect(output.server.xsrf.token).to.be(config.server.xsrf.token);
});

describe('legacy config values', function () {
it('rewrites legacy config values with literal path replacement', function () {
const file = { port: 4000, host: 'kibana.com' };
const output = rewriteDeprecatedConfig(file);
expect(output).to.not.be(file);
expect(output).to.eql({
'server.port': 4000,
'server.host': 'kibana.com',
});
});

it('logs warnings when legacy config properties are encountered', function () {
const log = sinon.stub();
rewriteDeprecatedConfig({ port: 5555 }, log);
sinon.assert.calledOnce(log);
expect(log.firstCall.args[0]).to.match(/port.+deprecated.+server\.port/);
});
it('logs warnings about deprecated config values', function () {
const log = sinon.stub();
const config = {};
set(config, 'server.xsrf.token', 'xxtokenxx');
checkForDeprecatedConfig(config, log);
sinon.assert.calledOnce(log);
expect(log.firstCall.args[0]).to.match(/server\.xsrf\.token.+deprecated/);
});

describe('deprecated config values', function () {
it('logs warnings about deprecated config values', function () {
describe('does not support compound.keys', function () {
it('ignores fully compound keys', function () {
const log = sinon.stub();
rewriteDeprecatedConfig({ 'server.xsrf.token': 'xxtokenxx' }, log);
sinon.assert.calledOnce(log);
expect(log.firstCall.args[0]).to.match(/server\.xsrf\.token.+deprecated/);
const config = { 'server.xsrf.token': 'xxtokenxx' };
checkForDeprecatedConfig(config, log);
sinon.assert.notCalled(log);
});

it('passes deprecated values through', function () {
const prop = 'server.xsrf.token';
const file = { [prop]: 'xxtokenxx' };
const output = rewriteDeprecatedConfig(file);
expect(output).to.not.be(file);
expect(output).to.have.property(prop, file[prop]);
it('ignores partially compound keys', function () {
const log = sinon.stub();
const config = { server: { 'xsrf.token': 'xxtokenxx' } };
checkForDeprecatedConfig(config, log);
sinon.assert.notCalled(log);
});

context('defined in a mixture of path keys and objects', function () {
it('detects nested propertie', function () {
const log = sinon.stub();
rewriteDeprecatedConfig({
server: {
xsrf: {
token: 'x'
}
}
}, log);
sinon.assert.calledOnce(log);
});

it('detects compound properties inside an object', function () {
const log = sinon.stub();
rewriteDeprecatedConfig({
server: {
'xsrf.token': 'x'
}
}, log);
sinon.assert.calledOnce(log);
});

it('detects a property under a compound property', function () {
const log = sinon.stub();
rewriteDeprecatedConfig({
'server.xsrf': {
token: 'x'
}
}, log);
sinon.assert.calledOnce(log);
});
it('ignores partially compound keys', function () {
const log = sinon.stub();
const config = { 'server.xsrf': { token: 'xxtokenxx' } };
checkForDeprecatedConfig(config, log);
sinon.assert.notCalled(log);
});
});
});
28 changes: 28 additions & 0 deletions src/cli/serve/__tests__/legacy_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import expect from 'expect.js';
import { rewriteLegacyConfig } from '../legacy_config';
import sinon from 'auto-release-sinon';

describe('cli/serve/legacy_config', function () {
it('returns a clone of the input', function () {
const file = {};
const output = rewriteLegacyConfig(file);
expect(output).to.not.be(file);
});

it('rewrites legacy config values with literal path replacement', function () {
const file = { port: 4000, host: 'kibana.com' };
const output = rewriteLegacyConfig(file);
expect(output).to.not.be(file);
expect(output).to.eql({
'server.port': 4000,
'server.host': 'kibana.com',
});
});

it('logs warnings when legacy config properties are encountered', function () {
const log = sinon.stub();
rewriteLegacyConfig({ port: 5555 }, log);
sinon.assert.calledOnce(log);
expect(log.firstCall.args[0]).to.match(/port.+deprecated.+server\.port/);
});
});
79 changes: 15 additions & 64 deletions src/cli/serve/deprecated_config.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,16 @@
import { forOwn, has, noop, transform } from 'lodash';

const legacySettings = {
// server
port: 'server.port',
host: 'server.host',
pid_file: 'pid.file',
ssl_cert_file: 'server.ssl.cert',
ssl_key_file: 'server.ssl.key',

// logging
log_file: 'logging.dest',

// kibana
kibana_index: 'kibana.index',
default_app_id: 'kibana.defaultAppId',

// es
ca: 'elasticsearch.ssl.ca',
elasticsearch_preserve_host: 'elasticsearch.preserveHost',
elasticsearch_url: 'elasticsearch.url',
kibana_elasticsearch_client_crt: 'elasticsearch.ssl.cert',
kibana_elasticsearch_client_key: 'elasticsearch.ssl.key',
kibana_elasticsearch_password: 'elasticsearch.password',
kibana_elasticsearch_username: 'elasticsearch.username',
ping_timeout: 'elasticsearch.pingTimeout',
request_timeout: 'elasticsearch.requestTimeout',
shard_timeout: 'elasticsearch.shardTimeout',
startup_timeout: 'elasticsearch.startupTimeout',
verify_ssl: 'elasticsearch.ssl.verify',
};

const deprecatedSettings = {
'server.xsrf.token': 'server.xsrf.token is deprecated. It is no longer used when providing xsrf protection.'
};

// transform legacy options into new namespaced versions
export function rewriteDeprecatedConfig(object, log = noop) {
const rewritten = transform(object, (clone, val, key) => {
if (legacySettings.hasOwnProperty(key)) {
const replacement = legacySettings[key];
log(`Config key "${key}" is deprecated. It has been replaced with "${replacement}"`);
clone[replacement] = val;
} else {
clone[key] = val;
}
}, {});

// walk through the object to find all nested keys,
// join them with simple string concatenation so that
// compound keys don't get considered a single path segment
(function recurse(obj, parent = []) {
forOwn(obj, (val, leaf) => {
const path = parent.concat(leaf);
const key = path.join('.');
if (deprecatedSettings.hasOwnProperty(key)) {
log(deprecatedSettings[key]);
} else if (typeof val === 'object') {
recurse(val, path);
}
});
}(rewritten));

return rewritten;
import { forOwn, has, noop } from 'lodash';

// deprecated settings are still allowed, but will be removed at a later time. They
// are checked for after the config object is prepared and known, so legacySettings
// will have already been transformed.
export const deprecatedSettings = new Map([
[['server', 'xsrf', 'token'], 'server.xsrf.token is deprecated. It is no longer used when providing xsrf protection.']
]);

// check for and warn about deprecated settings
export function checkForDeprecatedConfig(object, log = noop) {
for (const [key, msg] of deprecatedSettings.entries()) {
if (has(object, key)) log(msg);
}
return object;
}
47 changes: 47 additions & 0 deletions src/cli/serve/legacy_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { noop, transform } from 'lodash';

// legacySettings allow kibana 4.2+ to accept the same config file that people
// used for kibana 4.0 and 4.1. These settings are transformed to their modern
// equivalents at the very begining of the process
export const legacySettings = {
// server
port: 'server.port',
host: 'server.host',
pid_file: 'pid.file',
ssl_cert_file: 'server.ssl.cert',
ssl_key_file: 'server.ssl.key',

// logging
log_file: 'logging.dest',

// kibana
kibana_index: 'kibana.index',
default_app_id: 'kibana.defaultAppId',

// es
ca: 'elasticsearch.ssl.ca',
elasticsearch_preserve_host: 'elasticsearch.preserveHost',
elasticsearch_url: 'elasticsearch.url',
kibana_elasticsearch_client_crt: 'elasticsearch.ssl.cert',
kibana_elasticsearch_client_key: 'elasticsearch.ssl.key',
kibana_elasticsearch_password: 'elasticsearch.password',
kibana_elasticsearch_username: 'elasticsearch.username',
ping_timeout: 'elasticsearch.pingTimeout',
request_timeout: 'elasticsearch.requestTimeout',
shard_timeout: 'elasticsearch.shardTimeout',
startup_timeout: 'elasticsearch.startupTimeout',
verify_ssl: 'elasticsearch.ssl.verify',
};

// transform legacy options into new namespaced versions
export function rewriteLegacyConfig(object, log = noop) {
return transform(object, (clone, val, key) => {
if (legacySettings.hasOwnProperty(key)) {
const replacement = legacySettings[key];
log(`Config key "${key}" is deprecated. It has been replaced with "${replacement}"`);
clone[replacement] = val;
} else {
clone[key] = val;
}
}, {});
}
12 changes: 6 additions & 6 deletions src/cli/serve/read_yaml_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { safeLoad } from 'js-yaml';
import { red } from 'ansicolors';

import { fromRoot } from '../../utils';
import { rewriteDeprecatedConfig } from './deprecated_config';
import { rewriteLegacyConfig } from './legacy_config';
import { checkForDeprecatedConfig } from './deprecated_config';

const log = memoize(function (message) {
console.log(red('WARNING:'), message);
Expand Down Expand Up @@ -32,9 +33,8 @@ export function merge(sources) {
}

export default function (paths) {
const files = [].concat(paths || [])
.map(path => safeLoad(read(path, 'utf8')))
.map(file => rewriteDeprecatedConfig(file, log));

return merge(files);
const files = [].concat(paths || []);
const yamls = files.map(path => safeLoad(read(path, 'utf8')));
const config = merge(yamls.map(file => rewriteLegacyConfig(file, log)));
return checkForDeprecatedConfig(config, log);
}

0 comments on commit 5a100b3

Please sign in to comment.