feat(portal-data): instance sub-query, start/delete services
This commit is contained in:
parent
1e157641b2
commit
3c1763ceb4
@ -491,10 +491,11 @@ module.exports = class Data extends EventEmitter {
|
||||
manifest: manifest.raw
|
||||
};
|
||||
options.services[service.name] = replicas;
|
||||
this._dockerCompose.scale(options, (err) => {
|
||||
this._dockerCompose.scale(options, (err, res) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
console.log(JSON.stringify(res, null, ' '));
|
||||
finish();
|
||||
});
|
||||
}
|
||||
@ -592,9 +593,11 @@ module.exports = class Data extends EventEmitter {
|
||||
VAsync.forEachPipeline({
|
||||
func: (serviceName, next) => {
|
||||
const manifestService = manifestServices[serviceName];
|
||||
const container = provisionRes[serviceName].plan.containers[0];
|
||||
|
||||
const clientInstance = {
|
||||
name: serviceName,
|
||||
machineId: provisionRes[serviceName].plan.containers[0].id,
|
||||
machineId: container ? container.id : `${deploymentGroup.name}_${serviceName}_1`,
|
||||
status: 'CREATED'
|
||||
};
|
||||
this.createInstance(clientInstance, (err, createdInstance) => {
|
||||
@ -698,21 +701,12 @@ module.exports = class Data extends EventEmitter {
|
||||
return cb(null, null);
|
||||
}
|
||||
|
||||
VAsync.parallel({
|
||||
funcs: [
|
||||
(next) => {
|
||||
this._db.instances.get(service.instance_ids, next);
|
||||
},
|
||||
(next) => {
|
||||
this._db.packages.single({ id: service.package_id }, next);
|
||||
}
|
||||
]
|
||||
}, (err, results) => {
|
||||
this._db.packages.single({ id: service.package_id }, (err, packages) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
cb(null, Transform.fromService({ service, instances: results.successes[0], package: results.successes[1] }));
|
||||
cb(null, Transform.fromService({ service, instances: this._instancesFilter(service.instance_ids), packages }));
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -749,11 +743,45 @@ module.exports = class Data extends EventEmitter {
|
||||
}
|
||||
|
||||
return cb(null, services.map((service) => {
|
||||
return Transform.fromService({ service });
|
||||
return Transform.fromService({ service, instances: this._instancesFilter(service.instance_ids) });
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
_instancesFilter (instanceIds) {
|
||||
return ({ name, machineId, status }) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const query = {
|
||||
id: this._db.or(instanceIds)
|
||||
};
|
||||
|
||||
if (name) {
|
||||
query.name = name;
|
||||
}
|
||||
|
||||
if (machineId) {
|
||||
query.machine_id = machineId;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
query.status = status;
|
||||
}
|
||||
|
||||
this._db.instances.query(query, (err, instances) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
if (!instances || !instances.length) {
|
||||
return resolve([]);
|
||||
}
|
||||
|
||||
resolve(instances.map(Transform.fromInstance));
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
stopServices ({ ids }, cb) {
|
||||
this._db.services.get(ids, (err, services) => {
|
||||
if (err) {
|
||||
@ -799,15 +827,138 @@ module.exports = class Data extends EventEmitter {
|
||||
}
|
||||
|
||||
startServices ({ ids }, cb) {
|
||||
this._db.services.get(ids, (err, services) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
if (!services || !services.length) {
|
||||
return cb();
|
||||
}
|
||||
|
||||
let instanceIds = [];
|
||||
services.forEach((service) => {
|
||||
instanceIds = instanceIds.concat(service.instance_ids);
|
||||
});
|
||||
|
||||
VAsync.forEachParallel({
|
||||
func: (instanceId, next) => {
|
||||
this._db.instances.get(instanceId, (err, instance) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
const container = this._docker.getContainer(instance.machine_id);
|
||||
|
||||
container.start((err) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
this.updateInstance({ id: instance.id, status: 'RUNNING' }, next);
|
||||
});
|
||||
});
|
||||
},
|
||||
inputs: instanceIds
|
||||
}, (err, results) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
this.getServices({ ids }, cb);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
restartServices ({ ids }, cb) {
|
||||
this._db.services.get(ids, (err, services) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
if (!services || !services.length) {
|
||||
return cb();
|
||||
}
|
||||
|
||||
let instanceIds = [];
|
||||
services.forEach((service) => {
|
||||
instanceIds = instanceIds.concat(service.instance_ids);
|
||||
});
|
||||
|
||||
VAsync.forEachParallel({
|
||||
func: (instanceId, next) => {
|
||||
this._db.instances.get(instanceId, (err, instance) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
this.updateInstance({ id: instance.id, status: 'RESTARTING' }, () => {
|
||||
const container = this._docker.getContainer(instance.machine_id);
|
||||
|
||||
container.restart((err) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
this.updateInstance({ id: instance.id, status: 'RUNNING' }, next);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
inputs: instanceIds
|
||||
}, (err, results) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
this.getServices({ ids }, cb);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
deleteServices ({ ids }, cb) {
|
||||
this._db.services.get(ids, (err, services) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
if (!services || !services.length) {
|
||||
return cb();
|
||||
}
|
||||
|
||||
let instanceIds = [];
|
||||
services.forEach((service) => {
|
||||
instanceIds = instanceIds.concat(service.instance_ids);
|
||||
});
|
||||
|
||||
VAsync.forEachParallel({
|
||||
func: (instanceId, next) => {
|
||||
this._db.instances.get(instanceId, (err, instance) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
const container = this._docker.getContainer(instance.machine_id);
|
||||
|
||||
// Use force in case the container is running. TODO: should we keep force?
|
||||
container.remove({ force: true }, (err) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
this.updateInstance({ id: instance.id, status: 'DELETED' }, next);
|
||||
});
|
||||
});
|
||||
},
|
||||
inputs: instanceIds
|
||||
}, (err, results) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
this.getServices({ ids }, cb);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@ exports.fromService = function ({ service, instances, packages }) {
|
||||
name: service.name,
|
||||
slug: service.slug,
|
||||
environment: service.environment || [],
|
||||
instances: instances ? instances.map(exports.fromInstance) : [],
|
||||
instances,
|
||||
currentMetrics: [],
|
||||
connections: service.service_dependency_ids,
|
||||
package: packages ? exports.fromPackage(packages) : {},
|
||||
|
@ -691,11 +691,13 @@ describe.skip('scale()', () => {
|
||||
setTimeout(() => {
|
||||
data.getDeploymentGroup({ id: deploymentGroup.id }, (err, deploymentGroup) => {
|
||||
expect(err).to.not.exist();
|
||||
data.scale({ id: deploymentGroup.services[0].id, replicas: 3 }, (err, version) => {
|
||||
expect(err).to.not.exist();
|
||||
expect(version).to.exist();
|
||||
expect(version.scales[0].replicas).to.equal(3);
|
||||
done();
|
||||
deploymentGroup.services().then((deploymentGroupServices) => {
|
||||
data.scale({ id: deploymentGroupServices[0].id, replicas: 3 }, (err, version) => {
|
||||
expect(err).to.not.exist();
|
||||
expect(version).to.exist();
|
||||
expect(version.scales[0].replicas).to.equal(3);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, 80000);
|
||||
@ -739,3 +741,105 @@ describe.skip('stopServices()', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// skipping by default since it takes so long
|
||||
describe.skip('startServices()', () => {
|
||||
it('starts all instances of a service', { timeout: 180000 }, (done) => {
|
||||
const data = new PortalData(internals.options);
|
||||
data.connect((err) => {
|
||||
expect(err).to.not.exist();
|
||||
data.createDeploymentGroup({ name: 'something' }, (err, deploymentGroup) => {
|
||||
expect(err).to.not.exist();
|
||||
const clientManifest = {
|
||||
deploymentGroupId: deploymentGroup.id,
|
||||
type: 'compose',
|
||||
format: 'yml',
|
||||
raw: internals.composeFile
|
||||
};
|
||||
data.provisionManifest(clientManifest, (err, manifest) => {
|
||||
expect(err).to.not.exist();
|
||||
setTimeout(() => {
|
||||
data.getDeploymentGroup({ id: deploymentGroup.id }, (err, deploymentGroup) => {
|
||||
expect(err).to.not.exist();
|
||||
deploymentGroup.services().then((deploymentGroupServices) => {
|
||||
data.startServices({ ids: [deploymentGroupServices[0].id] }, (err, services) => {
|
||||
expect(err).to.not.exist();
|
||||
expect(services).to.exist();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, 80000);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// skipping by default since it takes so long
|
||||
describe.skip('restartServices()', () => {
|
||||
it('restarts all instances of a service', { timeout: 180000 }, (done) => {
|
||||
const data = new PortalData(internals.options);
|
||||
data.connect((err) => {
|
||||
expect(err).to.not.exist();
|
||||
data.createDeploymentGroup({ name: 'something' }, (err, deploymentGroup) => {
|
||||
expect(err).to.not.exist();
|
||||
const clientManifest = {
|
||||
deploymentGroupId: deploymentGroup.id,
|
||||
type: 'compose',
|
||||
format: 'yml',
|
||||
raw: internals.composeFile
|
||||
};
|
||||
data.provisionManifest(clientManifest, (err, manifest) => {
|
||||
expect(err).to.not.exist();
|
||||
setTimeout(() => {
|
||||
data.getDeploymentGroup({ id: deploymentGroup.id }, (err, deploymentGroup) => {
|
||||
expect(err).to.not.exist();
|
||||
deploymentGroup.services().then((deploymentGroupServices) => {
|
||||
data.restartServices({ ids: [deploymentGroupServices[0].id] }, (err, services) => {
|
||||
expect(err).to.not.exist();
|
||||
expect(services).to.exist();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, 80000);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// skipping by default since it takes so long
|
||||
describe.skip('deleteServices()', () => {
|
||||
it('deletes all instances of a service', { timeout: 180000 }, (done) => {
|
||||
const data = new PortalData(internals.options);
|
||||
data.connect((err) => {
|
||||
expect(err).to.not.exist();
|
||||
data.createDeploymentGroup({ name: 'something' }, (err, deploymentGroup) => {
|
||||
expect(err).to.not.exist();
|
||||
const clientManifest = {
|
||||
deploymentGroupId: deploymentGroup.id,
|
||||
type: 'compose',
|
||||
format: 'yml',
|
||||
raw: internals.composeFile
|
||||
};
|
||||
data.provisionManifest(clientManifest, (err, manifest) => {
|
||||
expect(err).to.not.exist();
|
||||
setTimeout(() => {
|
||||
data.getDeploymentGroup({ id: deploymentGroup.id }, (err, deploymentGroup) => {
|
||||
expect(err).to.not.exist();
|
||||
deploymentGroup.services().then((deploymentGroupServices) => {
|
||||
data.deleteServices({ ids: [deploymentGroupServices[0].id] }, (err, services) => {
|
||||
expect(err).to.not.exist();
|
||||
expect(services).to.exist();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, 80000);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user