Skip to content
6 changes: 4 additions & 2 deletions lib/models/mongo/context-version.js
Original file line number Diff line number Diff line change
Expand Up @@ -719,9 +719,10 @@ ContextVersionSchema.statics.updateAndGetFailedBuild = (buildId, errorMessage) =

/**
* @param {string} buildId - build id associated with context version
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: update jsdoc

* @param {object} imageData - the image data to attach to the context version,
* @return {Promise}
*/
ContextVersionSchema.statics.updateAndGetSuccessfulBuild = (buildId) => {
ContextVersionSchema.statics.updateAndGetSuccessfulBuild = (buildId, imageData) => {
var log = logger.child({
buildId: buildId,
method: 'updateAndGetSuccessfulBuild'
Expand All @@ -732,7 +733,8 @@ ContextVersionSchema.statics.updateAndGetSuccessfulBuild = (buildId) => {
$set: {
'build.completed': Date.now(),
'build.failed': false,
'state': ContextVersion.states.buildSucceeded
'state': ContextVersion.states.buildSucceeded,
'imageData': imageData
}
}

Expand Down
28 changes: 28 additions & 0 deletions lib/models/mongo/schemas/context-version.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,34 @@ var ContextVersionSchema = module.exports = new Schema({
},
log: Schema.Types.Mixed,
failed: Boolean
},
imageData: {
type: {
ports: {
type: [{
protocol: {
type: String
},
port: {
type: String
}
}],
'default': []
},
cmd: [{
type: String,
'default': []
}],
entryPoint: [{
type: String,
'default': []
}]
},
'default': {
ports: [],
cmd: [],
entryPoint: []
}
}
})

Expand Down
5 changes: 3 additions & 2 deletions lib/models/services/build-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -335,13 +335,14 @@ BuildService._buildBuild = function (build, buildInfo, sessionUser) {

/**
* @param {String} buildId
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit update jsdoc

* @param {object} imageData - the image data to attach to the context version,
* @return {Promise}
*/
BuildService.updateSuccessfulBuild = (buildId) => {
BuildService.updateSuccessfulBuild = (buildId, imageData) => {
var log = logger.child({ method: 'updateSuccessfulBuild' })
log.info({ buildId }, 'updateSuccessfulBuild called')

return ContextVersion.updateAndGetSuccessfulBuild(buildId)
return ContextVersion.updateAndGetSuccessfulBuild(buildId, imageData)
.tap((SuccessfullContextVersions) => {
var contextVersionIds = SuccessfullContextVersions.map(pluck('_id'))

Expand Down
82 changes: 56 additions & 26 deletions lib/workers/build.container.died.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,44 +19,26 @@ const Promise = require('bluebird')
const error = require('error')
const InstanceService = require('models/services/instance-service')
const BuildService = require('models/services/build-service')

const Isolation = require('models/mongo/isolation')
const logger = require('logger')
const rabbitMQ = require('models/rabbitmq')

const ContainerImageBuilderDied = {}

module.exports = ContainerImageBuilderDied

ContainerImageBuilderDied.jobSchema = joi.object({
from: joi.string().required(),
host: joi.string().uri({ scheme: 'http' }).required(),
id: joi.string().required(),
time: joi.number().required(),
inspectData: joi.object({
Config: joi.object({
Labels: joi.object({
'contextVersion.build._id': joi.string().required(),
'ownerUsername': joi.string().required(),
'sessionUserGithubId': joi.number().required()
}).unknown().required()
}).unknown().required()
}).unknown().required()
}).unknown().required()

class Worker {
constructor (job) {
this.log = logger.child({
job: job,
module: 'ContainerImageBuilderDied'
})

this.host = job.host
this.id = job.id
this.inspectImageData = this._getImageDataFromJob(job)
this.inspectData = job.inspectData
this.contextVersionBuildId = job.inspectData.Config.Labels['contextVersion.build._id']
this.ownerUsername = job.inspectData.Config.Labels.ownerUsername
this.sessionUserGithubId = job.inspectData.Config.Labels.sessionUserGithubId
this.dockerImageTag = job.inspectData.Config.Labels.dockerTag

this.log = logger.child({
job: job,
module: 'ContainerImageBuilderDied'
})
}

/**
Expand Down Expand Up @@ -103,7 +85,7 @@ class Worker {
imageTag: this.dockerImageTag
})

return BuildService.updateSuccessfulBuild(this.contextVersionBuildId)
return BuildService.updateSuccessfulBuild(this.contextVersionBuildId, this.inspectImageData)
}

/**
Expand Down Expand Up @@ -309,6 +291,48 @@ class Worker {

return false
}

/**
* @param ports {Object} Object who's properties are in the format {<port>/<protocol>:<empty>}
* @returns {Array} Array of ports parsed into {protocol: <protocol>, port: <port>
* @private
*/
_parsePorts (ports) {
let portList = []
let splitPort

if (ports) {
for (let key of Object.keys(ports)) {
splitPort = key.split('/')

portList.push({
protocol: splitPort[1],
port: splitPort[0]
})
}
}

return portList
}

/**
* Returns the image data formatted for the context version model.
*
* @param job
* @returns {{port: Array, cmd: Array, entryPoint: Array}}
* @private
*/
_getImageDataFromJob (job) {
const log = this.log.child({ job, method: '_getImageDataFromJob' })
log.info('called')

let rawImageData = keypather.get(job, 'inspectImageData.Config')
return {
port: this._parsePorts(keypather.get(rawImageData, 'ExposedPorts')),
cmd: keypather.get(rawImageData, 'Cmd'),
entryPoint: keypather.get(rawImageData, 'Entrypoint')
}
}
}

module.exports = {
Expand All @@ -323,6 +347,12 @@ module.exports = {
from: joi.string().required(),
host: joi.string().uri({ scheme: 'http' }).required(),
id: joi.string().required(),
time: joi.number().required(),
inspectImageData: joi.object({
exposedPorts: joi.array(joi.object({}).unknown()).default([]),
cmd: joi.array(joi.string()).default([]),
entrypoint: joi.array(joi.string()).default([])
}).unknown().required(),
inspectData: joi.object({
Config: joi.object({
Labels: joi.object({
Expand Down
64 changes: 61 additions & 3 deletions unit/models/mongo/context-version.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ describe('Context Version Unit Test', function () {
done()
})

it('should save a successful build', (done) => {
it('should save a successful build with no image data', (done) => {
const buildId = 12341

ContextVersion.updateAndGetSuccessfulBuild(buildId).asCallback(() => {
Expand All @@ -320,12 +320,70 @@ describe('Context Version Unit Test', function () {
$set: {
'build.failed': false,
'build.completed': sinon.match.number,
'state': ContextVersion.states.buildSucceeded
'state': ContextVersion.states.buildSucceeded,
imageData: undefined
}
})

sinon.assert.calledOnce(ContextVersion.findByAsync)
sinon.assert.calledWith(ContextVersion.findByAsync, 'build._id', buildId)
sinon.assert.calledWithExactly(ContextVersion.findByAsync, 'build._id', buildId)
done()
})
})

it('should save a successful build with image data', (done) => {
const buildId = 12341
const imageData = {
ports: [{
protocol: 'Omega',
port: '13'
}],
cmd: ['cmd 1'],
entryPoint: ['entry 1']
}

ContextVersion.updateAndGetSuccessfulBuild(buildId, imageData).asCallback(() => {
sinon.assert.calledOnce(ContextVersion.updateByAsync)
sinon.assert.calledWith(ContextVersion.updateByAsync,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if possible use sinon.assert.calledWithExactly - which is more strict

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was able to switch it below but this one causes issues.

'build._id',
buildId, {
$set: {
'build.failed': false,
'build.completed': sinon.match.number,
'state': ContextVersion.states.buildSucceeded,
'imageData': imageData
}
})

sinon.assert.calledOnce(ContextVersion.findByAsync)
sinon.assert.calledWithExactly(ContextVersion.findByAsync, 'build._id', buildId)
done()
})
})

it('should save a successful build with empty image data', (done) => {
const buildId = 12341
const imageData = {
ports: [],
cmd: [],
entryPoint: []
}

ContextVersion.updateAndGetSuccessfulBuild(buildId, imageData).asCallback(() => {
sinon.assert.calledOnce(ContextVersion.updateByAsync)
sinon.assert.calledWith(ContextVersion.updateByAsync,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if possible use sinon.assert.calledWithExactly - which is more strict

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was able to switch it below but this one causes issues.

'build._id',
buildId, {
$set: {
'build.failed': false,
'build.completed': sinon.match.number,
'state': ContextVersion.states.buildSucceeded,
'imageData': imageData
}
})

sinon.assert.calledOnce(ContextVersion.findByAsync)
sinon.assert.calledWithExactly(ContextVersion.findByAsync, 'build._id', buildId)
done()
})
})
Expand Down