Giter Club home page Giter Club logo

openwhisk-client-js's Introduction

Apache OpenWhisk Client for JavaScript

License Continuous Integration codecov JavaScript Style Guide

JavaScript client library for the Apache OpenWhisk platform. Provides a wrapper around the OpenWhisk APIs (Swagger JSON).

installation

$ npm install openwhisk

usage

within openwhisk platform

This client library can use environment parameters to automatically configure the authentication credentials, platform endpoint and namespace. These parameters are defined within the Node.js runtime environment in OpenWhisk. Unless you want to override these values, you can construct the client instance without further configuration.

var openwhisk = require('openwhisk');

function action() {
  var ow = openwhisk();
  return ow.actions.invoke('sample')
}

exports.main = action

All methods return a Promise resolved asynchronously with the results. Failures are available through the catch method.

ow.resource.operation()
  .then(function () { /* success! */ })
  .catch(function (err) { /* failed! */ })

Users can override default constructor parameters by passing in explicit options as shown in the example below.

outside openwhisk platform

var openwhisk = require('openwhisk');
var options = {apihost: 'openwhisk.ng.bluemix.net', api_key: '...'};
var ow = openwhisk(options);
ow.actions.invoke('sample').then(result => console.log(result))

using 3rd party authentication handler

You can specify an authentication handler in options.auth_handler this is an object that provides a function getAuthHeader that returns a Promise resolving to a string to be used in the Authorization http header for every http request.

const authHandler = {
  getAuthHeader: ()=>{
    return Promise.resolve('Basic user:password')
  }
}
var openwhisk = require('openwhisk');
var options = {
  apihost: 'openwhisk.ng.bluemix.net',
  auth_handler: authHandler
}
var ow = openwhisk(options)
ow.actions.invoke('sample').then(result => console.log(result))

constructor options

Client constructor supports the following mandatory parameters:

  • apihost. Hostname and optional port for openwhisk platform, e.g. openwhisk.ng.bluemix.net or my_whisk_host:80. Used with API URL template ${protocol}://${apihost}/api/v1/. If port is missing or port value is 443 in the apihost string, protocol is HTTPS. Otherwise, protocol is HTTP.
  • api_key. Authorisation key for user account registered with OpenWhisk platform.

Client constructor supports the following optional parameters:

  • api. Full API URL for OpenWhisk platform, e.g. https://openwhisk.ng.bluemix.net/api/v1/. This value overrides apihost if both are present.
  • apiversion Api version for the OpenWhisk platform, e.g. the v1 in https://openwhisk.ng.bluemix.net/api/v1/, when used with apihost (and api is not set)
  • namespace. Namespace for resource requests, defaults to _.
  • ignore_certs. Turns off server SSL/TLS certificate verification. This allows the client to be used against local deployments of OpenWhisk with a self-signed certificate. Defaults to false.
  • apigw_token. API Gateway service authentication token. This is mandatory for using an external API Gateway service, rather than the built-in api gateway.
  • apigw_space_guid. API Gateway space identifier. This is optional when using an API gateway service, defaults to the authentication uuid.
  • cert. Client cert to use when connecting to the apihost (if nginx_ssl_verify_client is turned on in your apihost)
  • key. Client key to use when connecting to the apihost (if nginx_ssl_verify_client is turned on in your apihost)
  • proxy. HTTP(s) URI for proxy service to forwards requests through. Uses Needle's built-in proxy support.
  • agent. Provide custom http.Agent implementation.
  • retry. Provide a retry options to retry on errors, for example, { retries: 2 }. By default, no retries will be done. Uses async-retry options. Default values are different from async-retry, please refer to the API doc.

environment variables

Client constructor will read values for the apihost, namespace, api_key, ignore_certs, apigw_token and apigw_space_guid options from the environment if the following parameters are set. Explicit options have precedence over environment values.

  • __OW_API_HOST
  • __OW_NAMESPACE
  • __OW_API_KEY
  • __OW_IGNORE_CERTS
  • __OW_APIGW_TOKEN
  • __OW_APIGW_SPACE_SUID
  • __OW_USER_AGENT

User-Agent

A User-Agent header may be specified to be passed along with all calls to OpenWhisk. This can be helpful, if you wish to discriminate client traffic to your OpenWhisk backend. By default, the header will have the value openwhisk-client-js. You may override this by passing along a 'User-Agent' field in the options structure of any API calls; note that this is not a constructor argument, but rather an option to the API calls themselves. For example, one might specify a myClient user agent to an action invocation as follows:

ow.actions.invoke({ 'User-Agent': 'myClient', name, params })

In some cases, you may need to have no User-Agent header. To override the default header behavior, you may pass noUserAgent: true in your options structure, e.g.

ow.actions.invoke({ noUserAgent: true, name, params })

Working with a Proxy

If you are working behind a firewall, HTTP(s) proxy details can be set by using the proxy option in the constructor parameters with the proxy service URI, e.g. http://proxy-server.com:3128. The proxy URI can also be set using the following environment parameters (to set a proxy without changing application code):

  • proxy or PROXY
  • http_proxy or HTTP_PROXY
  • https_proxy or HTTPS_proxy

If you need more advanced proxy behaviour, rather than using Needle's default built-in HTTP agent, the agent constructor parameter can be used to set a custom http.Agent implementation, e.g proxy-agent

Examples

invoke action, blocking for result

const name = 'reverseWords'
const blocking = true, result = true
const params = {msg: 'these are some words to reverse'}

ow.actions.invoke({name, blocking, result, params}).then(result => {
  console.log('here is the reversed string', result.reversed)
}).catch(err => {
  console.error('failed to invoke actions', err)
})

fire trigger

const name = 'eventTrigger'
const params = {msg: 'event trigger message string'}
ow.triggers.invoke({name, params}).then(result => {
  console.log('trigger fired!')
}).catch(err => {
  console.error('failed to fire trigger', err)
})

create action from source file

const name = 'reverseWords'
const action = fs.readFileSync('source.js', {encoding: 'utf8'})

ow.actions.create({name, action}).then(result => {
  console.log('action created!')
}).catch(err => {
  console.error('failed to create action', err)
})

create action from zip package

const name = 'reverseWords'
const action = fs.readFileSync('package.zip')

ow.actions.create({name, action}).then(result => {
  console.log('action created!')
}).catch(err => {
  console.error('failed to create action', err)
})

create sequence from another action

const actionName = '/mynamespace/reverseWords'
const name = 'reverse'

ow.actions.create({ name, sequence: [ actionName ] })

retrieve action resource

const name = 'reverseWords'
ow.actions.get(name).then(action => {
  console.log('action resource', action)
}).catch(err => {
  console.error('failed to retrieve action', err)
})

chaining calls

ow.actions.list()
  .then(actions => ow.actions.invoke(actions))
  .then(result => { /* ... */ })

list packages

ow.packages.list().then(packages => {
  packages.forEach(package => console.log(package.name))
}).catch(err => {
  console.error('failed to list packages', err)
})

update package parameters

const name = 'myPackage'
const package = {
  parameters: [
    {key: "colour", value: "green"},
    {key: "name", value: "Freya"}
  ]
}

ow.packages.update({name, package}).then(package => {
  console.log('updated package:', package.name)
}).catch(err => {
  console.error('failed to update package', err)
})

bind a package from another namespace

const name = 'myBoundPackage'
const package = {
  binding: {
    namespace: "othernamespace", // namespace to bind from
    name: "otherpackage" // package to bind from
  }
}

ow.packages.update({name, package}).then(package => {
  console.log('bound package:', package.name)
}).catch(err => {
  console.error('failed to bind package', err)
})

create trigger feed from alarm package

// alarmTrigger MUST already exist in default namespace
const params = {cron: '*/8 * * * * *', trigger_payload: {name: 'James'}}
const name = '/whisk.system/alarms/alarm'
const trigger = 'alarmTrigger'
ow.feeds.create({name, trigger, params}).then(package => {
  console.log('alarm trigger feed created')
}).catch(err => {
  console.error('failed to create alarm trigger', err)
})

API Details

resource identifiers + namespaces

When passing resource identifiers as parameters you can either use a short name, without an explicit namespace, or a fully-qualified identifier, including namespace and package details.

If the namespace is missing from the resource identifier, the client will use the namespace from configuration options following this ordering.

  • namespace from method parameter options OR
  • namespace from options passed into client constructor OR
  • namespace from environment variable (__OW_NAMESPACE) OR
  • default namespace: _

list resources

ow.actions.list()
ow.activations.list()
ow.triggers.list()
ow.rules.list()
ow.namespaces.list()
ow.packages.list()

Query parameters for the API calls are supported (e.g. limit, skip, count etc.) by passing an object with the named parameters as the first argument.

ow.actions.list({skip: 100, limit: 50})

To count the number of resources without retrieving the resources you can use count query parameter.

ow.actions.list({count:true})

The following optional parameters are supported:

  • namespace - set custom namespace for endpoint

retrieve resource

ow.actions.get({name: '...'})
ow.activations.get({name: '...'})
ow.triggers.get({name: '...'})
ow.rules.get({name: '...'})
ow.packages.get({name: '...'})
ow.feeds.get({name: '...', trigger: '...'})

The following optional parameters are supported for all resource retrievals:

  • namespace - set custom namespace for endpoint

Optional parameters for action resource retrievals are shown below:

  • code - set to true or false depending on whether action code should be included or excluded respectively

This method also supports passing the name property directly without wrapping within an object.

const name = "actionName"
ow.actions.get(name)

If you pass in an array for the first parameter, the get call will be executed for each array item. The function returns a Promise which resolves with the results when all operations have finished.

ow.actions.get(["a", {name: "b"}])

delete resource

ow.actions.delete({name: '...'})
ow.triggers.delete({name: '...'})
ow.rules.delete({name: '...'})
ow.packages.delete({name: '...'})
ow.feeds.delete({name: '...', trigger: '...'})

The following optional parameters are supported:

  • namespace - set custom namespace for endpoint

This method also supports passing the name property directly without wrapping within an object.

const name = "actionName"
ow.actions.delete(name)

If you pass in an array for the first parameter, the delete call will be executed for each array item. The function returns a Promise which resolves with the results when all operations have finished.

ow.actions.delete(["a", {name: "b"}])

invoke action

ow.actions.invoke({name: '...'})

The actionName parameter supports the following formats: actionName, package/actionName, /namespace/actionName, /namespace/package/actionName.

If actionName includes a namespace, this overrides any other namespace properties.

The following optional parameters are supported:

  • blocking - delay returning until action has finished executing (default: false)
  • result - return function result (obj.response.result) rather than entire API result (default: false)
  • params - JSON object containing parameters for the action being invoked (default: {})
  • namespace - set custom namespace for endpoint

This method also supports passing the name property directly without wrapping within an object.

const name = "actionName"
ow.actions.invoke(name)

If you pass in an array for the first parameter, the invoke call will be executed for each array item. The function returns a Promise which resolves with the results when all operations have finished.

ow.actions.invoke(["a", {name: "b", blocking: true}])

create & update action

ow.actions.create({name: '...', action: 'function main() {};'})
ow.actions.update({name: '...', action: 'function main() {};'})

The following mandatory parameters are supported:

  • name - action identifier
  • action - String containing JS function source code, Buffer containing package action zip file or JSON object containing full parameters for the action body

The following optional parameters are supported:

  • namespace - set custom namespace for endpoint
  • params - object containing default parameters for the action (default: {})
  • annotations - object containing annotations for the action (default: {})
  • limits - object containing limits for the action (default: {})
  • kind - runtime environment parameter, ignored when action is an object (default: nodejs:default)

If you pass in an array for the first parameter, the create call will be executed for each array item. The function returns a Promise which resolves with the results when all operations have finished.

ow.actions.create([{...}, {...}])

create & update action sequence

ow.actions.create({name: '...', sequence: ["action_name", "next_action", ...]})
ow.actions.update({name: '...', sequence: ["action_name", "next_action", ...]})

The following mandatory parameters are supported:

  • name - action identifier
  • sequence - Array containing JS strings with action identifiers to use in sequence. This can be a full or relative action identifier (e.g. action-name or /namespace/package/action-name).

The following optional parameters are supported:

  • namespace - set custom namespace for endpoint
  • params - object containing default parameters for the action (default: {})
  • annotations - object containing annotations for the action (default: {})
  • limits - object containing limits for the action (default: {})

If you pass in an array for the first parameter, the create call will be executed for each array item. The function returns a Promise which resolves with the results when all operations have finished.

ow.actions.create([{...}, {...}])

fire trigger

ow.triggers.invoke({name: '...'})

The following optional parameters are supported:

  • params - JSON object containing parameters for the trigger being fired (default: {})
  • namespace - set custom namespace for endpoint

This method also supports passing the name property directly without wrapping within an object.

const name = "actionName"
ow.triggers.invoke(name)

If you pass in an array for the first parameter, the invoke call will be executed for each array item. The function returns a Promise which resolves with the results when all operations have finished.

ow.triggers.invoke(["a", {name: "b", blocking: true}])

create & update trigger

ow.triggers.create({name: '...'})
ow.triggers.update({name: '...'})

The following optional parameters are supported:

  • trigger - JSON object containing parameters for the trigger body (default: {})
  • namespace - set custom namespace for endpoint
  • annotations - object containing annotations for the trigger (default: {})

create & update packages

ow.packages.create({name: '...'})
ow.packages.update({name: '...'})

The following optional parameters are supported:

  • package - JSON object containing parameters for the package body (default: {})
  • namespace - set custom namespace for endpoint
  • annotations - object containing annotations for the package (default: {})

create & update rule

ow.rules.create({name: '...', action: '...', trigger: '...'})
ow.rules.update({name: '...', action: '...', trigger: '...'})

trigger and action identifiers will have the default namespace (/_/) appended in the request, unless a fully qualified name is passed in (/custom_ns/action_or_trigger_name).

The following optional parameters are supported:

  • namespace - set namespace for rule
  • annotations - object containing annotations for the rule (default: {})

enable & disable rule

ow.rules.enable({name: '...'})
ow.rules.disable({name: '...'})

The following optional parameters are supported:

  • namespace - set custom namespace for endpoint

create & update feeds

ow.feeds.create({feedName: '...', trigger: '...'})
ow.feeds.update({feedName: '...', trigger: '...'})

The following optional parameters are supported:

  • namespace - set custom namespace for endpoint
  • params - JSON object containing parameters for the feed being invoked (default: {})

api gateway

OpenWhisk supports a built-in API gateway service and external third-party providers.

This client library defaults to using the platform service. If the apigw_token parameter is passed into the client constructor, the implementation will switch to the IBM Bluemix API Gateway.

The interface for managing routes through the library does not change between providers.

retrieve route

ow.routes.get({basepath: '...'})
ow.routes.get({name: '...'})

This method is a wrapper for the list method. It throws an error if the base path or name parameter is missing.

list routes

ow.routes.list()

The following optional parameters are supported to filter the result set:

  • relpath - relative URI path for endpoints
  • basepath - base URI path for endpoints
  • name - identifier for API
  • operation - HTTP methods
  • limit - limit result set size
  • skip - skip results from index

relpath is only valid when basepath is also specified. name and basepath cannot be used together.

delete routes

ow.routes.delete({basepath: '...'})
ow.routes.delete({name: '...'})

The following optional parameters are supported to filter the result set:

  • relpath - relative URI path for endpoints
  • operation - HTTP methods

add route

ow.routes.create({relpath: '...', operation: '...', action: '...'})

action supports normal (actionName) and fully-qualified (/namespace/actionName) formats.

The following optional parameters are supported:

  • responsetype - content type returned by web action, possible values: html, http, json, text and svg (default: json).
  • basepath - base URI path for endpoints (default: /)
  • name - identifier for API (default: basepath)
  • secure_key - auth key for secure web action

add route (swagger)

ow.routes.create({swagger: '{...}'})

Swagger parameter must be a well-formed JSON string, containing a valid Swagger API definition, which follows the OpenWhisk API Gateway route schema.

No other parameters are supported when creating the route from a JSON Swagger document.

Debugging

Setting an environment parameter (DEBUG=needle) will dump the HTTP requests from the client library and responses received to stderr.

DEBUG=needle node script.js

This parameter can also be set dynamically at runtime, provided this happens before the openwhisk module is required.

process.env.DEBUG='needle';
var openwhisk = require('openwhisk');

Development

unit tests

$ npm run test:unit

integration tests

Please see the instructions for setting up the integration test environment prior to running these tests.

$ npm run test:integration

Note: The test integration runs in secure mode by default, which means that all trusted signers must be present and available to the client process. If your local environment is using self-signed certificates, you can use the following command to start the script in insecure mode:

__OW_INSECURE=true npm run test-integration

This will disable SSL/TLS verification for all SSL communication.

code coverage

Code coverage data for the unit and integration tests can be created using the following commands:

  • npm run coverage:unit
  • npm run coverage:integration

Generated data in stored in the .nyc_output directory.

Running the npm run coverage:report command will generate the output reports.

openwhisk-client-js's People

Contributors

abaruni avatar alexkli avatar aml2732 avatar cfjedimaster avatar csantanapr avatar dependabot[bot] avatar dgrove-oss avatar drewml avatar dubee avatar ert78gb avatar gbdrt avatar ioana-blue avatar jasnell avatar jbampton avatar jthomas avatar krook avatar lionelvillard avatar lornajane avatar machenity avatar moritzraho avatar mrutkows avatar pritidesai avatar purplecabbage avatar rabbah avatar scottchapman avatar selfxp avatar shazron avatar starpit avatar tardieu avatar trieloff avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

openwhisk-client-js's Issues

please add ignore_certs env var

When running test code for openwhisk actions it is often necessary to ignore certificates since it is running openwhisk in travis. It looks like the other constructor parameters are already handled this way.

3.13.0 release

Minor release, rather than patch, as #99 is a new feature.

release notes

3.13.0 (2018.03.14)

  • Adds an optional query parameter for action fetches that determines if action code will be retrieved or not (#99)

process

  • npm version minor to bump package.json to 3.13.0
  • Push version commit and git tags to Github
  • Travis CI will auto-publish new version to NPM
  • Draft Github release from tags with notes above.

Need to write up these instructions in the repository.

consider switching from request-promise to needle

request-promise depends on request, which is very slow to load: request/request#2261

that issue aligns with my experience. namely, that request-promise, due to request, can take anywhere from 120-250ms to require on mac and linux.

on windows 10, apparently due to windows defender, it can take 10 times as long! sometimes multiple seconds!

an alternative is needle: https://www.npmjs.com/package/needle

quick experiments show that needle indeed loads in about 1/4th the time. these numbers from macos 10.12.6, node 8.5.0: fairly stably needle loads in 30-32ms, and request-promise in 110-120ms.

in more realistic scenarios, i've seen request-promise routinely take close to 300ms on macos, and 1-3 seconds on windows 10. the fall creators update of windows 10 seems to have made this much worse.

the patch for this is straightforward, as needle mostly obeys the same schema as rp.

rule creation fails due to openwhisk api change

recently, the openwhisk backend introduced a (non-semver!) breaking change to the rule creation API. now, the action and trigger fields must be fully qualified, as in they must include a namespace.

suggestion: if the action or trigger do not have a slash in them, then prepend '/_/'?

Add debugging flags

Use environment variable to turn on help debugging by dumping more information about API requests to the console.

Feature request: Result only flag for action invoke

Is there an option similar to the -r in the wsk cli that returns only the result of the invocation (used together with -b or blocking = true)? I'd use it all the time :)

On a related note, I don't think I understand how this example in the readme works:

const blocking = true
const params = {msg: 'this is some words to reverse'}

ow.actions.invoke({actionName, blocking, params}).then(result => {
  console.log('here's the reversed string', result.reversed)
}).catch(err => {
  console.error(failed to invoke actions', err)
})

IIUC the result of the invocation will contain not only the "result", but all the other meta data (e.g., duration, name, annotations, etc.) and I would expect result.reversed to be undefined. New to js, what am I missing?

actions.invoke returning a 405 (method POST not supported)

I was getting errors trying actions.invoke but not getting any error stack back (using .then().catch(err)). actions.list works fine which means my base setup of API key etc was fine. I added a line of instrumentation into base_operation.js handle_errors() which showed that OW was returning a 405 method not allowed.
ow_error

3.14.0 release

release notes

3.14.0 (2018.03.26)

  • Add support to count entities with list (#109 )

process

  • npm version patch to bump package.json to 3.14.0
  • Push version commit and git tags to Github
  • Travis CI will auto-publish new version to NPM
  • Draft Github release from tags with notes above.

odd SSL error when passing large payloads

try calling ow.packges.get({name:"foo", junk: "SOME VERY LARGE PAYLOAD"})

if the payload is too big (in my case, 330k), you will get back an odd SSL error:

Error encountered calling OpenWhisk: Error: error:0906D06C:PEM routines:PEM_read_bio:no start line"

CI with travis

Setup a Travis build to periodically run integration test against an openwhisk deployment (or the publicly hosted service).

socket hangup issues due to slow connection open

we inherit needle's default connection-open timeout of 10 seconds. this seems to result in socket hangup errors. i'm not sure what the right solution is here, but wanted to raise awareness of it.

  • option 1: the user of this library has to retry
  • option 2: we update the openwhisk npm to retry, according to a policy established by the caller (e.g. maxRetries)
  • option 3: we increase the connection open timeout a bit, in tandem with either opt1 or opt2

this seems to happen often enough to be of note, when talking to ibm cloud functions

support running against a local deployment of openwhisk

A local deployment of openwhisk generally uses a self signed certificate. The base request operations should permit an additional configuration parameter to disable rejecting unauthorized TLS. This is particularly helpful for integration testing against a local deployment.

[Error][minikube] ENOTFOUND nginx.openwhisk nginx.openwhisk:443

Hi folks!

I deploy OpenWhisk locally on minikube and it's my action:

const openwhisk = require('openwhisk');

function main(params){
  return new Promise((resolve, reject) => {
    ow.actions.list().then(resolve);
  });
}

Result of invoke it is error:

Unhandled rejection Error: Error encountered calling OpenWhisk: Error: getaddrinfo ENOTFOUND nginx.openwhisk nginx.openwhisk:443

Maybe someone experienced similar issue and can help?

Cheers ๐Ÿฅ‚

3.11.0 release

Minor release, rather than patch, as #88 is a new feature.

release notes

3.11.0 (2017.12.07)

  • Added client library support for updating trigger feeds (#88)
  • Updated version of needle to 2.1.0 to resolve timeout issues with HTTP library (#90)

process

  • npm version minor to bump package.json to 3.11.0
  • Push version commit and git tags to Github
  • Travis CI will auto-publish new version to NPM
  • Draft Github release from tags with notes above.

Need to write up these instructions in the repository.

3.10.0 release

Once the following PRs have merged, the next release can drafted and made available on this repo. npmbot should automatically publish to NPM.

outstanding PRs

notes for release page

  • Added new features to routes() methods. API name parameter and swagger route definition now supported. Route retrieval method included. (#69, #70, #71)
  • Swapped HTTP client library from request to needle. Significant reduction in dependencies installed and loading time. (#77)
  • Retrieving status and configuration for feed triggers now included (#80)
  • FQN names now handles missing leading forward-slash character (#75)
  • Updated TypeScript definitions (#76)

^^ @csantanapr

Working with Feeds should manage related Trigger annotations

The CLI and OW web UIs add an annotation to triggers to associate them with feeds when creating new trigger feeds.

This means that when that trigger is deleted, the feed can be notified.

The SDK does not implement this behaviour. This means that if someone creates a new trigger feed, deletes it and tries to re-create it, it may fail based on the implementation of the feed provider.

The behaviour of the SDK should mirror the other OW tools. It should be possible to disable this behaviour using a parameter option, although it defaults to on.

Build via react-scripts fails due to ES5 incompatibility

Using 'openwhisk' in context of a React app (created with create-react-app) is causing react-scripts build to fail due to ES5 incompatibility.

$ npm run build

> [email protected] build /Users/guest/Downloads/my-app
> react-scripts build

Creating an optimized production build...
Failed to compile.

Failed to minify the code from this file:

 	./node_modules/openwhisk/lib/names.js:6

Read more here: http://bit.ly/2tRViJ9

allow initialization for host:port and determine protocol automatically

rather than init the api like this:

var ow = openwhisk({api: 'https://openwhisk.ng.bluemix.net/api/v1/', api_key: '...', namespace: 'default_namespace'});

I'd like to suggest a little bit of convenience:

var ow = openwhisk({apihost: 'openwhisk.ng.bluemix.net', api_key: '...', namespace: 'default_namespace'});

where apihost allows one to just provide either the host or host:port.
this can be split to determine protocol as in

var edgeHostParts = apihost.split(':');
var protocol = (edgeHostParts.length >= 2  &&  edgeHostParts[1] == '443') ? 'https' : 'http';
api = protocol + '://' + apihost + '/api/v1/';

Travis Test Breakage

Travis is currently failing for this repo due to a trigger test failure.

Test output:

  โœ– triggers โ€บ fire a trigger   
  t.true(update_result.hasOwnProperty('activationId'))
                       |                              
                       false                          
  1. triggers โ€บ fire a trigger
  AssertionError: false === true
    triggers.test.js:112:7
    process._tickCallback (internal/process/next_tick.js:109:7)

feature request: support "name" for get, invoke operations

right now, i find that my code is littered with things like:

Promise.all(triggers.map(trigger => ow.triggers.invoke({ triggerName: trigger.name })))

it seems preferable to me to write:

Promise.all(triggers.map(ow.triggers.invoke))

but i can't, because the get and invoke operations require triggerName, or actionName or packageName or ruleName rather than just name.

on top of this, having an invokeAll or getAll command would be nice, so that i could write

ow.packages.get('foo').then(package=>package.actions).then(ow.actions.getAll)

and having a simple projection mechanism would then simplify this to:

ow.packages.getActions('foo').then(ow.actions.getAll)

compare this to what we have now:

ow.packages.get('foo').then(package=>package.actions)
    .then(Promise.all(triggers.map(trigger=>ow.triggers.invoke({triggerName:trigger.name})))

3.13.1 release

Patch release to resolve bug in 3.13.0

release notes

3.13.1 (2018.03.15)

  • Fix support for string parameter in action.get API (#105)

process

  • npm version patch to bump package.json to 3.13.1
  • Push version commit and git tags to Github
  • Travis CI will auto-publish new version to NPM
  • Draft Github release from tags with notes above.

action.get does not return parameters bound to an action

Whisk's CLI returns parameters bound to an action when using "wsk action get" (in an array called "parameters" that has objects storing each parameter's name and value).

But the parameter information is gone in the nodeJS library when using actions.get - the parameters array is always empty (or only has an "_actions" object for a sequence action).

Are multiple openwhisk() objects supported ?

Greetings

I am looking into the JS api and have a question.

var options = {apihost: 'openwhisk.ng.bluemix.net', api_key: '...'};
var ow = openwhisk(options);

Is it possible to have multiple 'ow' objects , with different API key/Namespace combos in the same Node.js application?

Does the library have any global/singleton properties that preclude that kind of usage?

Thanks
pj

Actions test uses payload instead of params when sending JSON string

In the test for invoking an action using a JSON string (actions.test.js, line 413 ff) the JSON string is defined in a payload field, rather than in the params field. Furthermore, it is an empty object, which is equal to the default when no params are provided - so the test will always succeed.

Add tests to improve coverage of error handling

Is it possible that the current test suite has no coverage of error handling? Because

  1. earlier versions of PR #78 didn't do proper error handling, but all of the integration and functional tests passed

  2. with proper error handling, the PR still fails, because the codecov tool complains that the lines having to do with error handling (in my update) are not covered by tests!

regression: global namespace no longer matters

at some point a change was made that breaks code that relies on the global namespace field, i.e. the one provided with the openwhisk constructor.

now, the namespace is either the per-request options.namespace or names.default_namespace(), the latter of which does not pay attention to the global option:

const default_namespace = () => {
  return process.env['__OW_NAMESPACE'] || '_'
}

this breaks our code. luckily we are still pre-production, or this would've been a nightmare.

perhaps this: 9269e96

Deprecate "experimental" API Gateway

OpenWhisk's API Gateway service has moved from "experimental" to "release". The API path has changed between the versions.

The library has been updated to support both API endpoints recently, using a configuration parameter to control which one to use.

We need to remove the old API from the library. This will be a breaking change and need to be a major release.

allow default parameters when creating and updating actions

action.js does not allow to set {"parameters"}

wsk -v action create --kind nodejs:6 -p param pval helloAction7 helloAction.js
...
Body sent:
{"parameters": [{"value": "pval", "key": "param"}], "exec": {"kind": "nodejs:6", "code": "function main() {\n    return {payload: 'Hello world'};\n}\n"}}

Updated README with more examples.

The README is light on examples of using the library for common tasks, focusing more the API documentation.

We should re-work the file to add more of these common usecases to help developers.

People have recently been asking about retrieving package details, including credentials, invoking actions and triggers amongst others.

integration tests require manual setup and cleanup

In order for a dev to run the integration tests, one has to create seed artifacts manually. Further, if a test fails, its transient artifacts are not reclaimed. The integration tests should perform all required setup and cleanup on termination.

Add support for error response coming out of OpenWhisk action invocation

action being invoked:

function main(args) {
    return new Promise((resolve, reject) => { reject({ statusCode: 404 }) };
}

The invocation of this action through the REST API produces this response:

{
"error": {
"statusCode": 404
}
}

However OpenWhisk Client expect the statusCode to be at the top-level, and I think we should change this behavior to also support OpenWhisk error response.

Many Action Invocations: EPIPE / PROTOCOL_CONNECTION_LOST

Hi, I'm invoking many actions from inside a parent action over a long (3-5 mins) period of time. We're running against an on-premises OpenWhisk cluster. The code invoking the actions is along the lines of:

const invokeAction = (openwhisk, v) => {
    return openwhisk.actions.invoke({
        name: "my-action",
        params: { param: "val" },
        insecure: true,
        blocking: true  //different error depending on whether true or false
    });
};
const ow = openwhisk({ ignore_certs: true });
rxObservableEmittingMySqlData
    .bufferCount(1000) //buffer to accomodate 1MB max message size
    .zip(Observable.timer(0, 800) x => x) //this will add a .8s delay before each action invocation - without this, I get "too many actions for namespace"
    .flatMap(v => Observable.fromPromise(invokeAction(ow, v)), 30)  //where 30 is maximum concurrent in-flight requests - these problems occur regardless of this value
    .subscribe(console.log, reject, resolve);

Error If blocking = true:

"response": {
        "status": "application error",
        "statusCode": 0,
        "success": false,
        "result": {
            "error": {
                "error": {
                    "code": "EPIPE",
                    "errno": "EPIPE",
                    "syscall": "write"
                },
                "message": "Unknown Error From API: Error: write EPIPE",
                "name": "OpenWhiskError"
            }
        }
    }

Error If blocking = false:

{"fatal":true, "code": "PROTOCOL_CONNECTION_LOST"}

Even though more OW instances were added to our cluster, it also doesn't seem like the actions aren't completing quickly enough (even when I remove/reduce my throttling), and even if not for these errors I'd be hitting the 5 minute timeout.

Is this the wrong approach for handling millions of MySQL records with OpenWhisk? Is OW even the right tool for the job?

Create Trigger Feed failing with Check syntax errors message

Hi I'm trying the sample code:

create trigger feed from alarm package

// for example...
const params = {cron: '*/8 * * * * *', trigger_payload: {name: 'James'}}
const name = '/whisk.system/alarms/alarm'
const trigger = 'alarmTrigger'
ow.feeds.create({name, trigger, params}).then(package => {
console.log('alarm trigger feed created')
}).catch(err => {
console.error('failed to create alarm trigger', err)
})

This is giving me a failure:
failed to create alarm trigger { BaseOperationError: Action invocation failed, API returned error code. Check syntax errors? Missing error message.
at Client.handle_errors (/home/lzhao/openwhisk/code/openwhisk-package-ecs/node_modules/openwhisk/lib/client.js:102:13)
at rp.catch.err (/home/lzhao/openwhisk/code/openwhisk-package-ecs/node_modules/openwhisk/lib/client.js:43:38)
at tryCatcher (/home/lzhao/openwhisk/code/openwhisk-package-ecs/node_modules/bluebird/js/main/util.js:26:23)
at Promise._settlePromiseFromHandler (/home/lzhao/openwhisk/code/openwhisk-package-ecs/node_modules/bluebird/js/main/promise.js:510:31)
at Promise._settlePromiseAt (/home/lzhao/openwhisk/code/openwhisk-package-ecs/node_modules/bluebird/js/main/promise.js:584:18)
at Promise._settlePromises (/home/lzhao/openwhisk/code/openwhisk-package-ecs/node_modules/bluebird/js/main/promise.js:700:14)
at Async._drainQueue (/home/lzhao/openwhisk/code/openwhisk-package-ecs/node_modules/bluebird/js/main/async.js:123:16)
at Async._drainQueues (/home/lzhao/openwhisk/code/openwhisk-package-ecs/node_modules/bluebird/js/main/async.js:133:10)
at Immediate.Async.drainQueues (/home/lzhao/openwhisk/code/openwhisk-package-ecs/node_modules/bluebird/js/main/async.js:15:14)
at runCallback (timers.js:666:20)
at tryOnImmediate (timers.js:639:5)
at processImmediate [as _immediateCallback] (timers.js:611:5)
name: 'BaseOperationError',
message: 'Action invocation failed, API returned error code. Check syntax errors? Missing error message.',
error:
{ duration: 109,
name: 'alarm',
subject: 'whisk.system',
activationId: '20ae80ca53c24fa3886fb9a23e2ba16c',
publish: false,
annotations: [ [Object], [Object] ],
version: '0.0.5',
response: { result: [Object], success: false, status: 'application error' },
end: 1492115313980,
logs: [],
start: 1492115313871,
namespace: 'whisk.system' } }

Can you let me know why this is not working? I am able to use the sample snippets to create an action without any problems but I'm not able to do it for an alarm

Improve Developer Experience when errors occur

If the platform returns an API error, the library parses any error text and wraps it in a generic error response.

Here's an example of creating an action for an invalid namespace.

{
  "error": {
    "name": "BaseOperationError",
    "message": "OpenWhisk authentication failed, check API key? The supplied authentication is not authorized to access this resource.",
    "error": {
      "error": "The supplied authentication is not authorized to access this resource.",
      "code": 5170570
    }
  }
}

This does not give the developer much help to understand where the error occurred and why.

Ideas for improving this from @starpit

  • Provide more descriptive names in error message, rather than BaseOperationError.
  • Add HTTP path for failing response into the error message.
  • Stack trace should match error site.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.