diff --git a/portal-api/lib/models/graphql.js b/portal-api/lib/models/graphql.js index 097e00ff..12b168a6 100644 --- a/portal-api/lib/models/graphql.js +++ b/portal-api/lib/models/graphql.js @@ -1,155 +1,47 @@ 'use strict'; +const Fs = require('fs'); +const Path = require('path'); const Graphql = require('graphql'); const internals = { - schema: ` - scalar Object - scalar Date - - type Activity { - date: Date! - type: String! - meta: Object - } - - type Datacenter { - name: String! - url: String! - } - - input DeploymentCreate { - name: String! - datacenter: String! - } - - input DeploymentUpdate { - id: ID! - name: String! - datacenter: String! - } - - type Deployment { - id: ID! - name: String! - datacenter: String! - } - - type Manifest { - revision: Int! - file: Object! - } - - input ManifestCreate { - file: Object! - } - - type Metric { - service: String! - cpu: Float! - memory: Float! - network: Float! - } - - type Service { - name: String! - count: Int! - } - - input ServiceUpdate { - name: String! - count: Int! - } - - type Mutation { - createDeployment(deployment: DeploymentCreate!): Deployment! - deleteDeployment(deploymentId: ID!): String - updateDeployment(deployment: DeploymentUpdate!): Deployment! - createManifest(deploymentId: ID!, manifest: ManifestCreate!): Manifest! - updateService(deploymentId: ID!, service: ServiceUpdate!): Service! - } - - type Query { - getActivities: [Activity] - getDatacenters: [Datacenter] - getDeployment(id: ID!): Deployment - getDeployments: [Deployment] - getManifest(deploymentId: ID!, revision: Int!): Manifest - getMetrics(deploymentId: ID!): [Metric] - getServices(deploymentId: ID!): [Service] - } - ` + schema: Fs.readFileSync(Path.join(__dirname, 'schema.gql')).toString() }; exports.options = (data) => { const schema = Graphql.buildSchema(internals.schema); - const createDeployment = function (args) { - return data.createDeployment(args.deployment); + const getPortal = function (args, request) { + }; - const deleteDeployment = function (args) { - return data.deleteDeployment(args.deploymentId); + const getDeploymentGroups = function (args, request) { + }; - const updateDeployment = function (args) { - return data.updateDeployment(args.deployment); + const getDeploymentGroup = function (args, request) { + }; - const createManifest = function (args) { - return data.createManifest(args.deploymentId, args.manifest); + const getServiceScales = function (args, request) { + }; - const updateService = function (args) { - return data.updateService(args.deploymentId, args.service); - }; + const getServiceScale = function (args, request) { - const getActivities = function () { - return data.getActivities(); - }; - - const getDatacenters = function () { - return data.getDatacenters(); - }; - - const getDeployment = function (args) { - return data.getDeployment(args.id); - }; - - const getDeployments = function () { - return data.getDeployments(); - }; - - const getManifest = function (args) { - return data.getManifest(args.deploymentId, args.revision); - }; - - const getMetrics = function (args) { - return data.getMetrics(args.deploymentId); - }; - - const getServices = function (args) { - return data.v(args.deploymentId); }; return { schema, endpointURL: '/graphql', rootValue: { - createDeployment, - deleteDeployment, - updateDeployment, - createManifest, - updateService, - getActivities, - getDatacenters, - getDeployment, - getDeployments, - getManifest, - getMetrics, - getServices + portal: getPortal, + deploymentGroups: getDeploymentGroups, + deploymentGroup: getDeploymentGroup, + serviceScales: getServiceScales, + serviceScale: getServiceScale } }; }; diff --git a/portal-api/lib/models/schema.gql b/portal-api/lib/models/schema.gql new file mode 100644 index 00000000..1ff50db8 --- /dev/null +++ b/portal-api/lib/models/schema.gql @@ -0,0 +1,204 @@ + +scalar Date +scalar Object + +type Portal { + username: String! + datacenter: Datacenter! + deploymentGroups: [DeploymentGroup]! +} + +type DeploymentGroup { + uuid: ID! + name: String! + slug: String! + services: [Service]! + version: Version! + history: [Version]! +} + +type ServiceScale { + uuid: ID! + serviceName: String! + replicas: Int! +} + +enum ConvergenceActionType { + NOOP + CREATE + RECREATE + START + } + +type ConvergenceAction { + uuid: String! + type: ConvergenceActionType! + service: String! # service name + machines: [String]! # instance machine ids +} + +type StateConvergencePlan { + uuid: String! + running: Boolean! + actions: [ConvergenceAction]! +} + +type Version { + created: Date! # Either Int or define scalar + manifest: Manifest! + scale: [ServiceScale]! + plan: StateConvergencePlan +} + +enum ManifestType { + COMPOSE + MARIPOSA +} + +enum ManifestFormat { + JSON + YAML +} + +type Manifest { + uuid: String! + created: Date! + type: ManifestType! + format: ManifestFormat! + raw: String! + obj: Object! +} + +# immutable +type Service { + uuid: String! # unique id for db row + hash: String! # unique id for version of service + name: String! # human readable name + slug: String! + instances: [Instance]! + # metrics: [MetricType]! + currentMetrics: [CurrentMetric]! + connections: [String!] # list of serviceUuids + parent: ID # parent service uuid + package: Package! # we don't have this in current mock data +} + +# for metrics max / min (I guess) +type Package { + uuid: ID! + name: String! + type: String! + memory: Float! + disk: Float! + swap: Float! + lwps: Int! + vcpus: Int! + version: String! + group: String! +} + +enum InstanceStatus { + CREATED + RESTARTING + RUNNING + PAUSED + EXITED + DELETED +} + +type Instance { + uuid: String! + name: String! + machineId: String! + status: InstanceStatus! + # metrics: [InstanceMetric]! +} + +type Datacenter { + uuid: String! + # name: String! # Do we have 'official' human readable names? + region: String! +} + +type InstanceMetric { + type: MetricType! + data: [MetricData]! +} + +type CurrentMetric { + name: String! + value: Float! + measurement: String! +} + +type MetricType { + uuid: String! + name: String! + id: String! +} + +type MetricData { + timestamp: Int! + value: Float! +} + +# Need to review queries +type Query { + portal: Portal + deploymentGroups: [DeploymentGroup] + deploymentGroup(uuid: String, slug: String): DeploymentGroup + services(deploymentGroupUuid: String, deploymentGroupSlug: String): [Service] + service(uuid: String, slug: String): Service + instances(serviceUuid: String, serviceSlug: String): [Instance] + instance(uuid: String, machineId: String): Instance + metricTypes: [MetricType] + metricData(instanceUuid: String!, metricType: String!, from: Date!, to: Date!): [InstanceMetric]! + package: Package + datacenters: [Datacenter] + # tmp test + instanceMetric: InstanceMetric! +} + +# we probably wont use some of these queries or arguments +# but this way we expose the entire db through gql +type Query { + portal: Portal + deploymentGroups(name: String, slug: String): [DeploymentGroup] + deploymentGroup(uuid: ID, name: String, slug: String): DeploymentGroup + serviceScales(serviceName: String, versionUuid: ID): [ServiceScale] + serviceScale(uuid: ID!): ServiceScale + convergenceActions(type: ConvergenceActionType, service: String, versionUuid: ID): [ConvergenceAction] + convergenceAction(uuid: ID!): ConvergenceAction + stateConvergencePlans(running: Boolean, versionUuid: ID): [StateConvergencePlan] + stateConvergencePlan(uuid: ID!): StateConvergencePlan + versions(manifestUuid: ID, deploymentGroupUuid: ID): [Version] + version(uuid: ID, manifestUuid: ID): Version + manifests(type: String, deploymentGroupUuid: ID): [Manifest] + manifest(uuid: ID!): Manifest + services(name: String, slug: String, parentUuid: ID, deploymentGroupUuid: ID, deploymentGroupSlug: String): [Service] + service(uuid: ID, hash: ID): Service + packages(name: String, type: String, memory: Int, disk: Int, swap: Int, lwps: Int, vcpus: Int, version: String, group: String): [Package] + package(uuid: ID!): Package + instances(name: String!, machineId: ID, status: InstanceStatus, serviceUuid: ID, serviceSlug: String, deploymentGroupUuid: ID, deploymentGroupSlug: String): [Instance] + instance(uuid: ID!): Instance + datacenter(uuid: ID, region: String): Datacenter +} + +type Mutation { + createDeploymentGroup(name: String!) : DeploymentGroup + updateDeploymentGroup(uuid: ID!, name: String!) : DeploymentGroup + + provisionManifest(deploymentGroupUuid: ID!, type: ManifestType!, format: ManifestFormat!, raw: String!) : Version + scale(service: ID!, replicas: Int!) : Version + + stopServices(uuids: [ID]!) : [Service] + startServices(uuids: [ID]!) : [Service] + restartServices(uuids: [ID]!) : [Service] + deleteServices(uuids: [ID]!) : [Service] + + stopInstances(uuids: [ID]!) : [Instance] + startInstances(uuids: [ID]!) : [Instance] + restartInstances(uuids: [ID]!) : [Instance] + + # reprovision() ??? +} diff --git a/portal-api/test/index.js b/portal-api/test/index.js index ec91acd5..cf3f4b78 100644 --- a/portal-api/test/index.js +++ b/portal-api/test/index.js @@ -341,19 +341,19 @@ describe('services', () => { }); -describe.skip('graphql', () => { +describe('graphql', () => { it('route exists', (done) => { const server = new Hapi.Server(); server.connection(); server.register(internals.register, (err) => { expect(err).to.not.exist(); - const url = '/graphql?query=%7B%0A%20%20getDeployment(id%3A%201)%20%7B%0A%20%20%20%20id%0A%20%20%7D%0A%7D'; + const url = '/graphql?query=%7B%0A%20%20deploymentGroups(name%3A%22hi%22%2C%20slug%3A%20%22hi%22)%20%7B%0A%20%20%20%20id%0A%20%20%7D%0A%7D'; server.inject({ method: 'GET', url }, (res) => { expect(res.statusCode).to.equal(200); const result = JSON.parse(res.result); expect(result.data).to.exist(); - expect(result.data.getDeployment).to.exist(); + expect(result.data.deploymentGroups).to.be.null(); done(); }); });