From b6c61390231b9a529d06bf97c33b8122f3a40fb4 Mon Sep 17 00:00:00 2001 From: geek Date: Tue, 30 May 2017 17:08:06 -0500 Subject: [PATCH] chore(portal-data): add manifest and versions support --- packages/portal-data/lib/index.js | 120 +++++++++-- packages/portal-data/lib/transform.js | 35 +++ packages/portal-data/test/index.js | 300 ++++++++++++++++++++++++-- yarn.lock | 48 +---- 4 files changed, 426 insertions(+), 77 deletions(-) diff --git a/packages/portal-data/lib/index.js b/packages/portal-data/lib/index.js index 84f0aa6e..c6c86c3c 100644 --- a/packages/portal-data/lib/index.js +++ b/packages/portal-data/lib/index.js @@ -68,7 +68,7 @@ module.exports = class Data { this.getDatacenter({ id: portal.datacenter_id }, next); }, (next) => { - this.getDeploymentGroups(portal.deployment_group_ids, next); + this.getDeploymentGroups({ ids: portal.deployment_group_ids }, next); } ] }, (err, results) => { @@ -112,7 +112,7 @@ module.exports = class Data { // deployment_groups - createDeploymentGroup ({ name }, cb) { + createDeploymentGroup (clientDeploymentGroup, cb) { // trigger deployment // create deployment queue (we should think about what is a deployment queue) // create the ConvergencePlans @@ -120,12 +120,14 @@ module.exports = class Data { // create a Version // update the DeploymentGroup - this._db.deployment_groups.insert({ name }, (err, key) => { + const deploymentGroup = Transform.toDeploymentGroup(clientDeploymentGroup); + this._db.deployment_groups.insert(deploymentGroup, (err, key) => { if (err) { return cb(err); } - cb(null, Transform.fromDeploymentGroup({ id: key, name })); + deploymentGroup.id = key; + cb(null, Transform.fromDeploymentGroup(deploymentGroup)); }); } @@ -139,19 +141,29 @@ module.exports = class Data { }); } - getDeploymentGroups (ids, cb) { - this._db.deployment_groups.get(ids, (err, deploymentGroups) => { + getDeploymentGroups ({ ids, name, slug }, cb) { + const finish = (err, deploymentGroups) => { if (err) { return cb(err); } deploymentGroups = deploymentGroups || []; cb(null, deploymentGroups.map(Transform.fromDeploymentGroup)); - }); + }; + + if (ids) { + return this._db.deployment_groups.get(ids, finish); + } + + if (name) { + return this._db.deployment_groups.query({ name }, finish); + } + + this._db.deployment_groups.query({ slug }, finish); } - getDeploymentGroup (id, cb) { - this._db.deployment_groups.single({ id }, (err, deploymentGroup) => { + getDeploymentGroup (query, cb) { + this._db.deployment_groups.single(query, (err, deploymentGroup) => { if (err) { return cb(err); } @@ -164,24 +176,102 @@ module.exports = class Data { // versions createVersion (clientVersion, cb) { - const version = Transform.toVersion(clientVersion); - this._db.versions.insert(version, (err, key) => { + Hoek.assert(clientVersion && clientVersion.manifestId, 'manifestId is required'); + + // go get the manifest to find the deployment group id so we can update it + this.getManifest({ id: clientVersion.manifestId }, (err, manifest) => { + if (err) { + return cb(err); + } + + if (!manifest) { + return cb(new Error('manifest not found for version')); + } + + const version = Transform.toVersion(clientVersion); + this._db.versions.insert(version, (err, key) => { + if (err) { + return cb(err); + } + + this._db.deployment_groups.update(manifest.deploymentGroupId, { history_version_ids: this._db.append(key) }, (err) => { + if (err) { + return cb(err); + } + + version.id = key; + cb(null, Transform.fromVersion(version)); + }); + }); + }); + } + + getVersion ({ id, manifestId }, cb) { + const query = id ? { id } : { manifest_id: manifestId }; + this._db.versions.single(query, (err, version) => { if (err) { return cb(err); } - version.id = key; cb(null, Transform.fromVersion(version)); }); } - getVersion (id, cb) { - this._db.versions.single({ id }, (err, version) => { + getVersions ({ manifestId, deploymentGroupId }, cb) { + const finish = (err, versions) => { if (err) { return cb(err); } - cb(null, Transform.fromVersion(version)); + versions = versions || []; + cb(null, versions.map(Transform.fromVersion)); + }; + + if (manifestId) { + return this._db.versions.query({ manifest_id: manifestId }, finish); + } + + this.getDeploymentGroup({ id: deploymentGroupId }, (err, deploymentGroup) => { + if (err) { + return finish(err); + } + + this._db.versions.get(deploymentGroup.history, finish); + }); + } + + + // manifests + + provisionManifest (clientManifest, cb) { + this._db.manifests.insert(Transform.toManifest(clientManifest), (err, key) => { + if (err) { + return cb(err); + } + + this.getManifest({ id: key }, cb); + }); + } + + getManifest ({ id }, cb) { + this._db.manifests.single({ id }, (err, manifest) => { + if (err) { + return cb(err); + } + + cb(null, Transform.fromManifest(manifest || {})); + }); + } + + getManifests ({ type, deploymentGroupId }, cb) { + const query = type ? { type } : { deployment_group_id: deploymentGroupId }; + this._db.manifests.query(query, (err, manifests) => { + if (err) { + return cb(err); + } + + manifests = manifests || []; + cb(null, manifests.map(Transform.fromManifest)); }); } }; diff --git a/packages/portal-data/lib/transform.js b/packages/portal-data/lib/transform.js index 37b43b43..3e344247 100644 --- a/packages/portal-data/lib/transform.js +++ b/packages/portal-data/lib/transform.js @@ -37,6 +37,16 @@ exports.fromDeploymentGroup = function (deploymentGroup, services) { }; }; +exports.toDeploymentGroup = function ({ name }) { + return { + name, + slug: '', + services: [], + version_id: '', + history_version_ids: [] + }; +}; + exports.fromService = function (service) { @@ -92,3 +102,28 @@ exports.fromPlan = function (plan) { actions: plan.actions }; }; + + +exports.toManifest = function (clientManifest) { + return { + id: clientManifest.id, + deployment_group_id: clientManifest.deploymentGroupId, + created: clientManifest.created || Date.now(), + type: clientManifest.type, + format: clientManifest.format, + raw: clientManifest.raw, + json: clientManifest.json + }; +}; + +exports.fromManifest = function (manifest) { + return { + id: manifest.id, + deploymentGroupId: manifest.deployment_group_id, + created: manifest.created, + type: manifest.type, + format: manifest.format, + raw: manifest.raw, + json: manifest.json + }; +}; diff --git a/packages/portal-data/test/index.js b/packages/portal-data/test/index.js index 5b7016c4..a16e7346 100644 --- a/packages/portal-data/test/index.js +++ b/packages/portal-data/test/index.js @@ -101,7 +101,7 @@ describe('deployment groups', () => { data.createDeploymentGroup({ name }, (err, createdDeploymentGroup) => { expect(err).to.not.exist(); expect(createdDeploymentGroup.id).to.exist(); - data.getDeploymentGroup(createdDeploymentGroup.id, (err, deploymentGroup) => { + data.getDeploymentGroup({ id: createdDeploymentGroup.id }, (err, deploymentGroup) => { expect(err).to.not.exist(); expect(deploymentGroup).to.equal(createdDeploymentGroup); done(); @@ -125,10 +125,14 @@ describe('deployment groups', () => { expect(err).to.not.exist(); expect(createdDeploymentGroup1.id).to.exist(); - data.getDeploymentGroups([createdDeploymentGroup1.id, createdDeploymentGroup2.id], (err, deploymentGroups) => { + data.getDeploymentGroups({ ids: [createdDeploymentGroup1.id, createdDeploymentGroup2.id] }, (err, deploymentGroups) => { expect(err).to.not.exist(); expect(deploymentGroups.length).to.equal(2); - done(); + data.getDeploymentGroups({ name }, (err, deploymentGroups) => { + expect(err).to.not.exist(); + expect(deploymentGroups.length).to.equal(2); + done(); + }); }); }); }); @@ -235,27 +239,277 @@ describe('versions', () => { const data = new PortalData(internals.options); data.connect((err) => { expect(err).to.not.exist(); - const clientVersion = { - manifestId: 'something', - scales: [{ - serviceName: 'consul', - replicas: 3 - }], - plan: { - running: true, - actions: [{ - type: 'start', - service: 'consul', - machines: ['vmid', 'vmid'] - }] - } - }; - - data.createVersion(clientVersion, (err, result) => { + data.createDeploymentGroup({ name: 'something' }, (err, deploymentGroup) => { expect(err).to.not.exist(); - expect(result.id).to.exist(); - expect(result.scales).to.equal(clientVersion.scales); - done(); + const clientManifest = { + deploymentGroupId: deploymentGroup.id, + type: 'compose', + format: 'yml', + raw: 'docker compose raw contents', + json: { services: [] } + }; + + data.provisionManifest(clientManifest, (err, manifest) => { + expect(err).to.not.exist(); + + const clientVersion = { + manifestId: manifest.id, + scales: [{ + serviceName: 'consul', + replicas: 3 + }], + plan: { + running: true, + actions: [{ + type: 'start', + service: 'consul', + machines: ['vmid', 'vmid'] + }] + } + }; + + data.createVersion(clientVersion, (err, result) => { + expect(err).to.not.exist(); + expect(result.id).to.exist(); + expect(result.scales).to.equal(clientVersion.scales); + done(); + }); + }); + }); + }); + }); + }); + + describe('getVersion()', () => { + it('retrieves a version record with an id or manifestId', (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: 'docker compose raw contents', + json: { services: [] } + }; + + data.provisionManifest(clientManifest, (err, manifest) => { + expect(err).to.not.exist(); + + const clientVersion = { + manifestId: manifest.id, + scales: [{ + serviceName: 'consul', + replicas: 3 + }], + plan: { + running: true, + actions: [{ + type: 'start', + service: 'consul', + machines: ['vmid', 'vmid'] + }] + } + }; + + data.createVersion(clientVersion, (err, result) => { + expect(err).to.not.exist(); + expect(result.id).to.exist(); + expect(result.scales).to.equal(clientVersion.scales); + data.getVersion({ id: result.id }, (err, retrievedVersion1) => { + expect(err).to.not.exist(); + expect(retrievedVersion1.id).to.equal(result.id); + data.getVersion({ manifestId: result.manifestId }, (err, retrievedVersion2) => { + expect(err).to.not.exist(); + expect(retrievedVersion1.id).to.equal(retrievedVersion2.id); + done(); + }); + }); + }); + }); + }); + }); + }); + }); + + describe('getVersions()', () => { + it('retrieve versions records with a manifestId', (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: 'docker compose raw contents', + json: { services: [] } + }; + + data.provisionManifest(clientManifest, (err, manifest) => { + expect(err).to.not.exist(); + + const clientVersion = { + manifestId: manifest.id, + scales: [{ + serviceName: 'consul', + replicas: 3 + }], + plan: { + running: true, + actions: [{ + type: 'start', + service: 'consul', + machines: ['vmid', 'vmid'] + }] + } + }; + + data.createVersion(clientVersion, (err, result) => { + expect(err).to.not.exist(); + expect(result.id).to.exist(); + expect(result.scales).to.equal(clientVersion.scales); + data.getVersions({ manifestId: clientVersion.manifestId }, (err, versions) => { + expect(err).to.not.exist(); + expect(versions.length).to.equal(1); + done(); + }); + }); + }); + }); + }); + }); + + it('retrieve versions records with a deployment group id', (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: 'docker compose raw contents', + json: { services: [] } + }; + + data.provisionManifest(clientManifest, (err, manifest) => { + expect(err).to.not.exist(); + + const clientVersion = { + manifestId: manifest.id, + scales: [{ + serviceName: 'consul', + replicas: 3 + }], + plan: { + running: true, + actions: [{ + type: 'start', + service: 'consul', + machines: ['vmid', 'vmid'] + }] + } + }; + + data.createVersion(clientVersion, (err, version) => { + expect(err).to.not.exist(); + + data.getVersions({ deploymentGroupId: deploymentGroup.id }, (err, versions) => { + expect(err).to.not.exist(); + expect(versions.length).to.equal(1); + expect(versions[0].id).to.equal(version.id); + done(); + }); + }); + }); + }); + }); + }); + }); +}); + + +describe('manifests', () => { + describe('provisionManifest()', () => { + it('creates a new manifest record in the manifests table', (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: 'docker compose raw contents', + json: { services: [] } + }; + + data.provisionManifest(clientManifest, (err, result) => { + expect(err).to.not.exist(); + expect(result.id).to.exist(); + expect(result.created).to.exist(); + done(); + }); + }); + }); + }); + }); + + describe('getManifests()', () => { + it('retrieves manifests using from a manifest type', (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: 'docker compose raw contents', + json: { services: [] } + }; + + data.provisionManifest(clientManifest, (err, result) => { + expect(err).to.not.exist(); + data.getManifests({ type: clientManifest.type }, (err, manifests) => { + expect(err).to.not.exist(); + expect(manifests.length).to.equal(1); + done(); + }); + }); + }); + }); + }); + + it('retrieves manifests using from a deployment group id', (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: 'docker compose raw contents', + json: { services: [] } + }; + + data.provisionManifest(clientManifest, (err, result) => { + expect(err).to.not.exist(); + data.getManifests({ type: clientManifest.type }, (err, manifests) => { + expect(err).to.not.exist(); + expect(manifests.length).to.equal(1); + done(); + }); + }); }); }); }); diff --git a/yarn.lock b/yarn.lock index 9147da0b..514f533c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -64,14 +64,14 @@ ansi-escapes@^1.1.0, ansi-escapes@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" -ansi-regex@*, ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - ansi-regex@^0.2.0, ansi-regex@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9" +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + ansi-styles@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de" @@ -1074,7 +1074,7 @@ debug@^2.1.1, debug@^2.2.0: dependencies: ms "2.0.0" -debuglog@*, debuglog@^1.0.1: +debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -1975,11 +1975,7 @@ hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" -hosted-git-info@^2.1.4, hosted-git-info@^2.1.5: - version "2.4.2" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67" - -hosted-git-info@~2.1.5: +hosted-git-info@^2.1.4, hosted-git-info@^2.1.5, hosted-git-info@~2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.1.5.tgz#0ba81d90da2e25ab34a332e6ec77936e1598118b" @@ -2012,7 +2008,7 @@ ignore@^3.2.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" -imurmurhash@*, imurmurhash@^0.1.4: +imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -2554,10 +2550,6 @@ lockfile@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.3.tgz#2638fc39a0331e9cac1a04b71799931c9c50df79" -lodash._baseindexof@*: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c" - lodash._baseuniq@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" @@ -2565,28 +2557,10 @@ lodash._baseuniq@~4.6.0: lodash._createset "~4.0.0" lodash._root "~3.0.0" -lodash._bindcallback@*: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" - -lodash._cacheindexof@*: - version "3.0.2" - resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92" - -lodash._createcache@*: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093" - dependencies: - lodash._getnative "^3.0.0" - lodash._createset@~4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" -lodash._getnative@*, lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - lodash._reinterpolate@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -2659,10 +2633,6 @@ lodash.mergewith@^4.3.1: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" -lodash.restparam@*: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -3695,7 +3665,7 @@ readable-stream@~2.1.5: string_decoder "~0.10.x" util-deprecate "~1.0.1" -readdir-scoped-modules@*, readdir-scoped-modules@^1.0.0: +readdir-scoped-modules@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747" dependencies: @@ -4781,7 +4751,7 @@ uuid@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" -validate-npm-package-license@*, validate-npm-package-license@^3.0.1: +validate-npm-package-license@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" dependencies: