feat(cp-gql-mock-server): handle service branches

This commit is contained in:
Sérgio Ramos 2017-07-14 12:15:13 +01:00 committed by Judit Greskovits
parent 46a352d0c8
commit 92181a2df0
3 changed files with 132 additions and 114 deletions

View File

@ -23,6 +23,9 @@
"joi": "^10.6.0", "joi": "^10.6.0",
"joyent-cp-gql-schema": "^1.0.4", "joyent-cp-gql-schema": "^1.0.4",
"js-yaml": "^3.8.4", "js-yaml": "^3.8.4",
"lodash.find": "^4.6.0",
"lodash.flatten": "^4.4.0",
"lodash.uniq": "^4.5.0",
"param-case": "^2.1.1", "param-case": "^2.1.1",
"uuid": "^3.1.0" "uuid": "^3.1.0"
}, },

View File

@ -66,21 +66,18 @@
"id": "4ee4103e-1a52-4099-a48e-01588f597c70", "id": "4ee4103e-1a52-4099-a48e-01588f597c70",
"slug": "percona", "slug": "percona",
"name": "Percona", "name": "Percona",
"deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401" "deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401",
}, "branches": [{
{ "id": "dmklaskdls",
"id": "9572d367-c4ae-4fb1-8ad5-f5e3830e7034", "slug": "percona",
"slug": "primary", "name": "Percona",
"name": "Primary", "instances": ["c3ec7633-a02b-4615-86a0-9e6faeaae94b"]
"parent": "4ee4103e-1a52-4099-a48e-01588f597c70", }, {
"deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401" "id": "dmklaskdls",
}, "slug": "percona-primary",
{ "name": "percona-primary",
"id": "c8411ef0-ab39-42cb-a704-d20b170eff31", "instances": ["c2b5fec2-31e2-41a7-b7fc-cd0bb1822e76"]
"slug": "secondaries", }]
"name": "Secondaries",
"parent": "4ee4103e-1a52-4099-a48e-01588f597c70",
"deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401"
}, },
{ {
"id": "97c68055-db88-45c9-ad49-f26da4264777", "id": "97c68055-db88-45c9-ad49-f26da4264777",
@ -183,7 +180,7 @@
{ {
"id": "c3ec7633-a02b-4615-86a0-9e6faeaae94b", "id": "c3ec7633-a02b-4615-86a0-9e6faeaae94b",
"name": "percona-primary", "name": "percona-primary",
"serviceId": "9572d367-c4ae-4fb1-8ad5-f5e3830e7034", "serviceId": "4ee4103e-1a52-4099-a48e-01588f597c70",
"deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401", "deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401",
"status": "RUNNING", "status": "RUNNING",
"healthy": "UNHEALTHY" "healthy": "UNHEALTHY"
@ -191,7 +188,7 @@
{ {
"id": "c2b5fec2-31e2-41a7-b7fc-cd0bb1822e76", "id": "c2b5fec2-31e2-41a7-b7fc-cd0bb1822e76",
"name": "percona-secondary", "name": "percona-secondary",
"serviceId": "c8411ef0-ab39-42cb-a704-d20b170eff31", "serviceId": "4ee4103e-1a52-4099-a48e-01588f597c70",
"deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401", "deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401",
"status": "RUNNING", "status": "RUNNING",
"healthy": "HEALTHY" "healthy": "HEALTHY"

View File

@ -1,6 +1,9 @@
const { v4: uuid } = require('uuid'); const { v4: uuid } = require('uuid');
const paramCase = require('param-case'); const paramCase = require('param-case');
const camelCase = require('camel-case'); const camelCase = require('camel-case');
const lfind = require('lodash.find');
const flatten = require('lodash.flatten');
const uniq = require('lodash.uniq');
const yaml = require('js-yaml'); const yaml = require('js-yaml');
const { const {
@ -30,7 +33,17 @@ const getUnfilteredServices = query => {
const addNestedResolvers = service => const addNestedResolvers = service =>
Object.assign({}, service, { Object.assign({}, service, {
instances: instancesResolver(service) instances: instancesResolver(service),
branches: (service.branches || []).map(service =>
Object.assign({}, service, {
instances: () =>
Promise.resolve(
flatten(
service.instances.map(id => instances.filter(find({ id })))
)
)
})
)
}); });
return Promise.resolve( return Promise.resolve(
@ -39,68 +52,30 @@ const getUnfilteredServices = query => {
}; };
const getServices = query => { const getServices = query => {
// get all services
const services = getUnfilteredServices(query) const services = getUnfilteredServices(query)
.then(services => { // get all instances
// loop through services and for each of them get all services that's parent id is the service .then(services =>
// once done - this will be a Promise all - need to remove any duplicates from the services list - the original
// then we can do below...
return (
Promise.all( Promise.all(
services.map(service => getUnfilteredServices({ parent: service.id }))
)
// this is going to be an array of arrays of services
.then(childServices => {
return childServices.reduce((childServices, childService) => {
return childServices.concat(childService);
}, []);
})
// now it's at least flat
.then(childServices => {
return services.concat(
childServices.reduce((childServices, childService) => {
const exists = services.filter(
service => service.id === childService.id
).length;
if (!exists) {
childServices.push(childService);
}
return childServices;
}, [])
);
})
.then(services => {
return Promise.all(
services.map(service => service.instances()) services.map(service => service.instances())
).then(instances => { ).then(instances => ({
return { services, instances }; services,
}); instances
}) }))
); )
})
.then(({ services, instances }) => { .then(({ services, instances }) => {
const activeServices = services.reduce((services, service, index) => { // filter all available instances
const active = instances[index].filter( const availableInstances = flatten(
instance => instances.filter(
instance.status !== 'DELETED' && instance.status !== 'EXITED' ({ status }) => ['DELETED', 'EXITED'].indexOf(status) < 0
).length; )
if (active) { );
services.push(service);
} // get all the serviceIds of the available instances
return services; // and then get the servcies with those ids
}, []); return uniq(
const allServices = activeServices.reduce((allServices, service) => { availableInstances.map(({ serviceId }) => serviceId)
if (service.parent) { ).map(serviceId => lfind(services, ['id', serviceId]));
const parentService = services.filter(s => s.id === service.parent);
const exists = allServices.filter(s => s.id === service.parent)
.length;
if (!exists && parentService) {
allServices.push(parentService[0]);
}
}
allServices.push(service);
return allServices;
}, []);
return allServices;
}); });
return Promise.resolve(services); return Promise.resolve(services);
@ -197,51 +172,79 @@ const updateServiceStatus = (ss, status) => {
service.status = status; service.status = status;
}); });
return null; return null;
} };
const updateServiceAndInstancesStatus = (serviceId, serviceStatus, instancesStatus) => { const updateServiceAndInstancesStatus = (
serviceId,
serviceStatus,
instancesStatus
) => {
return Promise.all([ return Promise.all([
getServices({ id: serviceId }), getServices({ id: serviceId }),
getServices({ parentId: serviceId }) getServices({ parentId: serviceId })
]) ])
.then(services => services.reduce((services, service) => .then(services =>
services.concat(service), [])) services.reduce((services, service) => services.concat(service), [])
)
.then(services => { .then(services => {
updateServiceStatus(services, serviceStatus); updateServiceStatus(services, serviceStatus);
return Promise.all( return Promise.all(
services.reduce((instances, service) => services.reduce(
service.instances ? instances.concat(service.instances()) : instances, [])) (instances, service) =>
.then(instances => updateInstancesStatus(instances.reduce((is, i) => service.instances
is.concat(i), []), instancesStatus)) ? instances.concat(service.instances())
: instances,
[]
)
).then(instances =>
updateInstancesStatus(
instances.reduce((is, i) => is.concat(i), []),
instancesStatus
)
);
}) })
.then(() => Promise.all([ .then(() =>
Promise.all([
getUnfilteredServices({ id: serviceId }), getUnfilteredServices({ id: serviceId }),
getUnfilteredServices({ parentId: serviceId }) getUnfilteredServices({ parentId: serviceId })
])) ])
.then(services => services.reduce((services, service) => )
services.concat(service), [])); .then(services =>
services.reduce((services, service) => services.concat(service), [])
);
}; };
const handleStatusUpdateRequest = (serviceId, const handleStatusUpdateRequest = (
transitionalServiceStatus, transitionalInstancesStatus, serviceId,
serviceStatus, instancesStatus) => { transitionalServiceStatus,
transitionalInstancesStatus,
serviceStatus,
instancesStatus
) => {
// this is what we need to delay // this is what we need to delay
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
updateServiceAndInstancesStatus(serviceId, updateServiceAndInstancesStatus(serviceId, serviceStatus, instancesStatus);
serviceStatus, instancesStatus);
}, 5000); }, 5000);
// this is what we'll need to return // this is what we'll need to return
return updateServiceAndInstancesStatus(serviceId, return updateServiceAndInstancesStatus(
transitionalServiceStatus, transitionalInstancesStatus); serviceId,
} transitionalServiceStatus,
transitionalInstancesStatus
);
};
const deleteServices = options => { const deleteServices = options => {
// service transitional 'DELETING' // service transitional 'DELETING'
// instances transitional 'STOPPING' // instances transitional 'STOPPING'
// service 'DELETED' // service 'DELETED'
// instances 'DELETED' // instances 'DELETED'
const deleteService = handleStatusUpdateRequest(options.ids[0], const deleteService = handleStatusUpdateRequest(
'DELETING', 'STOPPING', 'DELETED', 'DELETED'); options.ids[0],
'DELETING',
'STOPPING',
'DELETED',
'DELETED'
);
return Promise.resolve(deleteService); return Promise.resolve(deleteService);
}; };
@ -250,8 +253,13 @@ const stopServices = options => {
// instances transitional 'STOPPING' // instances transitional 'STOPPING'
// service 'STOPPED' // service 'STOPPED'
// instances 'STOPPED' // instances 'STOPPED'
const stopService = handleStatusUpdateRequest(options.ids[0], const stopService = handleStatusUpdateRequest(
'STOPPING', 'STOPPING', 'STOPPED', 'STOPPED'); options.ids[0],
'STOPPING',
'STOPPING',
'STOPPED',
'STOPPED'
);
return Promise.resolve(stopService); return Promise.resolve(stopService);
}; };
@ -260,8 +268,13 @@ const startServices = options => {
// instances transitional ... // instances transitional ...
// service 'ACTIVE' // service 'ACTIVE'
// instances 'RUNNING' // instances 'RUNNING'
const startService = handleStatusUpdateRequest(options.ids[0], const startService = handleStatusUpdateRequest(
'PROVISIONING', 'PROVISIONING', 'ACTIVE', 'RUNNING'); options.ids[0],
'PROVISIONING',
'PROVISIONING',
'ACTIVE',
'RUNNING'
);
return Promise.resolve(startService); return Promise.resolve(startService);
}; };
@ -270,8 +283,13 @@ const restartServices = options => {
// instances transitional 'STOPPING' // instances transitional 'STOPPING'
// service 'ACTIVE' // service 'ACTIVE'
// instances 'RUNNING' // instances 'RUNNING'
const restartService = handleStatusUpdateRequest(options.ids[0], const restartService = handleStatusUpdateRequest(
'RESTARTING', 'STOPPING', 'ACTIVE', 'RUNNING'); options.ids[0],
'RESTARTING',
'STOPPING',
'ACTIVE',
'RUNNING'
);
return Promise.resolve(restartService); return Promise.resolve(restartService);
}; };