Skip to content

Commit

Permalink
Merge pull request #30 from sonic-screwdriver-cd/add_command_api
Browse files Browse the repository at this point in the history
feat(677): Add command api
  • Loading branch information
catto authored Mar 2, 2018
2 parents 07e2815 + a5ceb81 commit 5e73bac
Show file tree
Hide file tree
Showing 8 changed files with 357 additions and 1 deletion.
2 changes: 2 additions & 0 deletions bin/server
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ const cache = Object.assign({ engine: strategy }, strategyConfig[strategyConfig.
const httpd = config.get('httpd');
const auth = config.get('auth');
const builds = config.get('builds');
const commands = config.get('commands');
const ecosystem = config.get('ecosystem');

require('../')({
cache,
httpd,
builds,
commands,
auth,
ecosystem
}, (err, server) => {
Expand Down
6 changes: 6 additions & 0 deletions config/custom-environment-variables.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ builds:
# Upper limit on incoming uploads to builds
maxByteSize: BUILDS_MAX_BYTES

commands:
# How long should commands stay around for
expiresInSec: COMMANDS_EXPIRE_TIME
# Upper limit on incoming uploads to commands
maxByteSize: COMMANDS_MAX_BYTES

strategy:
plugin: STRATEGY
memory:
Expand Down
6 changes: 6 additions & 0 deletions config/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ builds:
# Upper limit on incoming uploads to builds
maxByteSize: 1073741824 # 1GB

commands:
# How long should commands stay around for
expiresInSec: 31536000000 # 1 year
# Upper limit on incoming uploads to commands
maxByteSize: 1073741824 # 1GB

strategy:
plugin: memory
memory:
Expand Down
4 changes: 3 additions & 1 deletion lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ const CORE_PLUGINS = [
];
const CUSTOM_PLUGINS = [
'auth',
'builds'
'builds',
'commands'
];

/**
Expand All @@ -27,6 +28,7 @@ const CUSTOM_PLUGINS = [
* @param {Object} config.cache.engine Catbox Engine
* @param {Object} config.builds Build plugin configuration
* @param {Object} config.auth Auth plugin configuration
* @param {Object} config.commands Commands plugin configuration
* @param {Function} callback Callback to invoke when server has started.
* @return {http.Server} A listener: NodeJS http.Server object
*/
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"hoek": "^5.0.3",
"inert": "^4.0.2",
"joi": "^13.0.0",
"screwdriver-data-schema": "^18.11.5",
"verror": "^1.8.1",
"vision": "^4.1.0",
"winston": "^2.2.0"
Expand Down
137 changes: 137 additions & 0 deletions plugins/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
'use strict';

const boom = require('boom');
const schema = require('screwdriver-data-schema');
const SCHEMA_COMMAND_NAMESPACE = schema.config.command.namespace;
const SCHEMA_COMMAND_NAME = schema.config.command.name;
const SCHEMA_COMMAND_VERSION = schema.config.command.version;
const DEFAULT_TTL = 24 * 60 * 60 * 1000; // 1 day
const DEFAULT_BYTES = 1024 * 1024 * 1024; // 1GB

/**
* Commands Plugin
* @method register
* @param {Hapi} server Hapi Server
* @param {Object} options Configuration
* @param {Integer} options.expiresInSec How long to keep it around
* @param {Integer} options.maxByteSize Maximum Bytes to accept
* @param {Function} next Function to call when done
*/
exports.register = (server, options, next) => {
const cache = server.cache({
segment: 'commands',
expiresIn: parseInt(options.expiresInSec, 10) || DEFAULT_TTL
});

server.expose('stats', cache.stats);
server.route([{
method: 'GET',
path: '/commands/{namespace}/{name}/{version}',
config: {
description: 'Get command binary',
notes: 'Get a script or binary of specific command',
tags: ['api', 'commands'],
auth: {
strategies: ['token'],
scope: ['user', 'build']
},
plugins: {
'hapi-swagger': {
security: [{ token: [] }]
}
},
handler: (request, reply) => {
const { namespace, name, version } = request.params;

const id = `${namespace}-${name}-${version}`;

cache.get(id, (err, value) => {
if (err) {
return reply(err);
}
if (!value) {
return reply(boom.notFound());
}

// @TODO put cache headers in here
const response = reply(Buffer.from(value.c.data));

response.headers = value.h;

return response;
});
},
validate: {
params: {
namespace: SCHEMA_COMMAND_NAMESPACE,
name: SCHEMA_COMMAND_NAME,
version: SCHEMA_COMMAND_VERSION
}
}
}
}, {
method: 'POST',
path: '/commands/{namespace}/{name}/{version}',
config: {
description: 'Write command',
notes: 'Write a script or binary of specific command',
tags: ['api', 'commands'],
payload: {
maxBytes: parseInt(options.maxByteSize, 10) || DEFAULT_BYTES,
parse: false
},
auth: {
strategies: ['token'],
scope: ['build']
},
plugins: {
'hapi-swagger': {
security: [{ token: [] }]
}
},
handler: (request, reply) => {
const pipelineId = request.auth.credentials.pipelineId;
const { namespace, name, version } = request.params;
const id = `${namespace}-${name}-${version}`;
const contents = {
c: request.payload,
h: {}
};
const size = Buffer.byteLength(request.payload);

// Store all x-* and content-type headers
Object.keys(request.headers).forEach((header) => {
if (header.indexOf('x-') === 0 || header === 'content-type') {
contents.h[header] = request.headers[header];
}
});

request.log([pipelineId], `Saving command of ${name} of size ${size} `
+ `bytes with headers ${JSON.stringify(contents.h)}`);

return cache.set(id, contents, 0, (err) => {
if (err) {
request.log([id, 'error'], `Failed to store in cache: ${err}`);

return reply(boom.serverUnavailable(err.message, err));
}

return reply().code(202);
});
},
validate: {
params: {
namespace: SCHEMA_COMMAND_NAMESPACE,
name: SCHEMA_COMMAND_NAME,
version: SCHEMA_COMMAND_VERSION
}
}
}
}]);

next();
};

exports.register.attributes = {
name: 'commands'
};
2 changes: 2 additions & 0 deletions test/lib/server.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ describe('server case', function () {
auth: {
jwtPublicKey: '12345'
},
commands: {},
ecosystem
}, (e, s) => {
const server = s;
Expand Down Expand Up @@ -64,6 +65,7 @@ describe('server case', function () {
port: 12347
},
cache: { engine },
commands: {},
ecosystem
}, (error) => {
Assert.isOk(error);
Expand Down
Loading

0 comments on commit 5e73bac

Please sign in to comment.