Add v2 interface support for nodes env (#836)
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
ARG BUILDER_IMAGE=fission/builder
|
||||
FROM ${BUILDER_IMAGE}
|
||||
# default variant is the official alpine node image (much smaller than the standard image)
|
||||
FROM node:8-alpine
|
||||
|
||||
ARG NODE_ENV
|
||||
ENV NODE_ENV $NODE_ENV
|
||||
|
||||
COPY --from=0 /builder /builder
|
||||
ADD build.sh /usr/local/bin/build
|
||||
RUN chmod +x /usr/local/bin/build
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
cd ${SRC_PKG}
|
||||
npm install && cp -r ${SRC_PKG} ${DEPLOY_PKG}
|
||||
@@ -6,6 +6,10 @@
|
||||
{
|
||||
"name": "Soam Vasani",
|
||||
"email": "soamvasani@platform9.com"
|
||||
},
|
||||
{
|
||||
"name": "Gary Yeap",
|
||||
"email": "contact@garyyeap.com"
|
||||
}
|
||||
],
|
||||
"description": "NodeJS run container for the fission framework",
|
||||
@@ -20,7 +24,7 @@
|
||||
"morgan": "*",
|
||||
"mz": "~2.7.0",
|
||||
"request": "^2.81.0",
|
||||
"request-promise-native": "^1.0.3",
|
||||
"underscore": ">=1.8.3"
|
||||
"underscore": ">=1.8.3",
|
||||
"request-promise-native": "^1.0.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,56 +7,86 @@ const express = require('express');
|
||||
const app = express();
|
||||
const bodyParser = require('body-parser');
|
||||
const morgan = require('morgan');
|
||||
const argv = require('minimist')(process.argv.slice(1));// Command line opts
|
||||
|
||||
// Command line opts
|
||||
const argv = require('minimist')(process.argv.slice(1));
|
||||
if (!argv.codepath) {
|
||||
argv.codepath = "/userfunc/user";
|
||||
console.log("Codepath defaulting to ", argv.codepath);
|
||||
}
|
||||
if (!argv.port) {
|
||||
console.log("Port defaulting to 8888");
|
||||
argv.port = 8888;
|
||||
}
|
||||
|
||||
|
||||
// Node resolves module paths according to a file's location. We load
|
||||
// the file from argv.codepath, but tell users to put dependencies in
|
||||
// the server's package.json; this means the function's dependencies
|
||||
// are in /usr/src/app/node_modules. We could be smarter and have the
|
||||
// function deps in the right place in argv.codepath; but for now we
|
||||
// just symlink the function's node_modules to the server's
|
||||
// node_modules.
|
||||
fs.symlinkSync('/usr/src/app/node_modules', `${path.dirname(argv.codepath)}/node_modules`);
|
||||
|
||||
// User function. Starts out undefined.
|
||||
let userFunction;
|
||||
|
||||
//
|
||||
// Specialize this server to a given user function. The user function
|
||||
// is read from argv.codepath; it's expected to be placed there by the
|
||||
// fission runtime.
|
||||
//
|
||||
function specialize(req, res) {
|
||||
// Make sure we're a generic container. (No reuse of containers.
|
||||
// Once specialized, the container remains specialized.)
|
||||
if (userFunction) {
|
||||
res.status(400).send("Not a generic container");
|
||||
return;
|
||||
}
|
||||
|
||||
function loadFunction(modulepath, funcname) {
|
||||
// Read and load the code. It's placed there securely by the fission runtime.
|
||||
try {
|
||||
var startTime = process.hrtime();
|
||||
userFunction = require(argv.codepath);
|
||||
var elapsed = process.hrtime(startTime);
|
||||
let startTime = process.hrtime();
|
||||
// support v1 codepath and v2 entrypoint like 'foo', '', 'index.hello'
|
||||
let userFunction = funcname ? require(modulepath)[funcname] : require(modulepath);
|
||||
let elapsed = process.hrtime(startTime);
|
||||
console.log(`user code loaded in ${elapsed[0]}sec ${elapsed[1]/1000000}ms`);
|
||||
return userFunction;
|
||||
} catch(e) {
|
||||
console.error(`user code load error: ${e}`);
|
||||
res.status(500).send(JSON.stringify(e));
|
||||
return;
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
function withEnsureGeneric(func) {
|
||||
return function(req, res) {
|
||||
// Make sure we're a generic container. (No reuse of containers.
|
||||
// Once specialized, the container remains specialized.)
|
||||
if (userFunction) {
|
||||
res.status(400).send("Not a generic container");
|
||||
return;
|
||||
}
|
||||
|
||||
func(req, res);
|
||||
}
|
||||
}
|
||||
|
||||
function isFunction(func) {
|
||||
return func && func.constructor && func.call && func.apply;
|
||||
}
|
||||
|
||||
function specializeV2(req, res) {
|
||||
// for V2 entrypoint, 'filename.funcname' => ['filename', 'funcname']
|
||||
const entrypoint = req.body.functionName ? req.body.functionName.split('.') : [];
|
||||
// for V2, filepath is dynamic path
|
||||
const modulepath = path.join(req.body.filepath, entrypoint[0] || '');
|
||||
const result = loadFunction(modulepath, entrypoint[1]);
|
||||
|
||||
if(isFunction(result)){
|
||||
userFunction = result;
|
||||
res.status(202).send();
|
||||
} else {
|
||||
res.status(500).send(JSON.stringify(result));
|
||||
}
|
||||
}
|
||||
|
||||
function specialize(req, res) {
|
||||
// Specialize this server to a given user function. The user function
|
||||
// is read from argv.codepath; it's expected to be placed there by the
|
||||
// fission runtime.
|
||||
//
|
||||
const modulepath = argv.codepath || '/userfunc/user';
|
||||
|
||||
// Node resolves module paths according to a file's location. We load
|
||||
// the file from argv.codepath, but tell users to put dependencies in
|
||||
// the server's package.json; this means the function's dependencies
|
||||
// are in /usr/src/app/node_modules. We could be smarter and have the
|
||||
// function deps in the right place in argv.codepath; b ut for now we
|
||||
// just symlink the function's node_modules to the server's
|
||||
// node_modules.
|
||||
fs.symlinkSync('/usr/src/app/node_modules', `${path.dirname(modulepath)}/node_modules`);
|
||||
|
||||
const result = loadFunction(modulepath);
|
||||
|
||||
if(isFunction(result)){
|
||||
userFunction = result;
|
||||
res.status(202).send();
|
||||
} else {
|
||||
res.status(500).send(JSON.stringify(result));
|
||||
}
|
||||
res.status(202).send();
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +98,8 @@ app.use(bodyParser.json());
|
||||
app.use(bodyParser.raw());
|
||||
app.use(bodyParser.text({ type : "text/*" }));
|
||||
|
||||
app.post('/specialize', specialize);
|
||||
app.post('/specialize', withEnsureGeneric(specialize));
|
||||
app.post('/v2/specialize', withEnsureGeneric(specializeV2));
|
||||
|
||||
// Generic route -- all http requests go to the user function.
|
||||
app.all('/', function (req, res) {
|
||||
|
||||
Reference in New Issue
Block a user