domotz-remote-pawn
Version:
Domotz Agent
125 lines (109 loc) • 5.02 kB
JavaScript
/** This file is part of Domotz Agent.
* Copyright (C) 2016 Domotz Ltd
*
* Domotz Agent is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Domotz Agent is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>.
**/
/**
* Created by Tommaso Latini <tommaso@domotz.com> on 18/12/15.
*/
const MODULE = 'UPDATE_PACKAGE';
const NODE_MODULES = 'node_modules';
const NODE_CMD = 'domotz_node';
var factory = function (q, path, random, http, log, status, file, proc, mutex, eventUtils, engineRequest) {
var env = process.env;
var exec = proc.exec;
var spawn = proc.spawn;
var kill = proc.kill;
var join = path.join;
var rootDir = env.DOMOTZ_ROOT_DIR;
var binDir = env.DOMOTZ_BIN_DIR;
var libDir = env.DOMOTZ_LIB_DIR;
var tmpInstallFolder = join(libDir, 'tmp_inst');
var npmArgs = [
join(binDir, 'domotz_npm'),
'--cache', join(rootDir, '.npm'),
'--userconfig', join(rootDir, '.npmrc')
];
var lockId = random.md5(String(Math.random()));
function updateAgent(registry, name, version) {
if (mutex.lock(MODULE, lockId)) {
var tmpPawnFolder = join(tmpInstallFolder, NODE_MODULES, name);
var pawnFolder = join(libDir, NODE_MODULES, name);
var oldPawnFolder = pawnFolder + '_old';
var npmInstallArgs = npmArgs.concat(['install', name + '@' + version, '--prefix', tmpInstallFolder]);
var previousStatus = status.get();
status.set(status.UPDATING);
console.info('%s - Start Update Agent from %s. Name: %s, Version: %s.',
MODULE, registry, name, version);
exec('rm -rf ' + oldPawnFolder)
.then(function() {
console.info('%s - Removed %s', MODULE, oldPawnFolder);
return exec('rm -rf ' + tmpInstallFolder);
})
.then(function() {
console.info('%s - Creating %s', MODULE, tmpInstallFolder);
return exec('mkdir -p ' + tmpInstallFolder);
})
.then(function () {
console.info('%s - Created %s', MODULE, tmpInstallFolder);
return spawn(NODE_CMD, npmInstallArgs);
})
.then(function() {
console.info('%s - Finished download of package: %s@%s',
MODULE, name, version);
// NOTE: The domotz package replacement must be synchronous
// to minimize other routines interference
file.rename(pawnFolder, oldPawnFolder);
file.rename(tmpPawnFolder, pawnFolder);
console.info('%s - Moved %s -> %s. Finish installation of: %s@%s',
MODULE, tmpPawnFolder, pawnFolder, name, version);
})
.then(function() {
console.info('%s - Removing %s', MODULE, tmpInstallFolder);
return exec('rm -rf ' + tmpInstallFolder);
})
.then(function () {
var deferred = q.defer();
if (!engineRequest || typeof engineRequest !== 'object' || typeof engineRequest.sendWithPromise !== 'function') {
deferred.resolve();
} else {
var body = eventUtils.getBodyForEvent("down", "updateAgent");
engineRequest.sendWithPromise(
'/event', 'POST', body, undefined, undefined,
{maxAttempts: 5, retryDelay: 3000})
.finally(function () {
deferred.resolve();
});
}
return deferred;
})
.then(function() {
return kill(process.pid);
})
.catch(function errorHandler(err) {
console.warn('%s - Failed update procedure', MODULE);
console.error('%s - Error: %s', MODULE, JSON.stringify(err));
console.error(err.stack);
})
.finally(function () {
mutex.unlock(MODULE, lockId);
status.set(previousStatus);
});
}
}
return {
updateAgent: updateAgent
};
};
module.exports.factory = factory;