Skip to content

Commit

Permalink
ES Healthcheck v6 mapping compatibility (elastic#12714)
Browse files Browse the repository at this point in the history
* Beginning to update the healthcheck to use the SavedObjectsClient

Some tests are still broken
The sort method on the SavedObjectsClient isn't there yet

* Adding sort to create_find_query

* Fixing the tests

* Fixing upgrade_config tests

* Making the SavedObjectsClient be dependant on the mappings to enable
sorting

* Fixing disabled tests

* Fiixng test wording

* Passing the savedObjectsClient to the stats route handler

* Passing the savedObjectsClient to upgradeConfig from migratConfig

* Using array of keys with _.get instead of manual string concatenation
  • Loading branch information
kobelb committed Jul 10, 2017
1 parent 5478a8f commit e43f645
Show file tree
Hide file tree
Showing 15 changed files with 236 additions and 198 deletions.
2 changes: 2 additions & 0 deletions src/core_plugins/elasticsearch/lib/__tests__/health_check.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ describe('plugins/elasticsearch', () => {

cluster = { callWithInternalUser: sinon.stub() };
cluster.callWithInternalUser.withArgs('index', sinon.match.any).returns(Promise.resolve());
cluster.callWithInternalUser.withArgs('create', sinon.match.any).returns(Promise.resolve({ _id: 1, _version: 1 }));
cluster.callWithInternalUser.withArgs('mget', sinon.match.any).returns(Promise.resolve({ ok: true }));
cluster.callWithInternalUser.withArgs('get', sinon.match.any).returns(Promise.resolve({ found: false }));
cluster.callWithInternalUser.withArgs('search', sinon.match.any).returns(Promise.resolve({ hits: { hits: [] } }));
Expand All @@ -61,6 +62,7 @@ describe('plugins/elasticsearch', () => {
const get = sinon.stub();
get.withArgs('elasticsearch.url').returns(esUrl);
get.withArgs('kibana.index').returns('.my-kibana');
get.withArgs('pkg.version').returns('1.0.0');

const set = sinon.stub();

Expand Down
32 changes: 14 additions & 18 deletions src/core_plugins/elasticsearch/lib/__tests__/is_upgradeable.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ describe('plugins/elasticsearch', function () {
})
};

function upgradeDoc(_id, _version, bool) {
function upgradeDoc(id, _version, bool) {
describe('', function () {
before(function () { version = _version; });

it(`should return ${bool} for ${_id} <= ${version}`, function () {
expect(isUpgradeable(server, { _id: _id })).to.be(bool);
it(`should return ${bool} for ${id} <= ${version}`, function () {
expect(isUpgradeable(server, { id: id })).to.be(bool);
});

after(function () { version = pkg.version; });
Expand All @@ -42,32 +42,28 @@ describe('plugins/elasticsearch', function () {
upgradeDoc('4.1.0-rc1-SNAPSHOT', '4.1.0-rc1', false);
upgradeDoc('5.0.0-alpha1', '5.0.0', false);

it('should handle missing _id field', function () {
const doc = {
'_index': '.kibana',
'_type': 'config',
'_score': 1,
'_source': {
it('should handle missing id field', function () {
const configSavedObject = {
'type': 'config',
'attributes': {
'buildNum': 1.7976931348623157e+308,
'defaultIndex': '[logstash-]YYYY.MM.DD'
}
};

expect(isUpgradeable(server, doc)).to.be(false);
expect(isUpgradeable(server, configSavedObject)).to.be(false);
});

it('should handle _id of @@version', function () {
const doc = {
'_index': '.kibana',
'_type': 'config',
'_id': '@@version',
'_score': 1,
'_source': {
it('should handle id of @@version', function () {
const configSavedObject = {
'type': 'config',
'id': '@@version',
'attributes': {
'buildNum': 1.7976931348623157e+308,
'defaultIndex': '[logstash-]YYYY.MM.DD'
}
};
expect(isUpgradeable(server, doc)).to.be(false);
expect(isUpgradeable(server, configSavedObject)).to.be(false);
});

});
Expand Down
114 changes: 54 additions & 60 deletions src/core_plugins/elasticsearch/lib/__tests__/upgrade_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('plugins/elasticsearch', function () {
describe('lib/upgrade_config', function () {
let get;
let server;
let callWithInternalUser;
let savedObjectsClient;
let upgrade;

beforeEach(function () {
Expand All @@ -17,7 +17,9 @@ describe('plugins/elasticsearch', function () {
get.withArgs('pkg.version').returns('4.0.1');
get.withArgs('pkg.buildNum').returns(Math.random());

callWithInternalUser = sinon.stub();
savedObjectsClient = {
create: sinon.stub()
};

server = {
log: sinon.stub(),
Expand All @@ -26,22 +28,15 @@ describe('plugins/elasticsearch', function () {
get: get
};
},
plugins: {
elasticsearch: {
getCluster: sinon.stub().withArgs('admin').returns({
callWithInternalUser: callWithInternalUser
})
}
}
};
upgrade = upgradeConfig(server);
upgrade = upgradeConfig(server, savedObjectsClient);
});

describe('nothing is found', function () {
const response = { hits: { hits:[] } };
const configSavedObjects = { hits: { hits:[] } };

beforeEach(function () {
callWithInternalUser.withArgs('create', sinon.match.any).returns(Promise.resolve());
savedObjectsClient.create.returns(Promise.resolve({ id: 1, version: 1 }));
});

describe('production', function () {
Expand All @@ -52,17 +47,17 @@ describe('plugins/elasticsearch', function () {
});

it('should resolve buildNum to pkg.buildNum config', function () {
return upgrade(response).then(function () {
sinon.assert.calledOnce(callWithInternalUser);
const params = callWithInternalUser.args[0][1];
expect(params.body).to.have.property('buildNum', get('pkg.buildNum'));
return upgrade(configSavedObjects).then(function () {
sinon.assert.calledOnce(savedObjectsClient.create);
const attributes = savedObjectsClient.create.args[0][1];
expect(attributes).to.have.property('buildNum', get('pkg.buildNum'));
});
});

it('should resolve version to pkg.version config', function () {
return upgrade(response).then(function () {
const params = callWithInternalUser.args[0][1];
expect(params).to.have.property('id', get('pkg.version'));
return upgrade(configSavedObjects).then(function () {
const options = savedObjectsClient.create.args[0][2];
expect(options).to.have.property('id', get('pkg.version'));
});
});
});
Expand All @@ -75,68 +70,68 @@ describe('plugins/elasticsearch', function () {
});

it('should resolve buildNum to pkg.buildNum config', function () {
return upgrade(response).then(function () {
const params = callWithInternalUser.args[0][1];
expect(params.body).to.have.property('buildNum', get('pkg.buildNum'));
return upgrade(configSavedObjects).then(function () {
const attributes = savedObjectsClient.create.args[0][1];
expect(attributes).to.have.property('buildNum', get('pkg.buildNum'));
});
});

it('should resolve version to pkg.version config', function () {
return upgrade(response).then(function () {
const params = callWithInternalUser.args[0][1];
expect(params).to.have.property('id', get('pkg.version'));
return upgrade(configSavedObjects).then(function () {
const options = savedObjectsClient.create.args[0][2];
expect(options).to.have.property('id', get('pkg.version'));
});
});
});
});

it('should resolve with undefined if the current version is found', function () {
const response = { hits: { hits: [ { _id: '4.0.1' } ] } };
return upgrade(response).then(function (resp) {
const configSavedObjects = [ { id: '4.0.1' } ];
return upgrade(configSavedObjects).then(function (resp) {
expect(resp).to.be(undefined);
});
});

it('should create new config if the nothing is upgradeable', function () {
get.withArgs('pkg.buildNum').returns(9833);
callWithInternalUser.withArgs('create', sinon.match.any).returns(Promise.resolve());

const response = { hits: { hits: [ { _id: '4.0.1-alpha3' }, { _id: '4.0.1-beta1' }, { _id: '4.0.0-SNAPSHOT1' } ] } };
return upgrade(response).then(function () {
sinon.assert.calledOnce(callWithInternalUser);
const params = callWithInternalUser.args[0][1];
expect(params).to.have.property('body');
expect(params.body).to.have.property('buildNum', 9833);
expect(params).to.have.property('index', '.my-kibana');
expect(params).to.have.property('type', 'config');
expect(params).to.have.property('id', '4.0.1');
savedObjectsClient.create.returns(Promise.resolve({ id: 1, version: 1 }));

const configSavedObjects = [ { id: '4.0.1-alpha3' }, { id: '4.0.1-beta1' }, { id: '4.0.0-SNAPSHOT1' } ];
return upgrade(configSavedObjects).then(function () {
sinon.assert.calledOnce(savedObjectsClient.create);
const savedObjectType = savedObjectsClient.create.args[0][0];
expect(savedObjectType).to.eql('config');
const attributes = savedObjectsClient.create.args[0][1];
expect(attributes).to.have.property('buildNum', 9833);
const options = savedObjectsClient.create.args[0][2];
expect(options).to.have.property('id', '4.0.1');
});
});

it('should update the build number on the new config', function () {
get.withArgs('pkg.buildNum').returns(5801);
callWithInternalUser.withArgs('create', sinon.match.any).returns(Promise.resolve());

const response = { hits: { hits: [ { _id: '4.0.0', _source: { buildNum: 1 } } ] } };

return upgrade(response).then(function () {
sinon.assert.calledOnce(callWithInternalUser);
const params = callWithInternalUser.args[0][1];
expect(params).to.have.property('body');
expect(params.body).to.have.property('buildNum', 5801);
expect(params).to.have.property('index', '.my-kibana');
expect(params).to.have.property('type', 'config');
expect(params).to.have.property('id', '4.0.1');
savedObjectsClient.create.returns(Promise.resolve({ id: 1, version: 1 }));

const configSavedObjects = [ { id: '4.0.0', attributes: { buildNum: 1 } } ];

return upgrade(configSavedObjects).then(function () {
sinon.assert.calledOnce(savedObjectsClient.create);
const attributes = savedObjectsClient.create.args[0][1];
expect(attributes).to.have.property('buildNum', 5801);
const savedObjectType = savedObjectsClient.create.args[0][0];
expect(savedObjectType).to.eql('config');
const options = savedObjectsClient.create.args[0][2];
expect(options).to.have.property('id', '4.0.1');
});
});

it('should log a message for upgrades', function () {
get.withArgs('pkg.buildNum').returns(5801);
callWithInternalUser.withArgs('create', sinon.match.any).returns(Promise.resolve());
savedObjectsClient.create.returns(Promise.resolve({ id: 1, version: 1 }));

const response = { hits: { hits: [ { _id: '4.0.0', _source: { buildNum: 1 } } ] } };
const configSavedObjects = [ { id: '4.0.0', attributes: { buildNum: 1 } } ];

return upgrade(response).then(function () {
return upgrade(configSavedObjects).then(function () {
sinon.assert.calledOnce(server.log);
expect(server.log.args[0][0]).to.eql(['plugin', 'elasticsearch']);
const msg = server.log.args[0][1];
Expand All @@ -148,15 +143,14 @@ describe('plugins/elasticsearch', function () {

it('should copy attributes from old config', function () {
get.withArgs('pkg.buildNum').returns(5801);
callWithInternalUser.withArgs('create', sinon.match.any).returns(Promise.resolve());
savedObjectsClient.create.returns(Promise.resolve({ id: 1, version: 1 }));

const response = { hits: { hits: [ { _id: '4.0.0', _source: { buildNum: 1, defaultIndex: 'logstash-*' } } ] } };
const configSavedObjects = [ { id: '4.0.0', attributes: { buildNum: 1, defaultIndex: 'logstash-*' } } ];

return upgrade(response).then(function () {
sinon.assert.calledOnce(callWithInternalUser);
const params = callWithInternalUser.args[0][1];
expect(params).to.have.property('body');
expect(params.body).to.have.property('defaultIndex', 'logstash-*');
return upgrade(configSavedObjects).then(function () {
sinon.assert.calledOnce(savedObjectsClient.create);
const attributes = savedObjectsClient.create.args[0][1];
expect(attributes).to.have.property('defaultIndex', 'logstash-*');
});
});
});
Expand Down
14 changes: 7 additions & 7 deletions src/core_plugins/elasticsearch/lib/is_upgradeable.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import semver from 'semver';
const rcVersionRegex = /(\d+\.\d+\.\d+)\-rc(\d+)/i;

module.exports = function (server, doc) {
export default function (server, configSavedObject) {
const config = server.config();
if (/alpha|beta|snapshot/i.test(doc._id)) return false;
if (!doc._id) return false;
if (doc._id === config.get('pkg.version')) return false;
if (/alpha|beta|snapshot/i.test(configSavedObject.id)) return false;
if (!configSavedObject.id) return false;
if (configSavedObject.id === config.get('pkg.version')) return false;

let packageRcRelease = Infinity;
let rcRelease = Infinity;
let packageVersion = config.get('pkg.version');
let version = doc._id;
const matches = doc._id.match(rcVersionRegex);
let version = configSavedObject.id;
const matches = configSavedObject.id.match(rcVersionRegex);
const packageMatches = config.get('pkg.version').match(rcVersionRegex);

if (matches) {
Expand All @@ -30,4 +30,4 @@ module.exports = function (server, doc) {
return false;
}
return true;
};
}
30 changes: 12 additions & 18 deletions src/core_plugins/elasticsearch/lib/migrate_config.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
import { get } from 'lodash';
import upgrade from './upgrade_config';
import { SavedObjectsClient } from '../../../server/saved_objects';

module.exports = function (server, { mappings }) {
export default async function (server, { mappings }) {
const config = server.config();
const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin');
const options = {
index: config.get('kibana.index'),

const savedObjectsClient = new SavedObjectsClient(config.get('kibana.index'), mappings, callWithInternalUser);
const { saved_objects: configSavedObjects } = await savedObjectsClient.find({
type: 'config',
body: {
size: 1000,
sort: [
{
buildNum: {
order: 'desc',
unmapped_type: get(mappings, 'config.properties.buildNum.type') || 'keyword'
}
}
]
}
};
page: 1,
perPage: 1000,
sortField: 'buildNum',
sortOrder: 'desc'
});

return callWithInternalUser('search', options).then(upgrade(server));
};
return await upgrade(server, savedObjectsClient)(configSavedObjects);
}
Loading

0 comments on commit e43f645

Please sign in to comment.