knative-build/runtimes/javascript/platform/platform.js (90 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Runtime platform factory * * This module is a NodeJS compatible version of a factory that will * produce an implementation module provides OpenWhisk Language * Runtime functionality and is able to register endpoints/handlers * allowing to host OpenWhisk Actions and process OpenWhisk Activations. */ var dbg = require('../utils/debug'); var DEBUG = new dbg(); // Export supported platform impls. const PLATFORM_OPENWHISK = 'openwhisk'; const PLATFORM_KNATIVE = 'knative'; const SUPPORTED_PLATFORMS = [ PLATFORM_OPENWHISK, PLATFORM_KNATIVE ]; module.exports = class PlatformFactory { /** * Object constructor * @param app NodeJS express application instance * @param cfg Runtime configuration * @@param svc Runtime services (default handlers) */ constructor (app, cfg, svc) { DEBUG.dumpObject(app,"app"); DEBUG.dumpObject(cfg,"cfg"); DEBUG.dumpObject(svc,"svc"); this._app = app; this._service = svc; this._config = cfg; } /** * @returns {string[]} List of supported platforms by their string ID */ static get SUPPORTED_PLATFORMS() { return SUPPORTED_PLATFORMS; } static get PLATFORM_OPENWHISK() { return PLATFORM_OPENWHISK; } static get PLATFORM_KNATIVE() { return PLATFORM_KNATIVE; } get app(){ return this._app; } get service(){ return this._service; } get config(){ return this._config; } /** * validate if a platform ID is a known, supported value * @param id Platform Id */ static isSupportedPlatform(id) { if (SUPPORTED_PLATFORMS.indexOf(id) > -1) { return true; } return false; } /** * Instantiate a platform implementation * @param id Platform ID * @returns {PlatformImpl} Platform instance (interface), as best can be done with NodeJS */ createPlatformImpl(id) { DEBUG.functionStart(); DEBUG.dumpObject(id,"id"); // Load the appropriate implementation module and return reference to it switch (id.toLowerCase()) { case PLATFORM_KNATIVE: const knPlatformImpl = require('./knative.js'); this._platformImpl = new knPlatformImpl(this); break; case PLATFORM_OPENWHISK: const owPlatformImpl = require('./openwhisk.js'); this._platformImpl = new owPlatformImpl(this); break; default: console.error("Platform ID is not a known value (" + id + ")."); } DEBUG.dumpObject(this._platformImpl,"platformImpl"); DEBUG.functionEnd(); return this._platformImpl; } /** * Wraps an endpoint written to return a Promise into an express endpoint, * producing the appropriate HTTP response and closing it for all controllable * failure modes. * * The expected signature for the promise value (both completed and failed) * is { code: int, response: object }. * * @param ep a request=>promise function * @returns an express endpoint handler */ wrapEndpoint(ep) { DEBUG.functionStart("wrapping: " + ep.name); DEBUG.functionEnd("returning wrapper: " + ep.name); return function (req, res) { try { ep(req).then(function (result) { res.status(result.code).json(result.response); DEBUG.dumpObject(result,"result"); DEBUG.dumpObject(res,"response"); DEBUG.functionEndSuccess("wrapper for: " + ep.name); }).catch(function (error) { if (typeof error.code === "number" && typeof error.response !== "undefined") { res.status(error.code).json(error.response); } else { console.error("[wrapEndpoint]", "invalid errored promise", JSON.stringify(error)); res.status(500).json({ error: "Internal error." }); } DEBUG.dumpObject(error,"error"); DEBUG.dumpObject(res,"response"); DEBUG.functionEndError(error, "wrapper for: " + ep.name); }); } catch (e) { // This should not happen, as the contract for the endpoints is to // never (externally) throw, and wrap failures in the promise instead, // but, as they say, better safe than sorry. console.error("[wrapEndpoint]", "exception caught", e.message); res.status(500).json({ error: "Internal error (exception)." }); DEBUG.dumpObject(error,"error"); DEBUG.functionEndError(error, ep.name); } } } };