mirror of
https://github.com/yldio/copilot.git
synced 2024-12-01 07:30:07 +02:00
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
|
manifest: manifest.raw
|
||||||
};
|
};
|
||||||
options.services[service.name] = replicas;
|
options.services[service.name] = replicas;
|
||||||
this._dockerCompose.scale(options, (err) => {
|
this._dockerCompose.scale(options, (err, res) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
|
console.log(JSON.stringify(res, null, ' '));
|
||||||
finish();
|
finish();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -592,9 +593,11 @@ module.exports = class Data extends EventEmitter {
|
|||||||
VAsync.forEachPipeline({
|
VAsync.forEachPipeline({
|
||||||
func: (serviceName, next) => {
|
func: (serviceName, next) => {
|
||||||
const manifestService = manifestServices[serviceName];
|
const manifestService = manifestServices[serviceName];
|
||||||
|
const container = provisionRes[serviceName].plan.containers[0];
|
||||||
|
|
||||||
const clientInstance = {
|
const clientInstance = {
|
||||||
name: serviceName,
|
name: serviceName,
|
||||||
machineId: provisionRes[serviceName].plan.containers[0].id,
|
machineId: container ? container.id : `${deploymentGroup.name}_${serviceName}_1`,
|
||||||
status: 'CREATED'
|
status: 'CREATED'
|
||||||
};
|
};
|
||||||
this.createInstance(clientInstance, (err, createdInstance) => {
|
this.createInstance(clientInstance, (err, createdInstance) => {
|
||||||
@ -698,21 +701,12 @@ module.exports = class Data extends EventEmitter {
|
|||||||
return cb(null, null);
|
return cb(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
VAsync.parallel({
|
this._db.packages.single({ id: service.package_id }, (err, packages) => {
|
||||||
funcs: [
|
|
||||||
(next) => {
|
|
||||||
this._db.instances.get(service.instance_ids, next);
|
|
||||||
},
|
|
||||||
(next) => {
|
|
||||||
this._db.packages.single({ id: service.package_id }, next);
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}, (err, results) => {
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb(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 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) {
|
stopServices ({ ids }, cb) {
|
||||||
this._db.services.get(ids, (err, services) => {
|
this._db.services.get(ids, (err, services) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -799,15 +827,138 @@ module.exports = class Data extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
startServices ({ ids }, cb) {
|
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) {
|
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) {
|
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,
|
name: service.name,
|
||||||
slug: service.slug,
|
slug: service.slug,
|
||||||
environment: service.environment || [],
|
environment: service.environment || [],
|
||||||
instances: instances ? instances.map(exports.fromInstance) : [],
|
instances,
|
||||||
currentMetrics: [],
|
currentMetrics: [],
|
||||||
connections: service.service_dependency_ids,
|
connections: service.service_dependency_ids,
|
||||||
package: packages ? exports.fromPackage(packages) : {},
|
package: packages ? exports.fromPackage(packages) : {},
|
||||||
|
@ -691,13 +691,15 @@ describe.skip('scale()', () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
data.getDeploymentGroup({ id: deploymentGroup.id }, (err, deploymentGroup) => {
|
data.getDeploymentGroup({ id: deploymentGroup.id }, (err, deploymentGroup) => {
|
||||||
expect(err).to.not.exist();
|
expect(err).to.not.exist();
|
||||||
data.scale({ id: deploymentGroup.services[0].id, replicas: 3 }, (err, version) => {
|
deploymentGroup.services().then((deploymentGroupServices) => {
|
||||||
|
data.scale({ id: deploymentGroupServices[0].id, replicas: 3 }, (err, version) => {
|
||||||
expect(err).to.not.exist();
|
expect(err).to.not.exist();
|
||||||
expect(version).to.exist();
|
expect(version).to.exist();
|
||||||
expect(version.scales[0].replicas).to.equal(3);
|
expect(version.scales[0].replicas).to.equal(3);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}, 80000);
|
}, 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