From 953441ff2b8b5543d0fd7ed0ec5572cc09284f3f Mon Sep 17 00:00:00 2001 From: Ryan Graham Date: Wed, 13 May 2020 09:55:35 -0400 Subject: [PATCH 1/3] added a db call to the liveness probe --- app/routes/kube/kube.js | 8 ++++++-- kubernetes/razeedash-api/resource.yaml | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/routes/kube/kube.js b/app/routes/kube/kube.js index 8ab592d1b..9391336c8 100644 --- a/app/routes/kube/kube.js +++ b/app/routes/kube/kube.js @@ -15,11 +15,15 @@ */ const express = require('express'); +const asyncHandler = require('express-async-handler'); const router = express.Router(); // /kube/liveness -const kube = router.get('/liveness', (req, res) => { +const kube = router.get('/liveness', asyncHandler(async(req, res) => { + // does a db call to make sure we didnt disconnect + await require('../../apollo/models').models.Cluster.find({}, { _id:1 }, { limit:1 }); + return res.sendStatus(200); -}); +})); module.exports = kube; diff --git a/kubernetes/razeedash-api/resource.yaml b/kubernetes/razeedash-api/resource.yaml index 31c41c876..5869a7bcb 100644 --- a/kubernetes/razeedash-api/resource.yaml +++ b/kubernetes/razeedash-api/resource.yaml @@ -115,7 +115,7 @@ items: path: /api/kube/liveness port: 3333 initialDelaySeconds: 5 - periodSeconds: 10 + periodSeconds: 20 timeoutSeconds: 2 resources: requests: From 581b8bf024130ad0706c7004b86aa7cb6719a89d Mon Sep 17 00:00:00 2001 From: YING WANG <42584020+yingwang-us@users.noreply.github.com> Date: Thu, 21 May 2020 11:28:29 -0400 Subject: [PATCH 2/3] add proper apollo errors (#341) --- app/apollo/resolvers/channel.js | 21 +++++++++++---------- app/apollo/resolvers/common.js | 17 +++++++++++++---- app/apollo/resolvers/subscription.js | 14 +++++++------- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/app/apollo/resolvers/channel.js b/app/apollo/resolvers/channel.js index a1f136240..131ecc0ec 100644 --- a/app/apollo/resolvers/channel.js +++ b/app/apollo/resolvers/channel.js @@ -17,9 +17,10 @@ const _ = require('lodash'); const { v4: UUID } = require('uuid'); const crypto = require('crypto'); +const { UserInputError, ValidationError } = require('apollo-server'); const { ACTIONS, TYPES } = require('../models/const'); -const { whoIs, validAuth } = require ('./common'); +const { whoIs, validAuth, NotFoundError} = require ('./common'); const { encryptOrgData, decryptOrgData} = require('../../utils/orgs'); @@ -65,18 +66,18 @@ const channelResolvers = { const channel = await models.Channel.findOne({ uuid: channel_uuid, org_id }); if(!channel){ - throw `Could not find the channel with uuid "${channel_uuid}"`; + throw new NotFoundError(`Could not find the channel with uuid ${channel_uuid}.`); } const versionObj = channel.versions.find(v => v.uuid === version_uuid); if (!versionObj) { - throw `versionObj "${version_uuid}" is not found for ${channel.name}:${channel.uuid}.`; + throw NotFoundError(`versionObj "${version_uuid}" is not found for ${channel.name}:${channel.uuid}`); } if (versionObj.location === 'mongo') { const deployableVersionObj = await models.DeployableVersion.findOne({org_id, channel_id: channel_uuid, uuid: version_uuid }); if (!deployableVersionObj) { - throw `DeployableVersion is not found for ${channel.name}:${channel.uuid}/${versionObj.name}:${versionObj.uuid}.`; + throw new NotFoundError(`DeployableVersion is not found for ${channel.name}:${channel.uuid}/${versionObj.name}:${versionObj.uuid}.`); } deployableVersionObj.content = await decryptOrgData(orgKey, deployableVersionObj.content); return deployableVersionObj; @@ -121,7 +122,7 @@ const channelResolvers = { try{ const channel = await models.Channel.findOne({ uuid, org_id }); if(!channel){ - throw `channel uuid "${uuid}" not found`; + throw new NotFoundError(`channel uuid "${uuid}" not found`); } await models.Channel.updateOne({ org_id, uuid }, { $set: { name } }); @@ -147,7 +148,7 @@ const channelResolvers = { const orgKey = _.first(org.orgKeys); if(!name){ - throw 'A name was not included'; + throw new UserInputError('A name was not included'); } if(!type){ throw 'A "type" of application/json or application/yaml must be included'; @@ -158,7 +159,7 @@ const channelResolvers = { const channel = await models.Channel.findOne({ uuid: channel_uuid, org_id }); if(!channel){ - throw `channel uuid "${channel_uuid}" not found`; + throw new NotFoundError(`channel uuid "${channel_uuid}" not found`); } const versions = await models.DeployableVersion.find({ org_id, channel_id: channel_uuid }); @@ -167,7 +168,7 @@ const channelResolvers = { }); if(versionNameExists) { - throw `The version name ${name} already exists`; + throw new ValidationError(`The version name ${name} already exists`); } const iv = crypto.randomBytes(16); @@ -253,14 +254,14 @@ const channelResolvers = { try{ const channel = await models.Channel.findOne({ uuid, org_id }); if(!channel){ - throw `channel uuid "${uuid}" not found`; + throw new NotFoundError(`channel uuid "${uuid}" not found`); } const channel_uuid = channel.uuid; const subCount = await models.Subscription.count({ org_id, channel_uuid }); if(subCount > 0){ - throw `${subCount} subscriptions depend on this channel. Please update/remove them before removing this channel.`; + throw new ValidationError(`${subCount} subscriptions depend on this channel. Please update/remove them before removing this channel.`); } await models.Channel.deleteOne({ org_id, uuid }); diff --git a/app/apollo/resolvers/common.js b/app/apollo/resolvers/common.js index 17e8a9131..8230edb6c 100644 --- a/app/apollo/resolvers/common.js +++ b/app/apollo/resolvers/common.js @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const { AuthenticationError } = require('apollo-server'); +const { ForbiddenError, ApolloError } = require('apollo-server'); + const whoIs = me => { if (me === null || me === undefined) return 'null'; @@ -27,12 +28,20 @@ const whoIs = me => { const validAuth = async (me, org_id, action, type, queryName, context) => { const {req_id, models, logger} = context; if (me === null || !(await models.User.isAuthorized(me, org_id, action, type, null, context))) { - logger.error({req_id, me: whoIs(me), org_id, action, type}, `AuthenticationError - ${queryName}`); - throw new AuthenticationError( + logger.error({req_id, me: whoIs(me), org_id, action, type}, `ForbiddenError - ${queryName}`); + throw new ForbiddenError( `You are not allowed to ${action} on ${type} under organization ${org_id} for the query ${queryName}.`, ); } }; -module.exports = { whoIs, validAuth }; +// Not Found Error when look up db +class NotFoundError extends ApolloError { + constructor(message) { + super(message, 'NOT_FOUND'); + Object.defineProperty(this, 'name', { value: 'NotFoundError' }); + } +} + +module.exports = { whoIs, validAuth, NotFoundError }; diff --git a/app/apollo/resolvers/subscription.js b/app/apollo/resolvers/subscription.js index 0387828f8..5c0e59c40 100644 --- a/app/apollo/resolvers/subscription.js +++ b/app/apollo/resolvers/subscription.js @@ -19,7 +19,7 @@ const { v4: UUID } = require('uuid'); const { pub } = require('../../utils/pubsub'); const { ACTIONS, TYPES } = require('../models/const'); -const { whoIs, validAuth } = require ('./common'); +const { whoIs, validAuth, NotFoundError} = require ('./common'); const resourceResolvers = { @@ -77,7 +77,7 @@ const resourceResolvers = { // loads the channel var channel = await models.Channel.findOne({ org_id, uuid: channel_uuid }); if(!channel){ - throw `channel uuid "${channel_uuid}" not found`; + throw new NotFoundError(`channel uuid "${channel_uuid}" not found`); } // loads the version @@ -85,7 +85,7 @@ const resourceResolvers = { return (version.uuid == version_uuid); }); if(!version){ - throw `version uuid "${version_uuid}" not found`; + throw new NotFoundError(`version uuid "${version_uuid}" not found`); } await models.Subscription.create({ @@ -118,13 +118,13 @@ const resourceResolvers = { try{ var subscription = await models.Subscription.findOne({ org_id, uuid }); if(!subscription){ - throw `subscription { uuid: "${uuid}", org_id:${org_id} } not found`; + throw new NotFoundError(`subscription { uuid: "${uuid}", org_id:${org_id} } not found`); } // loads the channel var channel = await models.Channel.findOne({ org_id, uuid: channel_uuid }); if(!channel){ - throw `channel uuid "${channel_uuid}" not found`; + throw new NotFoundError(`channel uuid "${channel_uuid}" not found`); } // loads the version @@ -132,7 +132,7 @@ const resourceResolvers = { return (version.uuid == version_uuid); }); if(!version){ - throw `version uuid "${version_uuid}" not found`; + throw new NotFoundError(`version uuid "${version_uuid}" not found`); } var sets = { @@ -168,7 +168,7 @@ const resourceResolvers = { try{ var subscription = await models.Subscription.findOne({ org_id, uuid }); if(!subscription){ - throw `subscription uuid "${uuid}" not found`; + throw new NotFoundError(`subscription uuid "${uuid}" not found`); } await subscription.deleteOne(); From baad123d1049bedd7a909b056ba9f033f402cb36 Mon Sep 17 00:00:00 2001 From: YING WANG <42584020+yingwang-us@users.noreply.github.com> Date: Thu, 21 May 2020 19:15:38 -0400 Subject: [PATCH 3/3] fixes (#353) * fixes * update --- app/apollo/models/channel.schema.js | 4 ++++ app/apollo/resolvers/channel.js | 12 ++++++++---- app/apollo/schema/channel.js | 3 ++- app/routes/index.js | 12 ++++++++++++ 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/app/apollo/models/channel.schema.js b/app/apollo/models/channel.schema.js index f7ebf53d9..1ef4acf16 100644 --- a/app/apollo/models/channel.schema.js +++ b/app/apollo/models/channel.schema.js @@ -47,6 +47,10 @@ const ChannelSchema = new mongoose.Schema({ location: { type: String, }, + created: { + type: Date, + default: Date.now, + } } ], }); diff --git a/app/apollo/resolvers/channel.js b/app/apollo/resolvers/channel.js index 131ecc0ec..2dcad5e26 100644 --- a/app/apollo/resolvers/channel.js +++ b/app/apollo/resolvers/channel.js @@ -98,9 +98,13 @@ const channelResolvers = { logger.debug({ req_id, user: whoIs(me), org_id, name }, `${queryName} enter`); await validAuth(me, org_id, ACTIONS.MANAGE, TYPES.CHANNEL, queryName, context); - try{ + try { + // might not necessary with uunique index. Worth to check to return error better. + const channel = await models.Channel.findOne({ name, org_id }); + if(channel){ + throw new ValidationError(`The channel name ${name} already exists.`); + } const uuid = UUID(); - await models.Channel.create({ _id: UUID(), uuid, org_id, name, versions: [], @@ -228,13 +232,13 @@ const channelResolvers = { type, }; + const dObj = await models.DeployableVersion.create(deployableVersionObj); const versionObj = { uuid: deployableVersionObj.uuid, name, description, location, + created: dObj.created }; - await models.DeployableVersion.create(deployableVersionObj); - await models.Channel.updateOne( { org_id, uuid: channel.uuid }, { $push: { versions: versionObj } } diff --git a/app/apollo/schema/channel.js b/app/apollo/schema/channel.js index d07d8883b..02482cca3 100644 --- a/app/apollo/schema/channel.js +++ b/app/apollo/schema/channel.js @@ -22,7 +22,8 @@ const channelSchema = gql` uuid: String! name: String! description: String - location: String! + location: String! + created: Date } type Channel { uuid: String! diff --git a/app/routes/index.js b/app/routes/index.js index 6571d8cd9..f6d674688 100644 --- a/app/routes/index.js +++ b/app/routes/index.js @@ -142,6 +142,18 @@ async function initialize(){ options: { name: 'org_id.cluster_id'} } ], + channels: [ + { + keys: { org_id: 1, name: 1 }, + options: { name: 'org_id.name', unique: true } + } + ], + deployableVersions: [ + { + keys: { org_id: 1, channel_id: 1, name: 1}, + options: { name: 'org_id.channel_id.name', unique: true } + } + ], resourceStats:[ { keys: { org_id: 1 },