e-ucm/rage-analytics-backend

View on GitHub
bin/upgrade/controllers/upgrade-elastic-indices.js

Summary

Maintainability
B
5 hrs
Test Coverage
/*
 * Copyright 2016 e-UCM (http://www.e-ucm.es/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * This project has received funding from the European Union’s Horizon
 * 2020 research and innovation programme under grant agreement No 644187.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0 (link is external)
 *
 * 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.
 */

'use strict';

var Path = require('path');
var elasticsearch = require('elasticsearch');
var upgrader = require(Path.resolve(__dirname, '../upgrader.js'));
var AbstractController = require(Path.resolve(__dirname, './abstract-controller.js'));
var transformerToVersion2 = require(Path.resolve(__dirname,
    '../transformers/elastic/transformToVersion2.js'));

function ElasticController() {
    AbstractController.call(this, [transformerToVersion2]);
}

ElasticController.prototype = new AbstractController();
ElasticController.prototype.constructor = ElasticController;

ElasticController.prototype.doConnect = function (config, callback) {
    var baseUsersAPI = config.elasticsearch.uri;

    var esClient = new elasticsearch.Client({
        host: baseUsersAPI,
        api: '5.6'
    });

    esClient.ping({
        // Ping usually has a 3000ms timeout
        requestTimeout: 3000
    }, function (error) {
        if (error) {
            callback(new Error('Elasticsearch cluster is down!' + error));
        } else {
            console.log('Successfully connected to elasticsearch!', baseUsersAPI);
            config.elasticsearch.esClient = esClient;
            callback(null, config);
        }
    });
};

ElasticController.prototype.getTargetVersion = function (config) {
    return config.elasticsearch.modelVersion.toString();
};

ElasticController.prototype.getModelVersion = function (config, callback) {
    var esClient = config.elasticsearch.esClient;
    var modelVersion = null;

    esClient.get({
        index: '.model',
        type: 'version',
        id: '1'
    }, function (error, response) {
        var needsVersionGuessing = false;
        if (error) {
            console.log('Error while retrieving ElasticSearch Model Version not found,' +
                ' will start guessing version!', error);
            needsVersionGuessing = true;
        } else {
            if (response && response._id === '1' && response._source) {
                var version = response._source.version;
                if (!version) {
                    console.log('ElasticSearch Model Version attribute not found, ' +
                        'will start guessing version!');
                    needsVersionGuessing = true;
                } else {
                    modelVersion = version.toString();
                }
            } else {
                console.log('ElasticSearch Model Version response (hits) not found, ' +
                    'will start guessing version!');
                needsVersionGuessing = true;
            }
        }

        if (needsVersionGuessing) {
            this.guessModelVersion(esClient, function(newVersion) {
                callback(null, newVersion);
            });
        } else {
            callback(null, modelVersion);
        }
    }.bind(this));
};

ElasticController.prototype.guessModelVersion = function(esClient, callback) {
    console.log('Trying to guess elasticsearch existing model version!');
    var defaultIndex = require(Path.resolve(__dirname, '../../../lib/kibana/defaultIndex.js'));
    var indexId = 'defaultIndex';

    if (defaultIndex && defaultIndex.title) {
        indexId = defaultIndex.title;
    }
    esClient.get({
        index: '.template',
        type: 'index',
        id: indexId
    }, function (error, response) {
        var minVersion = '1';
        if (error) {
            console.log('Error while retrieving ElasticSearch .template (defaultIndex) not found,' +
                ' defaulting to initial version!', error);
            callback(minVersion);
        } else {
            if (response && response._id === indexId && response._source) {
                var fieldStr = response._source.fields;
                if (!fieldStr) {
                    console.log('ElasticSearch Model Version attribute not found, ' +
                        'defaulting to initial version!');
                    callback(minVersion);
                } else {
                    try {
                        var fields = JSON.parse(fieldStr);

                        if (fields && fields.length > 0) {
                            var isVersion2 = false;

                            for (var i = 0; i < fields.length; ++i) {
                                var field = fields[i];
                                if (field && field.name && field.name.indexOf('ext.') === 0) {
                                    isVersion2 = field;
                                    break;
                                } else if (field && field.name && field.name.indexOf('out.ext.') === 0) {
                                    // Note that this is actually Version 3 of Elastic, but we don't have a transformer to version 3:
                                    // Changes: out.{trace} statement field, and other changes in trace format
                                    // Anyway, we set the version to 2, so that no changes are performed
                                    isVersion2 = field;
                                    break;
                                }
                            }

                            if (isVersion2) {
                                console.log('Fields parsed, found ext. def at field ' + JSON.stringify(isVersion2, null, 4));
                                callback('2');
                            } else {
                                console.log('Fields parsed object has elements but no ext valued found, defaulting to minimum version');
                                callback(minVersion);
                            }
                        } else {
                            console.log('Fields parsed object is null or empty array, defaulting to minimum version');
                            callback(minVersion);
                        }
                    } catch (ex) {
                        console.log('Error parsing .template defaultIndex.fields', ex);
                        callback(minVersion);
                    }
                }
            } else {
                callback(minVersion);

            }
        }

    }.bind(this));
};

ElasticController.prototype.setModelVersion = function (version, config, callback) {
    var esClient = this.appConfig.elasticsearch.esClient;
    esClient.index({
        index: '.model',
        type: 'version',
        id: '1',
        body: {
            version: version
        }
    }, function (error, response) {
        if (error) {
            return callback(error, response);
        }
        console.log('Finished transform elastic transformers phase!');
        callback(null, response);
    });
};

upgrader.controller('elastic', new ElasticController());