joyent-portal/packages/portal-watch/lib/index.js

174 lines
4.2 KiB
JavaScript

'use strict';
// const Assert = require('assert');
const TritonWatch = require('triton-watch');
const DEPLOYMENT_GROUP = 'docker:label:com.docker.compose.project';
const SERVICE = 'docker:label:com.docker.compose.service';
const HASH = 'docker:label:com.docker.compose.config-hash';
module.exports = class Watcher {
constructor (options) {
options = options || {};
// todo assert options
this._data = options.data;
this._tritonWatch = new TritonWatch({
frequency: 500,
triton: {
profile: {
url: options.url || process.env.SDC_URL,
account: options.account || process.env.SDC_ACCOUNT,
keyId: options.keyId || process.env.SDC_KEY_ID
}
}
});
this._tritonWatch.on('change', (container) => { return this.onChange(container); });
}
getDeploymentGroupId (name, cb) {
this._data.getDeploymentGroup({ name }, (err, deploymentGroup) => {
if (err) {
return cb(err);
}
return cb(null, deploymentGroup && deploymentGroup.id);
});
}
getServiceId ({ serviceName, deploymentGroupId }, cb) {
this._data.getServices({ name: serviceName, deploymentGroupId }, (err, services) => {
if (err) {
return cb(err);
}
if (!services || !services.length) {
return cb();
}
return cb(null, services.pop().id);
});
}
getInstance (machineId, cb) {
this._data.getInstances({ machineId }, (err, instances) => {
if (err) {
return cb(err);
}
if (!instances || !instances.length) {
return cb();
}
return cb(null, instances.pop());
});
}
resolveChanges ({ machine, deploymentGroupId, serviceId, instance }) {
const handleError = (err) => {
if (err) {
console.error(err);
}
};
const create = () => {
return this._data.updateInstance({
name: machine.name,
status: machine.state.toUpperCase(),
machineId: machine.id
}, handleError);
};
const update = () => {
return this._data.updateInstance({
id: instance.id,
status: machine.state.toUpperCase()
}, handleError);
};
return (!instance || !instance.id) ?
create() :
update();
}
onChange (machine) {
if (!machine) {
console.error('`change` event received without machine data');
return;
}
const { id, tags = [] } = machine;
// assert id existence
if (!id) {
console.error('`change` event received for a machine without `id`');
return;
}
// assert that it's a docker-compose project
const isCompose = [DEPLOYMENT_GROUP, SERVICE, HASH].every(
(name) => { return tags[name]; }
);
if (!isCompose) {
console.error(`Changed machine ${id} was not provisioned by docker-compose`);
return;
}
const deploymentGroupName = tags[DEPLOYMENT_GROUP];
const serviceName = tags[SERVICE];
const handleError = (next) => {
return (err, item) => {
if (err) {
console.error(err);
return;
}
next(item);
};
};
const getInstance = (deploymentGroupId, serviceId) => {
this.getInstance(id, handleError((instance) => {
return this.resolveChanges({
machine,
deploymentGroupId,
serviceId,
instance
});
}));
};
// assert that service exists
const assertService = (deploymentGroupId) => {
this.getServiceId({ serviceName, deploymentGroupId }, handleError((serviceId) => {
if (!serviceId) {
console.error(`Service "${serviceName}" form DeploymentGroup "${deploymentGroupName}" for machine ${id} not found`);
return;
}
getInstance(deploymentGroupId, serviceId);
}));
};
// assert that project managed by this portal
const assertDeploymentGroup = () => {
this.getDeploymentGroupId(deploymentGroupName, handleError((deploymentGroupId) => {
if (!deploymentGroupId) {
console.error(`DeploymentGroup "${deploymentGroupName}" for machine ${id} not found`);
return;
}
assertService(deploymentGroupId);
}));
};
assertDeploymentGroup();
}
};