diff --git a/packages/cp-gql-mock-server/package.json b/packages/cp-gql-mock-server/package.json index 8462f95c..199b3f0c 100644 --- a/packages/cp-gql-mock-server/package.json +++ b/packages/cp-gql-mock-server/package.json @@ -23,6 +23,9 @@ "joi": "^10.6.0", "joyent-cp-gql-schema": "^1.0.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", "uuid": "^3.1.0" }, diff --git a/packages/cp-gql-mock-server/src/data.json b/packages/cp-gql-mock-server/src/data.json index d9f2cdd2..d3a879e7 100644 --- a/packages/cp-gql-mock-server/src/data.json +++ b/packages/cp-gql-mock-server/src/data.json @@ -66,21 +66,18 @@ "id": "4ee4103e-1a52-4099-a48e-01588f597c70", "slug": "percona", "name": "Percona", - "deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401" - }, - { - "id": "9572d367-c4ae-4fb1-8ad5-f5e3830e7034", - "slug": "primary", - "name": "Primary", - "parent": "4ee4103e-1a52-4099-a48e-01588f597c70", - "deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401" - }, - { - "id": "c8411ef0-ab39-42cb-a704-d20b170eff31", - "slug": "secondaries", - "name": "Secondaries", - "parent": "4ee4103e-1a52-4099-a48e-01588f597c70", - "deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401" + "deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401", + "branches": [{ + "id": "dmklaskdls", + "slug": "percona", + "name": "Percona", + "instances": ["c3ec7633-a02b-4615-86a0-9e6faeaae94b"] + }, { + "id": "dmklaskdls", + "slug": "percona-primary", + "name": "percona-primary", + "instances": ["c2b5fec2-31e2-41a7-b7fc-cd0bb1822e76"] + }] }, { "id": "97c68055-db88-45c9-ad49-f26da4264777", @@ -183,7 +180,7 @@ { "id": "c3ec7633-a02b-4615-86a0-9e6faeaae94b", "name": "percona-primary", - "serviceId": "9572d367-c4ae-4fb1-8ad5-f5e3830e7034", + "serviceId": "4ee4103e-1a52-4099-a48e-01588f597c70", "deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401", "status": "RUNNING", "healthy": "UNHEALTHY" @@ -191,7 +188,7 @@ { "id": "c2b5fec2-31e2-41a7-b7fc-cd0bb1822e76", "name": "percona-secondary", - "serviceId": "c8411ef0-ab39-42cb-a704-d20b170eff31", + "serviceId": "4ee4103e-1a52-4099-a48e-01588f597c70", "deploymentGroupId": "e0ea0c02-55cc-45fe-8064-3e5176a59401", "status": "RUNNING", "healthy": "HEALTHY" diff --git a/packages/cp-gql-mock-server/src/resolvers.js b/packages/cp-gql-mock-server/src/resolvers.js index f877a315..473b1b86 100644 --- a/packages/cp-gql-mock-server/src/resolvers.js +++ b/packages/cp-gql-mock-server/src/resolvers.js @@ -1,6 +1,9 @@ const { v4: uuid } = require('uuid'); const paramCase = require('param-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 { @@ -30,7 +33,17 @@ const getUnfilteredServices = query => { const addNestedResolvers = 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( @@ -39,68 +52,30 @@ const getUnfilteredServices = query => { }; const getServices = query => { + // get all services const services = getUnfilteredServices(query) - .then(services => { - // loop through services and for each of them get all services that's parent id is the service - // 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( - 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()) - ).then(instances => { - return { services, instances }; - }); - }) - ); - }) + // get all instances + .then(services => + Promise.all( + services.map(service => service.instances()) + ).then(instances => ({ + services, + instances + })) + ) .then(({ services, instances }) => { - const activeServices = services.reduce((services, service, index) => { - const active = instances[index].filter( - instance => - instance.status !== 'DELETED' && instance.status !== 'EXITED' - ).length; - if (active) { - services.push(service); - } - return services; - }, []); - const allServices = activeServices.reduce((allServices, service) => { - if (service.parent) { - 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; + // filter all available instances + const availableInstances = flatten( + instances.filter( + ({ status }) => ['DELETED', 'EXITED'].indexOf(status) < 0 + ) + ); + + // get all the serviceIds of the available instances + // and then get the servcies with those ids + return uniq( + availableInstances.map(({ serviceId }) => serviceId) + ).map(serviceId => lfind(services, ['id', serviceId])); }); return Promise.resolve(services); @@ -197,51 +172,79 @@ const updateServiceStatus = (ss, status) => { service.status = status; }); return null; -} +}; -const updateServiceAndInstancesStatus = (serviceId, serviceStatus, instancesStatus) => { +const updateServiceAndInstancesStatus = ( + serviceId, + serviceStatus, + instancesStatus +) => { return Promise.all([ - getServices({ id: serviceId }), - getServices({ parentId: serviceId }) - ]) - .then(services => services.reduce((services, service) => - services.concat(service), [])) + getServices({ id: serviceId }), + getServices({ parentId: serviceId }) + ]) + .then(services => + services.reduce((services, service) => services.concat(service), []) + ) .then(services => { updateServiceStatus(services, serviceStatus); return Promise.all( - services.reduce((instances, service) => - service.instances ? instances.concat(service.instances()) : instances, [])) - .then(instances => updateInstancesStatus(instances.reduce((is, i) => - is.concat(i), []), instancesStatus)) - }) - .then(() => Promise.all([ + services.reduce( + (instances, service) => + service.instances + ? instances.concat(service.instances()) + : instances, + [] + ) + ).then(instances => + updateInstancesStatus( + instances.reduce((is, i) => is.concat(i), []), + instancesStatus + ) + ); + }) + .then(() => + Promise.all([ getUnfilteredServices({ id: 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, - transitionalServiceStatus, transitionalInstancesStatus, - serviceStatus, instancesStatus) => { - // this is what we need to delay - const timeout = setTimeout(() => { - updateServiceAndInstancesStatus(serviceId, - serviceStatus, instancesStatus); - }, 5000); - // this is what we'll need to return - return updateServiceAndInstancesStatus(serviceId, - transitionalServiceStatus, transitionalInstancesStatus); -} +const handleStatusUpdateRequest = ( + serviceId, + transitionalServiceStatus, + transitionalInstancesStatus, + serviceStatus, + instancesStatus +) => { + // this is what we need to delay + const timeout = setTimeout(() => { + updateServiceAndInstancesStatus(serviceId, serviceStatus, instancesStatus); + }, 5000); + // this is what we'll need to return + return updateServiceAndInstancesStatus( + serviceId, + transitionalServiceStatus, + transitionalInstancesStatus + ); +}; const deleteServices = options => { // service transitional 'DELETING' // instances transitional 'STOPPING' // service 'DELETED' // instances 'DELETED' - const deleteService = handleStatusUpdateRequest(options.ids[0], - 'DELETING', 'STOPPING', 'DELETED', 'DELETED'); + const deleteService = handleStatusUpdateRequest( + options.ids[0], + 'DELETING', + 'STOPPING', + 'DELETED', + 'DELETED' + ); return Promise.resolve(deleteService); }; @@ -250,8 +253,13 @@ const stopServices = options => { // instances transitional 'STOPPING' // service 'STOPPED' // instances 'STOPPED' - const stopService = handleStatusUpdateRequest(options.ids[0], - 'STOPPING', 'STOPPING', 'STOPPED', 'STOPPED'); + const stopService = handleStatusUpdateRequest( + options.ids[0], + 'STOPPING', + 'STOPPING', + 'STOPPED', + 'STOPPED' + ); return Promise.resolve(stopService); }; @@ -260,8 +268,13 @@ const startServices = options => { // instances transitional ... // service 'ACTIVE' // instances 'RUNNING' - const startService = handleStatusUpdateRequest(options.ids[0], - 'PROVISIONING', 'PROVISIONING', 'ACTIVE', 'RUNNING'); + const startService = handleStatusUpdateRequest( + options.ids[0], + 'PROVISIONING', + 'PROVISIONING', + 'ACTIVE', + 'RUNNING' + ); return Promise.resolve(startService); }; @@ -270,8 +283,13 @@ const restartServices = options => { // instances transitional 'STOPPING' // service 'ACTIVE' // instances 'RUNNING' - const restartService = handleStatusUpdateRequest(options.ids[0], - 'RESTARTING', 'STOPPING', 'ACTIVE', 'RUNNING'); + const restartService = handleStatusUpdateRequest( + options.ids[0], + 'RESTARTING', + 'STOPPING', + 'ACTIVE', + 'RUNNING' + ); return Promise.resolve(restartService); };