Merge branch 'master' into allow-self-reference

# Conflicts:
#	lib/classes/Error.js
This commit is contained in:
Erik Erikson 2017-02-08 15:51:57 -08:00
commit 7376fc0dff
62 changed files with 2919 additions and 124 deletions

View File

@ -6,7 +6,7 @@
## What did you implement:
Closes #12345
Closes #XXXXX
<!--
Briefly describe the feature if no issue exists for this PR
@ -32,17 +32,15 @@ Examples:
* Other - Anything else that comes to mind to help us evaluate
-->
## Todos:
- [ ] Write tests
- [ ] Write documentation
- [ ] Fix linting errors
- [ ] Make sure code coverage hasn't dropped
- [ ] Provide verification config/commands/resources
- [ ] Enable ["Allow edits from maintainers"](https://help.github.com/articles/allowing-changes-to-a-pull-request-branch-created-from-a-fork/) for this PR
- [ ] Change ready for review message below
- [ ] Provide verification config / commands / resources
- [ ] Enable "Allow edits from maintainers" for this PR
- [ ] Update the messages below
***Is this ready for review?:*** NO
***Is it a breaking change?:*** NO

View File

@ -1,3 +1,42 @@
# 1.6.1 (31.01.2017)
A minimal patch release that fixes an issue with rendering README.md on npm registry.
# 1.6.0 (30.01.2017)
**Important Note:** This release includes breaking changes. If your services stopped working after upgrading to v1.6.0, please read the following section.
## Breaking Changes
### CloudWatch logs are created explicitly
Up until this release, CloudWatch log groups were created implicitly by AWS/Lambda by default and were not included in your service stack. However, some users were able to easily reach the CloudWatch log group limits (currently at 500 log groups), and it wasn't an easy task to clear them all. Because of that we decided to explicitly create the log groups using CloudFormation so that you can easily remove them with `sls remove`. This was also optionally possible with the `cfLogs: true` config option.
If your service doesn't have the `cfLogs: true` set, and one of the function has been invoked at least once (hence the log groups were created implicitly by AWS), then it's very likely that you'll receive a "log group already exists" error after upgrading to v1.6.0. That's because CF is now trying to create the already created log groups from scratch to include it in the stack resources. **To fix this breaking change,** simply delete the old log group, or rename your service if you **must** keep the old logs.
### Removed function Arns from CloudFormation outputs
Up until this release, the output section of the generated CloudFormation template included an output resource for each function Arn. This caused deploying big services to fail because users were hitting the 60 outputs per stack limit. This effectively means that you can't have a service that has more than 60 functions. To avoid this AWS limit, we decided to remove those function output resources completely, to keep the stack clean. This also means removing the function Arns from the `sls info` command, and at the end of the deployment command.
This is a breaking change for your project if you're depending on those function output resources in anyway, or if you're depending on function arn outputs from the deploy or info commands. Otherwise, your project shouldn't be affected by this change. Fixing this issue depends on your needs, but just remember that you can always create your own CF outputs in `serverless.yml`.
### Moved `getStackName()` method
This is a breaking change for plugin authors only. If your plugin used the `provider.getStackName()` method, it has been moved to `naming.js`, and should be referenced with `provider.naming.getStackName()` instead.
### Removed the `defaults` property from `serverless.yml`
We've finally dropped support for the `defaults` property which we introduced in v1. All child properties should now be moved to the `provider` object instead.
## Non-breaking changes
- Reduce memory consumption on deploy by at least 50% (#3145)
- Added openwhisk template to `sls create` command (#3122)
- Allow Role 'Fn::GetAtt' for Lambda `role` (#3083)
- Added Access-Control-Allow-Credentials for CORS settings (#2736)
- add Support for SNS Subscription to existing topics (#2796)
- Function version resources are now optional. (#3042)
- Invoke local now supports python runtime. (#2937)
- Fixed "deployment bucket doesn't exist" error (#3107)
- Allowed function events value to be variables (#2434)
## Meta
- [Comparison since last release](https://github.com/serverless/serverless/compare/v1.5.1...v1.6.0)
# 1.5.1 (19.01.2017)
## Bug Fixes

View File

@ -106,6 +106,7 @@ The following are services you can instantly install and use by running `serverl
* [serverless-examples](https://github.com/serverless/examples)
* [CRUD](https://github.com/pmuens/serverless-crud) - CRUD service, [Scala Port](https://github.com/jahangirmohammed/serverless-crud-scala)
* [CRUD with FaunaDB](https://github.com/faunadb/serverless-crud) - CRUD service using FaunaDB
* [CRUD with S3](https://github.com/tscanlin/serverless-s3-crud) - CRUD service using S3
* [GraphQL Boilerplate](https://github.com/serverless/serverless-graphql) - GraphQL application Boilerplate service
* [Authentication](https://github.com/laardee/serverless-authentication-boilerplate) - Authentication boilerplate service
@ -158,7 +159,7 @@ This table is generated from https://github.com/serverless/plugins/blob/master/p
| **[Serverless Crypt](https://github.com/marcy-terui/serverless-crypt)** <br/> Securing the secrets on Serverless Framework by AWS KMS encryption. | [marcy-terui](http://github.com/marcy-terui) |
| **[Serverless Dotnet](https://github.com/fruffin/serverless-dotnet)** <br/> A serverless plugin to run 'dotnet' commands as part of the deploy process | [fruffin](http://github.com/fruffin) |
| **[Serverless Dynamodb Local](https://github.com/99xt/serverless-dynamodb-local)** <br/> Serverless Dynamodb Local Plugin - Allows to run dynamodb locally for serverless | [99xt](http://github.com/99xt) |
| **[Serverless Enable Api Logs](https://github.com/paulSambolin/serverless-enable-api-logs)** <br/> Enables Coudwatch logging for API Gateway events | [paulSambolin](http://github.com/paulSambolin) |
| **[Serverless Enable Api Logs](https://github.com/paulSambolin/serverless-enable-api-logs)** <br/> Enables Cloudwatch logging for API Gateway events | [paulSambolin](http://github.com/paulSambolin) |
| **[Serverless Event Constant Inputs](https://github.com/dittto/serverless-event-constant-inputs)** <br/> Allows you to add constant inputs to events in Serverless 1.0. For more info see [constant values in Cloudwatch](https://aws.amazon.com/blogs/compute/simply-serverless-use-constant-values-in-cloudwatch-event-triggered-lambda-functions/) | [dittto](http://github.com/dittto) |
| **[Serverless Jest Plugin](https://github.com/SC5/serverless-jest-plugin)** <br/> A Serverless Plugin for the Serverless Framework which adds support for test-driven development using Jest | [SC5](http://github.com/SC5) |
| **[Serverless Mocha Plugin](https://github.com/SC5/serverless-mocha-plugin)** <br/> A Serverless Plugin for the Serverless Framework which adds support for test-driven development using Mocha | [SC5](http://github.com/SC5) |

View File

@ -10,13 +10,13 @@ layout: Doc
# Documentation
The Serverless Framework allows you to deploy auto-scaling, pay-per-execution, event-driven functions to any cloud. We currently support Amazon Web Service's Lambda, and are expanding to support other cloud providers.
The Serverless Framework allows you to deploy auto-scaling, pay-per-execution, event-driven functions to any cloud. We currently support AWS Lambda, IBM OpenWhisk, and are expanding to support other cloud providers.
<div class="docsSections">
<div class="docsSection">
<div class="docsSectionHeader">
<a href="./providers/aws/guide/">
<img src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/docs_guide_aws5.jpg" alt="Serverless Framework AWS Lambda Guide" width="250" draggable="false"/>
<img src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/sls_aws_guide.png" alt="Serverless Framework AWS Lambda Guide" width="250" draggable="false"/>
</a>
</div>
<div class="test">
@ -43,7 +43,7 @@ The Serverless Framework allows you to deploy auto-scaling, pay-per-execution, e
<div class="docsSection">
<div class="docsSectionHeader">
<a href="./providers/aws/cli-reference/">
<img src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/docs_clireference_aws4.jpg" alt="Serverless Framework AWS Lambda CLI Reference" width="250" draggable="false"/>
<img src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/sls_aws_cli.png" alt="Serverless Framework AWS Lambda CLI Reference" width="250" draggable="false"/>
</a>
</div>
<div>
@ -69,7 +69,7 @@ The Serverless Framework allows you to deploy auto-scaling, pay-per-execution, e
<div class="docsSection">
<div class="docsSectionHeader">
<a href="./providers/aws/events/">
<img src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/docs_events_aws4.jpg" alt="Serverless Framework AWS Lambda Events" width="250" draggable="false"/>
<img src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/sls_aws_events.png" alt="Serverless Framework AWS Lambda Events" width="250" draggable="false"/>
</a>
</div>
<div>
@ -88,7 +88,7 @@ The Serverless Framework allows you to deploy auto-scaling, pay-per-execution, e
<div class="docsSection">
<div class="docsSectionHeader">
<a href="./providers/aws/examples/">
<img src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/docs_examples_aws4.jpg" alt="Serverless Framework AWS Lambda Examples" width="250" draggable="false"/>
<img src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/sls_aws_examples.png" alt="Serverless Framework AWS Lambda Examples" width="250" draggable="false"/>
</a>
</div>
<div>
@ -100,3 +100,83 @@ The Serverless Framework allows you to deploy auto-scaling, pay-per-execution, e
</div>
</div>
</div>
<div class="docsSections">
<div class="docsSection">
<div class="docsSectionHeader">
<a href="./providers/openwhisk/guide/">
<img src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/docs_guide_openwhisk.jpg" alt="Serverless Framework IBM OpenWhisk Guide" width="250" draggable="false"/>
</a>
</div>
<div class="test">
<ul>
<li><a href="./providers/openwhisk/guide/intro.md">Intro</a></li>
<li><a href="./providers/openwhisk/guide/installation.md">Installation</a></li>
<li><a href="./providers/openwhisk/guide/credentials.md">Credentials</a></li>
<li><a href="./providers/openwhisk/guide/services.md">Services</a></li>
<li><a href="./providers/openwhisk/guide/functions.md">Functions</a></li>
<li><a href="./providers/openwhisk/guide/events.md">Events</a></li>
<li><a href="./providers/openwhisk/guide/deploying.md">Deploying</a></li>
<li><a href="./providers/openwhisk/guide/testing.md">Testing</a></li>
<li><a href="./providers/openwhisk/guide/variables.md">Variables</a></li>
<li><a href="./providers/openwhisk/guide/packaging.md">Packaging</a></li>
<li><a href="./providers/openwhisk/guide/plugins.md">Plugins</a></li>
<li><a href="./providers/openwhisk/guide/workflow.md">Workflow</a></li>
<li><a href="./providers/openwhisk/guide/serverless.yml.md">Serverless.yml</a></li>
</ul>
</div>
</div>
<div class="docsSection">
<div class="docsSectionHeader">
<a href="./providers/openwhisk/cli-reference/">
<img src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/docs_cli_openwhisk.jpg" alt="Serverless Framework IBM OpenWhisk CLI Reference" width="250" draggable="false"/>
</a>
</div>
<div>
<ul>
<li><a href="./providers/openwhisk/cli-reference/config-credentials.md">Config Credentials</a></li>
<li><a href="./providers/openwhisk/cli-reference/create.md">Create</a></li>
<li><a href="./providers/openwhisk/cli-reference/install.md">Install</a></li>
<li><a href="./providers/openwhisk/cli-reference/deploy.md">Deploy</a></li>
<li><a href="./providers/openwhisk/cli-reference/deploy-function.md">Deploy Function</a></li>
<li><a href="./providers/openwhisk/cli-reference/invoke.md">Invoke</a></li>
<li><a href="./providers/openwhisk/cli-reference/invoke-local.md">Invoke Local</a></li>
<li><a href="./providers/openwhisk/cli-reference/logs.md">Logs</a></li>
<li><a href="./providers/openwhisk/cli-reference/info.md">Info</a></li>
<li><a href="./providers/openwhisk/cli-reference/remove.md">Remove</a></li>
<li><a href="./providers/openwhisk/cli-reference/slstats.md">Serverless Stats</a></li>
</ul>
</div>
</div>
<div class="docsSection">
<div class="docsSectionHeader">
<a href="./providers/openwhisk/events/">
<img src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/docs_events_openwhisk.jpg" alt="Serverless Framework IBM OpenWhisk Events" width="250" draggable="false"/>
</a>
</div>
<div>
<ul>
<li><a href="./providers/openwhisk/events/apigateway.md">API Gateway</a></li>
<li><a href="./providers/openwhisk/events/schedule.md">Schedule</a></li>
<li><a href="./providers/openwhisk/events/triggers.md">Triggers</a></li>
</ul>
</div>
</div>
<div class="docsSection">
<div class="docsSectionHeader">
<a href="./providers/openwhisk/examples/">
<img src="https://s3-us-west-2.amazonaws.com/assets.site.serverless.com/images/docs_examples_openwhisk.jpg" alt="Serverless Framework IBM OpenWhisk Examples" width="250" draggable="false"/>
</a>
</div>
<div>
<div>
<ul>
<li><a href="./providers/openwhisk/examples/hello-world">Hello World</a></li>
</ul>
</div>
</div>
</div>
</div>

View File

@ -61,3 +61,18 @@ This example will pass the json data in the `lib/data.json` file (relative to th
### Limitations
Currently, `invoke local` only supports the NodeJs and Python runtimes.
## Resource permissions
Lambda functions assume an *IAM role* during execution: the framework creates this role, and set all the permission provided in the `iamRoleStatements` section of `serverless.yml`.
Unless you explicitly state otherwise, every call to the AWS SDK inside the lambda function is made using this role (a temporary pair of key / secret is generated and set by AWS as environment variables, `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`).
When you use `serverless invoke local`, the situation is quite different: the role isn't available (the function is executed on your local machine), so unless you set a different user directly in the code (or via a key pair of environment variables), the AWS SDK will use the default profile specified inside you AWS credential configuration file.
Take a look to the official AWS documentation (in this particular instance, for the javascript SDK, but should be similar for all SDKs):
- [http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-shared.html](http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-shared.html)
- [http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-lambda.html](http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-lambda.html)
Whatever approach you decide to implement, **be aware**: the set of permissions might be (and probably is) different, so you won't have an exact simulation of the *real* IAM policy in place.

View File

@ -277,11 +277,11 @@ provider:
- ${env:MY_API_KEY} # you can hide it in a serverless variable
functions:
hello:
events:
- http:
path: user/create
method: get
private: true
events:
- http:
path: user/create
method: get
private: true
```
Please note that those are the API keys names, not the actual values. Once you deploy your service, the value of those API keys will be auto generated by AWS and printed on the screen for you to use.

View File

@ -104,6 +104,28 @@ provider:
profile: devProfile
```
##### Use an existing AWS Profile
To easily switch between projects without the need to do `aws configure` every time you can use environment variables.
For example you define different profiles in `~/.aws/credentials`
```ini
[profileName1]
aws_access_key_id=***************
aws_secret_access_key=***************
[profileName2]
aws_access_key_id=***************
aws_secret_access_key=***************
```
Now you can switch per project (/ API) by executing once when you start your project:
`export AWS_PROFILE="profileName2" && export AWS_REGION=eu-west-1`.
in the Terminal. Now everything is set to execute all the `serverless` CLI options like `sls deploy`.
The AWS region setting is to prevent issues with specific services, so adapt if you need another default region.
#### Per Stage Profiles
As an advanced use-case, you can deploy different stages to different accounts by using different profiles per stage. In order to use different profiles per stage, you must leverage [variables](https://serverless.com/framework/docs/providers/aws/guide/variables) and the provider profile setting.

View File

@ -36,7 +36,7 @@ You can perform multiple jobs in your code, but we don't recommend doing that wi
Anything that triggers an AWS Lambda Function to execute is regarded by the Framework as an **Event**. Events are infrastructure events on AWS such as:
* *An AWS API Gateway HTTP endpoint (e.g., for a REST API)*
* *An AWS API Gateway HTTP endpoint request (e.g., for a REST API)*
* *An AWS S3 bucket upload (e.g., for an image)*
* *A CloudWatch timer (e.g., run every 5 minutes)*
* *An AWS SNS topic (e.g., a message)*

View File

@ -0,0 +1,19 @@
<!--
title: Serverless - Apache OpenWhisk Documentation
menuText: OpenWhisk
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/)
<!-- DOCS-SITE-LINK:END -->
# Serverless Apache OpenWhisk Provider Documentation
Welcome to the Serverless Apache OpenWhisk documentation!
Please select a section on the left to get started.
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](https://gitter.im/serverless/serverless)
**Note:** Before continuing [Apache OpenWhisk system credentials](./guide/credentials.md) are required for using the CLI.

View File

@ -0,0 +1,17 @@
<!--
title: Serverless - Apache OpenWhisk - CLI Reference
menuText: OpenWhisk
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/)
<!-- DOCS-SITE-LINK:END -->
# Serverless Apache OpenWhisk CLI Reference
Welcome to the Serverless Apache OpenWhisk CLI Reference! Please select a section on the left to get started.
**Note:** Before continuing [Apache OpenWhisk system credentials](../guide/credentials.md) are required for using the CLI.
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](http://forum.serverless.com/).

View File

@ -0,0 +1,37 @@
<!--
title: Serverless Framework Commands - Apache OpenWhisk - Config Credentials
menuText: Config Credentials
menuOrder: 1
description: Configure Serverless credentials
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/config-credentials)
<!-- DOCS-SITE-LINK:END -->
# Config Credentials
```bash
serverless config credentials --provider provider --apihost apihost --auth auth
```
## Options
- `--provider` or `-p` The provider (in this case `openwhisk`). **Required**.
- `--apihost` or `-h` The `openwhisk_apihost`. **Required**.
- `--auth` or `-a` The `openwhisk_auth`. **Required**.
## Provided lifecycle events
- `config:credentials:config`
## Examples
### Configure the default profile
```bash
serverless config credentials --provider openwhisk --apihost openwhisk.ng.bluemix.net --auth username:password
```
Credentials are stored in `~/.wskprops`, which you can edit directly if needed.

View File

@ -0,0 +1,78 @@
<!--
title: Serverless Framework Commands - Apache OpenWhisk - Create
menuText: Create
menuOrder: 2
description: Creates a new Service in your current working directory
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/create)
<!-- DOCS-SITE-LINK:END -->
# Create
Creates a new service in the current working directory based on the provided template.
**Create service in current working directory:**
```bash
serverless create --template openwhisk-nodejs
```
**Create service in new folder:**
```bash
serverless create --template openwhisk-nodejs --path myService
```
## Options
- `--template` or `-t` The name of one of the available templates. **Required**.
- `--path` or `-p` The path where the service should be created.
- `--name` or `-n` the name of the service in `serverless.yml`.
## Provided lifecycle events
- `create:create`
## Available Templates
To see a list of available templates run `serverless create --help`
Most commonly used templates:
- openwhisk-nodejs
- plugin
## Examples
### Creating a new service
```bash
serverless create --template openwhisk-nodejs --name my-special-service
```
This example will generate scaffolding for a service with `openwhisk` as a provider and `nodejs:6` as runtime. The scaffolding
will be generated in the current working directory.
The provider which is used for deployment later on is Apache OpenWhisk.
### Creating a named service in a (new) directory
```bash
serverless create --template openwhisk-nodejs --path my-new-service
```
This example will generate scaffolding for a service with `openwhisk` as a provider and `nodejs` as runtime. The scaffolding
will be generated in the `my-new-service` directory. This directory will be created if not present. Otherwise Serverless
will use the already present directory.
Additionally Serverless will rename the service according to the path you provide. In this example the service will be
renamed to `my-new-service`.
### Creating a new plugin
```
serverless create --template plugin
```
This example will generate scaffolding for a hello world plugin that demonstrates how to create a new command and how to listen to the various events available.

View File

@ -0,0 +1,22 @@
<!--
title: Serverless Framework Commands - Apache OpenWhisk - Deploy Function
menuText: Deploy Function
menuOrder: 5
description: Deploy your Apache OpenWhisk functions quickly
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/deploy-function)
<!-- DOCS-SITE-LINK:END -->
# Deploy Function
The `sls deploy function` command deploys an individual function. This command simply compiles a deployment package with a single function handler. This is a much faster way of deploying changes in code.
```bash
serverless deploy function -f functionName
```
## Options
- `--function` or `-f` The name of the function which should be deployed

View File

@ -0,0 +1,48 @@
<!--
title: Serverless Framework Commands - Apache OpenWhisk - Deploy
menuText: Deploy
menuOrder: 4
description: Deploy your service to the specified provider
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/deploy)
<!-- DOCS-SITE-LINK:END -->
# Deploy
The `sls deploy` command deploys your entire service via the Apache OpenWhisk platform API. Run this command when you have made service changes (i.e., you edited `serverless.yml`). Use `serverless deploy function -f myFunction` when you have made code changes and you want to quickly upload your updated code to Apache OpenWhisk.
```bash
serverless deploy
```
## Options
- `--noDeploy` or `-n` Skips the deployment steps and leaves artifacts in the `.serverless` directory
- `--verbose` or `-v` Shows all stack events during deployment, and display any Stack Output.
## Artifacts
After the `serverless deploy` command runs all created deployment artifacts are placed in the `.serverless` folder of the service.
## Examples
### Deployment without stage and region options
```bash
serverless deploy
```
This is the simplest deployment usage possible. With this command Serverless will deploy your service to the defined
OpenWhisk platform endpoints.
## Provided lifecycle events
- `deploy:cleanup`
- `deploy:initialize`
- `deploy:setupProviderConfiguration`
- `deploy:createDeploymentArtifacts`
- `deploy:compileFunctions`
- `deploy:compileEvents`
- `deploy:deploy`
- `deploy:function:deploy`

View File

@ -0,0 +1,56 @@
<!--
title: Serverless Framework Commands - Apache OpenWhisk - Info
menuText: Info
menuOrder: 11
description: Display information about your deployed service and the Apache OpenWhisk Functions, Events and Resources it contains.
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/info)
<!-- DOCS-SITE-LINK:END -->
# Info
Displays information about the deployed service.
```bash
serverless info
```
## Options
- `--verbose` or `-v` Shows displays any Stack Output.
## Provided lifecycle events
- `info:info`
## Examples
### Apache OpenWhisk
On Apache OpenWhisk the info plugin uses platform API to gather the necessary
information about deployed functions, events, routes and more. See the example
below for an example output.
**Example:**
```bash
$ serverless info
Service Information
platform: openwhisk.ng.bluemix.net
namespace: _
service: hello-world
actions:
hello-world-dev-helloWorld
triggers:
my-hello-world-event
rules:
my-hello-world-event-rule
endpoints:
https://xyz1234-gws.api-gw.mybluemix.net
/hello-world GET -> hello-world
```

View File

@ -0,0 +1,53 @@
<!--
title: Serverless Framework Commands - Apache OpenWhisk - Install
menuText: Install
menuOrder: 3
description: Install pre-written Apache OpenWhisk Functions, Events and Resources with the Serverless Framework
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/install)
<!-- DOCS-SITE-LINK:END -->
# Install
Installs a service from a GitHub URL in the current working directory.
```bash
serverless install --url https://github.com/some/service
```
## Options
- `--url` or `-u` The services GitHub URL. **Required**.
- `--name` or `-n` Name for the service.
## Provided lifecycle events
- `install:install`
## Examples
### Installing a service from a GitHub URL
```bash
serverless install --url https://github.com/jthomas/serverless-openwhisk-boilerplate
```
This example will download the .zip file of the `serverless-openwhisk-boilerplate` service from GitHub, create a new directory with the name `serverless-openwhisk-boilerplate` in the current working directory and unzips the files in this directory.
### Installing a service from a GitHub URL with a new service name
```bash
serverless install --url https://github.com/jthomas/serverless-openwhisk-boilerplate --name my-app
```
This example will download the .zip file of the `serverless-openwhisk-boilerplate` service from GitHub, create a new directory with the name `my-app` in the current working directory and unzips the files in this directory and renames the service to `my-app` if `serverless.yml` exists in the service root.
### Installing a service from a directory in a GitHub URL
```bash
serverless install --url
https://github.com/serverless/examples/tree/master/openwhisk-node-simple
```
This example will download the `openwhisk-node-simple` service from GitHub.

View File

@ -0,0 +1,63 @@
<!--
title: Serverless Framework Commands - Apache OpenWhisk - Invoke Local
menuText: Invoke Local
menuOrder: 8
description: Emulate an invocation of your Apache OpenWhisk function locally using the Serverless Framework
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/invoke-local)
<!-- DOCS-SITE-LINK:END -->
# Invoke Local
This runs your code locally by emulating the Apache OpenWhisk environment. Please keep in mind, it's not a 100% perfect emulation, there may be some differences, but it works for the vast majority of users.
```bash
serverless invoke local --function functionName
```
## Options
- `--function` or `-f` The name of the function in your service that you want to invoke locally. **Required**.
- `--path` or `-p` The path to a json file holding input data to be passed to the invoked function. This path is relative to the root directory of the service. The json file should have event and context properties to hold your mocked event and context data.
- `--data` or `-d` String data to be passed as an event to your function. Keep in mind that if you pass both `--path` and `--data`, the data included in the `--path` file will overwrite the data you passed with the `--data` flag.
## Examples
### Local function invocation
```bash
serverless invoke local --function functionName
```
This example will locally invoke your function.
### Local function invocation with data
```bash
serverless invoke --function functionName --data "hello world"
```
```bash
serverless invoke --function functionName --data '{"a":"bar"}'
```
### Local function invocation with data from standard input
```bash
node dataGenerator.js | serverless invoke local --function functionName
```
### Local function invocation with data passing
```bash
serverless invoke local --function functionName --path lib/data.json
```
This example will pass the json data in the `lib/data.json` file (relative to the root of the service) while invoking the specified/deployed function.
### Limitations
Currently, `invoke local` only supports the NodeJs

View File

@ -0,0 +1,83 @@
<!--
title: Serverless Framework Commands - Apache OpenWhisk - Invoke
menuText: Invoke
menuOrder: 7
description: Invoke an Apache OpenWhisk Function using the Serverless Framework
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/invoke)
<!-- DOCS-SITE-LINK:END -->
# Invoke
Invokes deployed function. It allows to send event data to the function, read logs and display other important information of the function invocation.
```bash
serverless invoke [local] --function functionName
```
## Options
- `--function` or `-f` The name of the function in your service that you want to invoke. **Required**.
- `--data` or `-d` String data to be passed as an event to your function. By default data is read from standard input.
- `--path` or `-p` The path to a json file with input data to be passed to the invoked function. This path is relative to the root directory of the service.
- `--type` or `-t` The type of invocation. Either `RequestResponse`, `Event` or `DryRun`. Default is `RequestResponse`.
- `--log` or `-l` If set to `true` and invocation type is `RequestResponse`, it will output logging data of the invocation. Default is `false`.
## Provided lifecycle events
- `invoke:invoke`
# Invoke Local
Invokes a function locally for testing and logs the output. You can only invoke Node.js runtime locally at the moment. Keep in mind that we mock the `context` with simple mock data.
```bash
serverless invoke local --function functionName
```
## Options
- `--function` or `-f` The name of the function in your service that you want to invoke locally. **Required**.
- `--path` or `-p` The path to a json file holding input data to be passed to the invoked function. This path is relative to the
root directory of the service. The json file should have event and context properties to hold your mocked event and context data.
- `--data` or `-d` String data to be passed as an event to your function. Keep in mind that if you pass both `--path` and `--data`, the data included in the `--path` file will overwrite the data you passed with the `--data` flag.
## Examples
### Apache OpenWhisk
```bash
serverless invoke --function functionName
```
This example will invoke your deployed function on the configured platform
endpoint. This will output the result of the invocation in your terminal.
#### Function invocation with data
```bash
serverless invoke --function functionName --data '{"name": "Bernie"}'
```
#### Function invocation with data from standard input
```bash
node dataGenerator.js | serverless invoke --function functionName
```
#### Function invocation with logging
```bash
serverless invoke --function functionName --log
```
Just like the first example, but will also outputs logging information about your invocation.
#### Function invocation with data passing
```bash
serverless invoke --function functionName --path lib/data.json
```
This example will pass the json data in the `lib/data.json` file (relative to the root of the service) while invoking
the specified/deployed function.

View File

@ -0,0 +1,75 @@
<!--
title: Serverless Framework Commands - Apache OpenWhisk - Logs
menuText: Logs
menuOrder: 9
description: View logs of your Apache OpenWhisk Function within your terminal using the Serverless Framework
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/logs)
<!-- DOCS-SITE-LINK:END -->
# Logs
Lets you watch the logs of a specific function.
```bash
serverless logs -f hello
```
## Options
- `--function` or `-f` The function you want to fetch the logs for. **Required**
- `--startTime` A specific unit in time to start fetching logs from (ie: `2010-10-20` or `1469705761`). Here's a list of the supported string formats:
```bash
30m # since 30 minutes ago
2h # since 2 hours ago
3d # since 3 days ago
2013-02-08 # A calendar date part
2013-W06-5 # A week date part
2013-039 # An ordinal date part
20130208 # Basic (short) full date
2013W065 # Basic (short) week, weekday
2013W06 # Basic (short) week only
2013050 # Basic (short) ordinal date
2013-02-08T09 # An hour time part separated by a T
20130208T080910,123 # Short date and time up to ms, separated by comma
20130208T080910.123 # Short date and time up to ms
20130208T080910 # Short date and time up to seconds
20130208T0809 # Short date and time up to minutes
20130208T08 # Short date and time, hours only
```
- `--filter` You can specify a filter string to filter the log output. This is useful if you want to to get the `error` logs for example.
- `--tail` or `-t` You can optionally tail the logs and keep listening for new logs in your terminal session by passing this option.
- `--interval` or `-i` If you choose to tail the output, you can control the interval at which the framework polls the logs with this option. The default is `1000`ms.
## Examples
### Apache OpenWhisk
```bash
serverless logs -f hello --startTime 5h
```
This will fetch the logs that happened in the past 5 hours.
```bash
serverless logs -f hello --startTime 1469694264
```
This will fetch the logs that happened starting at epoch `1469694264`.
```bash
serverless logs -f hello -t
```
Serverless will tail the platform log output and print new log messages coming in.
```bash
serverless logs -f hello --filter serverless
```
This will fetch only the logs that contain the string `serverless`

View File

@ -0,0 +1,32 @@
<!--
title: Serverless Framework Commands - Apache OpenWhisk - Remove
menuText: Remove
menuOrder: 13
description: Remove a deployed Service and all of its Apache OpenWhisk Functions, Events and Resources
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/remove)
<!-- DOCS-SITE-LINK:END -->
# Remove
The `sls remove` command will remove the deployed service, defined in your current working directory, from the provider.
```bash
serverless remove
```
## Provided lifecycle events
- `remove:remove`
## Examples
### Removal of service in specific stage and region
```bash
serverless remove
```
This example will remove the deployed service of your current working directory from the current platform endpoint.

View File

@ -0,0 +1,36 @@
<!--
title: Serverless Framework Commands - Apache OpenWhisk - Serverless Stats
menuText: Serverless Stats
menuOrder: 14
description: Enables or disables Serverless Statistic logging within the Serverless Framework.
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/cli-reference/slstats)
<!-- DOCS-SITE-LINK:END -->
# Serverless Statistics
This plugin implements a way to toggle framework statistics.
```bash
serverless slstats --enable
```
## Options
- `--enable` or `-e`.
- `--disable` or `-d`
## Provided lifecycle events
- `slstats:slstats`
## Examples
### Disabling it
```bash
serverless slstats --disable
```
This example will disable framework statistics.

View File

@ -0,0 +1,19 @@
<!--
title: Serverless - Apache OpenWhisk - Events
menuText: OpenWhisk
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/events/)
<!-- DOCS-SITE-LINK:END -->
# Serverless Apache OpenWhisk Events
Welcome to the Serverless Apache OpenWhisk Events Glossary!
Please select a section on the left to get started.
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](http://forum.serverless.com/)
**Note:** Before continuing [Apache OpenWhisk system credentials](../guide/credentials.md) are required for using the CLI.

View File

@ -0,0 +1,119 @@
<!--
title: Serverless Framework - Apache OpenWhisk Events - API Gateway
menuText: API Gateway
menuOrder: 1
description: Setting up API Gateway Events with Apache OpenWhisk via the Serverless Framework
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/events/apigateway)
<!-- DOCS-SITE-LINK:END -->
# API Gateway
Apache OpenWhisk has an [API gateway](https://github.com/openwhisk/openwhisk/blob/master/docs/apigateway.md) included within the platform. This service
allows you to define public HTTP endpoints for your serverless functions.
To create HTTP endpoints as Event sources for your Apache OpenWhisk Functions, use the Serverless Framework's easy API Gateway Events syntax.
## API Gateway Events
### Simple HTTP Endpoint
This setup specifies that the `hello` function should be run when someone accesses the API gateway at `example/hello` via
a `GET` request.
Here's an example:
```yml
# serverless.yml
functions:
example:
handler: handler.hello
events:
- http: GET hello
```
URL paths for the serverless functions are prefixed with the function name, e.g.
`/function_name/some/path`.
```javascript
// handler.js
'use strict';
module.exports.hello = function(params) {
// Your function handler
return { payload: 'Hello world!' };
};
```
When this service is deployed, the base API Gateway url will be
printed to the console. Combine this with your custom HTTP path to create
the full HTTP endpoint exposing your serverless function.
```
$ serverless deploy
...
Serverless: Configured API endpoint: https://xxx-yyy-gws.api-gw.mybluemix.net/example
$ http get https://xxx-yyy-gws.api-gw.mybluemix.net/example/hello
{
"payload": "Hello, World!"
}
```
### HTTP Endpoint with Parameters
Here we've defined an POST endpoint for the path `posts/create`.
```yml
# serverless.yml
functions:
greeting:
handler: greeting.handler
events:
- http: POST greeting/generate
```
```javascript
// posts.js
'use strict';
module.exports.handler = function(params) {
const name = params.name || 'stranger';
// Your function handler
return { payload: `Hello ${name}!` };
};
```
The body of the incoming request is parsed as JSON and passed as the
`params` argument to the function handler.
The returned JavaScript object will be serialised as JSON and returned in the
HTTP response body.
### HTTP Endpoint with Extended Options
Here we've defined an POST endpoint for the path `posts/create`.
```yml
# serverless.yml
functions:
create:
handler: posts.create
events:
- http:
path: posts/create
method: post
```
### CORS Support
**Note:** All HTTP endpoints defined in this manner have cross-site requests
enabled for all source domains.

View File

@ -0,0 +1,57 @@
<!--
title: Serverless Framework - Apache OpenWhisk Events - Scheduled & Recurring
menuText: Schedule
menuOrder: 4
description: Setting up Scheduled, Recurring, CRON Task Events with Apache OpenWhisk via the Serverless Framework
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/events/schedule)
<!-- DOCS-SITE-LINK:END -->
# Schedule
This event allows you to set up scheduled invocations of your function.
The plugin automatically configures a trigger and rule to connect your function
to the trigger feed from the [alarm package](https://github.com/openwhisk/openwhisk/blob/master/docs/catalog.md#using-the-alarm-package).
## Configuration
The `schedule` event configuration is controlled by a string, based on the UNIX
crontab syntax, in the format `cron(X X X X X)`. This can either be passed in
as a native string or through the `rate` parameter.
### Simple
The following config will attach a schedule event and causes the function `crawl` to be called every minute.
```yaml
functions:
crawl:
handler: crawl
events:
- schedule: cron(* * * * * *) // run every minute
```
This automatically generates a new trigger (``${service}_crawl_schedule_trigger`)
and rule (`${service}_crawl_schedule_rule`) during deployment.
### Customise Parameters
Other schedule event parameters can be manually configured, e.g trigger or rule names.
```yaml
functions:
aggregate:
handler: statistics.handler
events:
- schedule:
rate: cron(0 * * * *) // call once an hour
trigger: triggerName
rule: ruleName
max: 10000 // max invocations, default: 1000, max: 10000
params: // event params for invocation
hello: world
```

View File

@ -0,0 +1,82 @@
<!--
title: Serverless Framework - Apache OpenWhisk Events - Triggers
menuText: Triggers
menuOrder: 2
description: Setting up Apache OpenWhisk Triggers and Rules for Function Events
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/events/streams)
<!-- DOCS-SITE-LINK:END -->
# Triggers
Functions are connected to event sources in OpenWhisk [using triggers and rules](https://github.com/openwhisk/openwhisk/blob/master/docs/triggers_rules.md).
Triggers create a named event stream within the system. Triggers can be fired
manually or connected to external data sources, like databases or message
queues.
Rules set up a binding between triggers and serverless functions. With an active
rule, each time a trigger is fired, the function will be executed with the
trigger payload.
Event binding using triggers and rules for functions can be configured through the `serverless.yaml` file.
```yaml
functions:
my_function:
handler: index.main
events:
- trigger: my_trigger
```
This configuration will create a trigger called `servicename-my_trigger` with an active rule binding `my_function` to this event stream.
## Customising Rules
Rule names default to the following format `servicename-trigger-to-action`. These names be explicitly set through configuration.
```yaml
functions:
my_function:
handler: index.main
events:
- trigger:
name: "my_trigger"
rule: "rule_name"
```
## Customing Triggers
Triggers can be defined as separate resources in the `serverless.yaml` file. This allows you to set up trigger properties like default parameters.
```yaml
functions:
my_function:
handler: index.main
events:
- trigger: my_trigger
resources:
triggers:
my_trigger:
parameters:
hello: world
```
## Trigger Feeds
Triggers can be bound to external event sources using the `feed` property. OpenWhisk [provides a catalogue](https://github.com/openwhisk/openwhisk/blob/master/docs/catalog.md) of third-party event sources bundled as [packages](https://github.com/openwhisk/openwhisk/blob/master/docs/packages.md#creating-and-using-trigger-feeds).
This example demonstrates setting up a trigger which uses the `/whisk.system/alarms/alarm` feed. The `alarm` feed will fire a trigger according to a user-supplied cron schedule.
```yaml
resources:
triggers:
alarm_trigger:
parameters:
hello: world
feed: /whisk.system/alarms/alarm
feed_parameters:
cron: '*/8 * * * * *'
```

View File

@ -0,0 +1,19 @@
<!--
title: Serverless - Apache OpenWhisk - Examples
menuText: OpenWhisk
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/examples/)
<!-- DOCS-SITE-LINK:END -->
# Serverless Apache OpenWhisk Examples
Have an example? Submit a PR or [open an issue](https://github.com/serverless/examples/issues). ⚡️
| Example | Runtime |
|:--------------------------- |:-----|
| [OpenWhisk Node Simple](https://github.com/serverless/examples/tree/master/openwhisk-node-simple) <br/> Boilerplate project repository for OpenWhisk provider with Serverless Framework. | nodeJS |
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](http://forum.serverless.com/)

View File

@ -0,0 +1,20 @@
<!--
title: Hello World Example
menuText: Hello World Example
description: Example of creating a Hello World function in Node.js with the Serverless framework
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/examples/hello-world/)
<!-- DOCS-SITE-LINK:END -->
# Hello World Serverless Example 🌍
Welcome to the Hello World example.
Pick your language of choice:
* [JavaScript](./node)
[View all examples](https://www.serverless.com/framework/docs/providers/openwhisk/examples/)

View File

@ -0,0 +1,38 @@
<!--
title: Hello World Node.js Example
menuText: Hello World Node.js Example
description: Create a Node.js Hello World OpenWhisk function
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/examples/hello-world/node/)
<!-- DOCS-SITE-LINK:END -->
# Hello World Node.js Example
Make sure `serverless` is installed. [See installation guide](../../../guide/installation.md).
## 1. Create a service
`serverless create --template openwhisk-nodejs --path myService` or `sls create --template openwhisk-nodejs --path myService`, where 'myService' is a new folder to be created with template service files. Change directories into this new folder.
## 2. Install Provider Plugin
`npm install -g serverless-openwhisk` followed by `npm install` in the service directory.
## 3. Deploy
`serverless deploy` or `sls deploy`. `sls` is shorthand for the Serverless CLI command
## 4. Invoke deployed function
`serverless invoke --function helloWorld` or `serverless invoke -f helloWorld`
`-f` is shorthand for `--function`
In your terminal window you should see the response from Apache OpenWhisk
```bash
{
"payload": "Hello, World!"
}
```
Congrats you have just deployed and run your Hello World function!

View File

@ -0,0 +1,7 @@
'use strict';
// Your function handler
module.exports.helloWorldHandler = function (params) {
const name = params.name || 'World';
return { payload: `Hello, ${name}!` };
};

View File

@ -0,0 +1,9 @@
{
"name": "serverless-openwhisk-hello-world",
"version": "0.1.0",
"description": "Hello World example for OpenWhisk provider with Serverless Framework.",
"scripts": {
"postinstall": "npm link serverless-openwhisk",
"test": "echo \"Error: no test specified\" && exit 1"
}
}

View File

@ -0,0 +1,15 @@
# Hello World for Apache OpenWhisk
service: hello-world # Service Name
provider:
name: openwhisk
functions:
helloWorld:
handler: handler.helloWorldHandler
events:
- http: GET hello
# remember to run npm install to download the provider plugin.
plugins:
- serverless-openwhisk

View File

@ -0,0 +1,19 @@
<!--
title: Serverless - Apache OpenWhisk
menuText: OpenWhisk
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/)
<!-- DOCS-SITE-LINK:END -->
# Serverless Apache OpenWhisk Guide
Welcome to the Serverless Apache OpenWhisk Guide!
Get started with the **[Introduction to the framework](./intro.md)**
If you have questions, join the [chat in gitter](https://gitter.im/serverless/serverless) or [post over on the forums](http://forum.serverless.com/)
**Note:** Before continuing [Apache OpenWhisk user credentials](./credentials.md) are required for using the CLI.

View File

@ -0,0 +1,125 @@
<!--
title: Serverless Framework - Apache OpenWhisk Guide - Credentials
menuText: Credentials
menuOrder: 3
description: How to set up the Serverless Framework with your Apache OpenWhisk credentials
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/credentials)
<!-- DOCS-SITE-LINK:END -->
# Credentials
The Serverless Framework needs access to account credentials for your OpenWhisk provider so that it can create and manage resources on your behalf.
OpenWhisk is an open-source serverless platform. This means you can either choose to run the platform yourself or choose to use a hosted provider's instance.
Here we'll provide setup instructions for both options, just pick the one that you're using.
## Register with OpenWhisk platform (IBM Bluemix)
IBM's Bluemix cloud platform provides a hosted serverless solution based upon Apache OpenWhisk.
Here's how to get started…
- Sign up for a free account @ [https://bluemix.net](https://console.ng.bluemix.net/registration/)
IBM Bluemix comes with a [free trial](https://www.ibm.com/cloud-computing/bluemix/pricing?cm_mc_uid=22424350960514851832143&cm_mc_sid_50200000=1485183214) that doesn't need credit card details for the first 30 days. Following the trial, developers have to enrol using a credit card but get a free tier for the platform and services.
**All IBM Bluemix users get access to the [Free Tier for OpenWhisk](https://console.ng.bluemix.net/openwhisk/learn/pricing). This includes 400,000 GB-seconds of serverless function compute time per month.**
Additional execution time is charged at $0.000017 per GB-second of execution, rounded to the nearest 100ms.
### Access Account Credentials
Once you have signed up for IBM Bluemix, we need to retrieve your account credentials. These are available on [the page](https://console.ng.bluemix.net/openwhisk/learn/cli) about installing the command-line tool from the [service homepage](https://console.ng.bluemix.net/openwhisk/).
The second point in the instructions contains a command-line which includes the platform endpoint and authentication keys.
```
wsk property set --apihost openwhisk.ng.bluemix.net --auth XXX:YYY
```
**Make a note of the `apihost` and `auth` command flag values.**
### (optional) Install command-line utility
The command-line utility is linked from [the previous page](https://console.ng.bluemix.net/openwhisk/learn/cli). Download and install the binary into a location in your [shell path](http://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path).
## Register with OpenWhisk platform (Self-Hosted)
Following the [Quick Start guide](https://github.com/openwhisk/openwhisk#quick-start) will let you run the platform locally using a Virtual Machine.
- Download and install [Vagrant](https://www.vagrantup.com/) for your platform.
- Run the following commands to retrieve, build and start an instance of the platform.
```
# Clone openwhisk
git clone --depth=1 https://github.com/openwhisk/openwhisk.git
# Change directory to tools/vagrant
cd openwhisk/tools/vagrant
# Run script to create vm and run hello action
./hello
```
This platform will now be running inside a virtual machine at the following IP address: `192.168.33.13`
### Access Account Credentials
The default environment has a guest account configured with the authentication key available here: https://github.com/openwhisk/openwhisk/blob/master/ansible/files/auth.guest
Use the `192.168.33.13` address as the `apihost` value needed below.
### (optional) Install command-line utility
Building OpenWhisk from a cloned repository will result in the generation of the command line interface in `openwhisk/bin/go-cli/`. The default executable in this location will run on the operating system and CPU architecture on which it was built.
Executables for other operating system, and CPU architectures are located in the following directories: `openwhisk/bin/go-cli/mac`, `openwhisk/bin/go-cli/linux`, `openwhisk/bin/go-cli/windows`.
Download and install the correct binary into a location in your [shell path](http://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path).
## Using Account Credentials
You can configure the Serverless Framework to use your OpenWhisk credentials in two ways:
#### Quick Setup
As a quick setup to get started you can export them as environment variables so they would be accessible to Serverless Framework:
```bash
export OW_AUTH=<your-key-here>
export OW_APIHOST=<your-api-host>
# OW_AUTH and OW_APIHOST are now available for serverless to use
serverless deploy
```
#### Using Configuration File
For a more permanent solution you can also set up credentials through a configuration file. Here are different methods you can use to do so.
##### Setup with the `wsk` cli
If you have followed the instructions above to install the `wsk` command-line utility, run the following command to create the configuration file.
```bash
$ wsk property set --apihost PLATFORM_API_HOST --auth USER_AUTH_KEY
```
Credentials are stored in `~/.wskprops`, which you can edit directly if needed.
##### Edit file manually
The following configuration values should be stored in a new file (`.wskprops`) in your home directory. Replace the `PLATFORM_API_HOST` and `USER_AUTH_KEY` values will the credentials from above.
```
APIHOST=PLATFORM_API_HOST
AUTH=USER_AUTH_KEY
```

View File

@ -0,0 +1,63 @@
<!--
title: Serverless Framework - Apache OpenWhisk Guide - Deploying
menuText: Deploying
menuOrder: 8
description: How to deploy your Apache OpenWhisk functions and their required infrastructure
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/deploying)
<!-- DOCS-SITE-LINK:END -->
# Deploying
The Serverless Framework was designed to provision your Apache OpenWhisk Functions, Triggers and Rules safely and quickly. It does this via a couple of methods designed for different types of deployments.
## Deploy All
This is the main method for doing deployments with the Serverless Framework:
```bash
serverless deploy
```
Use this method when you have updated your Function, Event or Resource configuration in `serverless.yml` and you want to deploy that change (or multiple changes at the same time) to Apache OpenWhisk.
### How It Works
The Serverless Framework translates all syntax in `serverless.yml` to [platform API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/openwhisk/openwhisk/master/core/controller/src/main/resources/whiskswagger.json) calls to provision your Actions, Triggers, Rules and APIs.
* Provider plugin parses `serverless.yml` configuration and translates to OpenWhisk resources.
* The code of your Functions is then packaged into zip files.
* Resources are deployed in the following order: *Functions, Function Sequences, API Routes, Triggers, Feeds, Rules.*
* Resources stages are deployed sequentially due to potential dependencies between the stages.
* Resources within a stage are deployed in parallel.
* Stages without any resources defined will be skipped.
### Tips
* Use this in your CI/CD systems, as it is the safest method of deployment.
* Apache OpenWhisk has a [maximum action artefact](https://github.com/openwhisk/openwhisk/blob/master/docs/reference.md#per-action-artifact-mb-fixed-48mb) size of 48MB. This might be an issue if you are using lots of NPM packages. JavaScript build tools like webpack can help to minify your code and save space.
Check out the [deploy command docs](../cli-reference/deploy.md) for all details and options.
## Deploy Function
This deployment method updates a single function. It performs the platform API call to deploy your package without the other resources. It is much faster than redeploying your whole service each time.
```bash
serverless deploy function --function myFunction
```
### How It Works
* The Framework packages up the targeted Apache OpenWhisk Action into a zip file.
* That zip file is deployed to Apache OpenWhisk using the platform API.
### Tips
* Use this when you are developing and want to test on Apache OpenWhisk because it's much faster.
* During development, people will often run this command several times, as opposed to `serverless deploy` which is only run when larger infrastructure provisioning is required.
Check out the [deploy command docs](../cli-reference/deploy.md) for all details and options.

View File

@ -0,0 +1,57 @@
<!--
title: Serverless Framework - Apache OpenWhisk Guide - Events
menuText: Events
menuOrder: 6
description: Configuring Apache OpenWhisk Events in the Serverless Framework
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/events)
<!-- DOCS-SITE-LINK:END -->
# Events
Simply put, events are the things that trigger your functions to run.
If you are using Apache OpenWhisk as your provider, all `events` in the service are anything in Apache OpenWhisk that can trigger your Actions, like HTTP endpoints, message queues, database updates and cron-scheduled events.
[View the Apache OpenWhisk events section for a list of supported events](../events)
Upon deployment, the framework will set up the Triggers and Rules that correspond to that event and configure your `function` to listen to it.
## Configuration
Events belong to each Function and can be found in the `events` property in `serverless.yml`.
```yml
# 'functions' in serverless.yml
functions:
createUser: # Function name
handler: handler.createUser # Reference to file handler.js & exported function 'createUser'
events: # All events associated with this function
- http: GET /users/create
```
The `events` property is an array, because it is possible for functions to be triggered by multiple events, as shown
You can set multiple Events per Function, as long as that is supported by Apache OpenWhisk.
```yml
# 'functions' in serverless.yml
functions:
createUser: # Function name
handler: handler.users # Reference to file handler.js & exported function 'users'
events: # All events associated with this function
- http: GET /users/create
- http: POST /users/update
- trigger: "custom trigger"
```
## Types
The Serverless Framework supports all of the Apache OpenWhisk events and more. Instead of listing them here, we've put them in a separate section, since they have a lot of configurations and functionality. [Check out the events section for more information.](../events)
## Deploying
To deploy or update your Functions, Events and Routes, run `serverless deploy`.

View File

@ -0,0 +1,97 @@
<!--
title: Serverless Framework - Apache OpenWhisk Guide - Functions
menuText: Functions
menuOrder: 5
description: How to configure Apache OpenWhisk functions in the Serverless Framework
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/functions)
<!-- DOCS-SITE-LINK:END -->
# Functions
If you are using OpenWhisk as a provider, all *functions* inside the service are OpenWhisk Actions.
## Configuration
All of the OpenWhisk Actions in your serverless service can be found in `serverless.yml` under the `functions` property.
```yml
# serverless.yml
service: myService
provider:
name: openwhisk
runtime: nodejs:6 # optional, default is nodejs:default
memorySize: 512 # optional, default is 256
timeout: 30 # optional, default is 60
functions:
hello:
handler: handler.hello # required, handler set in Apache OpenWhisk
name: some_custom_name # optional, default is ${service}_${function}
runtime: nodejs # optional overwrite, default is provider runtime
memory: 512 # optional overwrite, default is 256
timeout: 10 # optional overwrite, default is 60
```
The `handler` property points to the file and module containing the code you want to run in your function.
```javascript
// handler.js
exports.handler = function(params) {}
```
You can add as many functions as you want within this property.
```yml
# serverless.yml
service: myService
provider:
name: openwhisk
functions:
functionOne:
handler: handler.functionOne
description: optional description for your Action
functionTwo:
handler: handler.functionTwo
functionThree:
handler: handler.functionThree
```
Your functions can either inherit their settings from the `provider` property.
```yml
# serverless.yml
service: myService
provider:
name: openwhisk
runtime: nodejs:6
memory: 512 # will be inherited by all functions
functions:
functionOne:
handler: handler.functionOne
```
Or you can specify properties at the function level.
```yml
# serverless.yml
service: myService
provider:
name: openwhisk
runtime: nodejs:6
functions:
functionOne:
handler: handler.functionOne
memory: 512 # function specific
```

View File

@ -0,0 +1,65 @@
<!--
title: Serverless Framework - Apache OpenWhisk Guide - Installing The Serverless Framework
menuText: Installation
menuOrder: 2
description: How to install the Serverless Framework and start using Apache OpenWhisk
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/installation)
<!-- DOCS-SITE-LINK:END -->
# Installation
### Installing Node.js
Serverless is a [Node.js](https://nodejs.org) CLI tool so the first thing you need to do is to install Node.js on your machine.
Go to the official [Node.js website](https://nodejs.org), download and follow the [installation instructions](https://nodejs.org/en/download/) to install Node.js on your local machine.
**Note:** Serverless runs on Node v4 or higher.
You can verify that Node.js is installed successfully by runnning `node --version` in your terminal. You should see the corresponding Node version number printed out.
### Installing the Serverless Framework
Next, install the Serverless Framework via [npm](https://npmjs.org) which was already installed when you installed Node.js.
Open up a terminal and type `npm install -g serverless` to install Serverless.
```bash
npm install -g serverless
```
Once the installation process is done you can verify that Serverless is installed successfully by running the following command in your terminal:
```bash
serverless
```
To see which version of serverless you have installed run:
```bash
serverless --version
```
### Installing OpenWhisk Provider Plugin
Now we need to install the provider plugin to allow the framework to deploy services to the platform. This plugin is also [published](http://npmjs.com/package/serverless-openwhisk) on [npm](https://npmjs.org) and can installed using the same `npm install` command.
```
npm install -g serverless-openwhisk
```
*Due to an [outstanding issue](https://github.com/serverless/serverless/issues/2895) with provider plugins, the [OpenWhisk provider](https://github.com/serverless/serverless-openwhisk) must be installed as a global module.*
### Setting up OpenWhisk
To run serverless commands that interface with the OpenWhisk platform, you will need to setup your OpenWhisk account credentials on your machine.
[Follow these instructions on setting up OpenWhisk credentials](./credentials.md)

View File

@ -0,0 +1,77 @@
<!--
title: Serverless Framework - Apache OpenWhisk Guide - Introduction
menuText: Intro
menuOrder: 1
description: An introduction to using Apache OpenWhisk with the Serverless Framework.
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/intro)
<!-- DOCS-SITE-LINK:END -->
# Introduction
The Serverless Framework helps you develop and deploy serverless applications using Apache OpenWhisk. It's a CLI that offers structure, automation and best practices out-of-the-box, allowing you to focus on building sophisticated, event-driven, serverless architectures, comprised of [Functions](#functions) and [Events](#events).
The Serverless Framework is different than other application frameworks because:
* It manages your code as well as your infrastructure
* It supports multiple languages (Node.js, Python, Java, and more)
## Core Concepts
Here are the Framework's main concepts and how they pertain to Apache OpenWhisk…
### Functions
A Function is an [Apache OpenWhisk Action](https://github.com/openwhisk/openwhisk/blob/master/docs/actions.md). It's an independent unit of deployment, like a microservice. It's merely code, deployed in the cloud, that is most often written to perform a single job such as:
* *Saving a user to the database*
* *Processing a file in a database*
* *Performing a scheduled task*
You can perform multiple jobs in your code, but we don't recommend doing that without good reason. Separation of concerns is best and the Framework is designed to help you easily develop and deploy Functions, as well as manage lots of them.
### Events
Anything that triggers an Apache OpenWhisk Action to execute is regarded by the Framework as an **Event**. Events are platform events on Apache OpenWhisk such as:
* *An API Gateway HTTP endpoint (e.g., for a REST API)*
* *A NoSQL database update (e.g., for a user profile)*
* *A scheduled timer (e.g., run every 5 minutes)*
* *A Kafka queue message (e.g., a message)*
* *A Webhook fires (e.g., Github project update)*
* *And more...*
When you define an event for your Apache OpenWhisk Action in the Serverless Framework, the Framework will automatically translate this into [Triggers and Rules](https://github.com/openwhisk/openwhisk/blob/master/docs/triggers_rules.md) needed for that event and configure your functions to listen to it.
### Services
A **Service** is the Framework's unit of organization. You can think of it as a project file, though you can have multiple services for a single application. It's where you define your Functions, the Events that trigger them, and the Resources your Functions use, all in one file entitled `serverless.yml`. It looks like this:
```yml
# serverless.yml
service: users
functions: # Your "Functions"
usersCreate:
events: # The "Events" that trigger this function
- http: post /users/create
usersDelete:
events:
- http: delete /users/delete
```
When you deploy with the Framework by running `serverless deploy`, everything in `serverless.yml` is deployed at once.
### Plugins
You can overwrite or extend the functionality of the Framework using **Plugins**. Every `serverless.yml` can contain a `plugins:` property, which features multiple plugins.
```yml
# serverless.yml
plugins:
- serverless-plugin-identifier
- serverless-another-plugin
```

View File

@ -0,0 +1,101 @@
<!--
title: Serverless Framework Guide - Apache OpenWhisk Guide - Packaging
menuText: Packaging
menuOrder: 11
description: How the Serverless Framework packages your Apache OpenWhisk functions and other available options
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/packaging)
<!-- DOCS-SITE-LINK:END -->
# Packaging
Sometimes you might like to have more control over your function artifacts and how they are packaged.
You can use the `package` and `exclude` configuration for more control over the packaging process.
## Exclude / include
Exclude and include allows you to define globs that will be excluded / included from the resulting artifact. If you wish to
include files you can use a glob pattern prefixed with `!` such as `!re-include-me/**` in `exclude` or the dedicated `include` config.
Serverless will run the glob patterns in order.
At first it will apply the globs defined in `exclude`. After that it'll add all the globs from `include`. This way you can always re-include
previously excluded files and directories.
## Examples
Exclude all node_modules but then re-include a specific modules (in this case node-fetch) using `exclude` exclusively
``` yml
package:
exclude:
- node_modules/**
- '!node_modules/node-fetch/**'
```
Exclude all files but `handler.js` using `exclude` and `include`
``` yml
package:
exclude:
- src/**
include:
- src/function/handler.js
```
**Note:** Don't forget to use the correct glob syntax if you want to exclude directories
```
exclude:
- tmp/**
- .git/**
```
## Artifact
For complete control over the packaging process you can specify your own artifact zip file.
Serverless won't zip your service if this is configured and therefore `exclude` and `include` will be ignored. Either you use artifact or include / exclude.
The artifact option is especially useful in case your development environment allows you to generate a deployable artifact like Maven does for Java.
## Example
```yml
service: my-service
package:
exclude:
- tmp/**
- .git/**
include:
- some-file
artifact: path/to/my-artifact.zip
```
## Packaging functions separately
If you want even more controls over your functions for deployment you can configure them to be packaged independently. This allows you more control for optimizing your deployment. To enable individual packaging set `individually` to true in the service wide packaging settings.
Then for every function you can use the same `exclude`, `include` or `artifact` config options as you can service wide. The `exclude` and `include` option will be merged with the service wide options to create one `exclude` and `include` config per function during packaging.
```yml
service: my-service
package:
individually: true
exclude:
- excluded-by-default.json
functions:
hello:
handler: handler.hello
package:
# We're including this file so it will be in the final package of this function only
include:
- excluded-by-default.json
world:
handler: handler.hello
package:
exclude:
- some-file.js
```

View File

@ -0,0 +1,318 @@
<!--
title: Serverless Framework - Apache OpenWhisk Guide - Plugins
menuText: Plugins
menuOrder: 13
description: How to install and create Plugins to extend or overwrite the functionality of the Serverless Framework
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/plugins)
<!-- DOCS-SITE-LINK:END -->
# Plugins
A Plugin is custom Javascript code that creates new or extends existing commands within the Serverless Framework. The Serverless Framework is merely a group of Plugins that are provided in the core. If you or your organization have a specific workflow, install a pre-written Plugin or write a plugin to customize the Framework to your needs. External Plugins are written exactly the same way as the core Plugins.
## Installing Plugins
External Plugins are added on a per service basis and are not applied globally. Make sure you are in your Service's root directory, then install the corresponding Plugin with the help of NPM:
```
npm install --save custom-serverless-plugin
```
We need to tell Serverless that we want to use the plugin inside our service. We do this by adding the name of the Plugin to the `plugins` section in the `serverless.yml` file.
```yml
# serverless.yml file
plugins:
- custom-serverless-plugin
```
Plugins might want to add extra information which should be accessible to Serverless. The `custom` section in the `serverless.yml` file is the place where you can add necessary
configurations for your plugins (the plugins author / documentation will tell you if you need to add anything there):
```yml
plugins:
- custom-serverless-plugin
custom:
customkey: customvalue
```
## Service local plugin
If you are working on a plugin or have a plugin that is just designed for one project you can add them to the `.serverless_plugins` directory at the root of your service, and in the `plugins` array in `serverless.yml`.
The plugin will be loaded based on being named `custom-serverless-plugin.js` or `custom-serverless-plugin\index.js` in the root of `.serverless_plugins` folder.
### Load Order
Keep in mind that the order you define your plugins matters. When Serverless loads all the core plugins and then the custom plugins in the order you've defined them.
```yml
# serverless.yml
plugins:
- plugin1
- plugin2
```
In this case `plugin1` is loaded before `plugin2`.
## Writing Plugins
### Concepts
#### Plugin
Code which defines *Commands*, any *Events* within a *Command*, and any *Hooks* assigned to an *Lifecycle Event*.
* Command // CLI configuration, commands, subcommands, options
* LifecycleEvent(s) // Events that happen sequentially when the command is run
* Hook(s) // Code that runs when a Lifecycle Event happens during a Command
#### Command
A CLI *Command* that can be called by a user, e.g. `serverless deploy`. A Command has no logic, but simply defines the CLI configuration (e.g. command, subcommands, parameters) and the *Lifecycle Events* for the command. Every command defines its own lifecycle events.
```javascript
'use strict';
class MyPlugin {
constructor() {
this.commands = {
deploy: {
lifecycleEvents: [
'resources',
'functions'
]
},
};
}
}
module.exports = MyPlugin;
```
#### Lifecycle Events
Events that fire sequentially during a Command. The above example list two Events. However, for each Event, and additional `before` and `after` event is created. Therefore, six Events exist in the above example:
- `before:deploy:resources`
- `deploy:resources`
- `after:deploy:resources`
- `before:deploy:functions`
- `deploy:functions`
- `after:deploy:functions`
The name of the command in front of lifecycle events when they are used for Hooks.
#### Hooks
A Hook binds code to any lifecycle event from any command.
```javascript
'use strict';
class Deploy {
constructor() {
this.commands = {
deploy: {
lifecycleEvents: [
'resources',
'functions'
]
},
};
this.hooks = {
'before:deploy:resources': this.beforeDeployResources,
'deploy:resources': this.deployResources,
'after:deploy:functions': this.afterDeployFunctions
};
}
beforeDeployResources() {
console.log('Before Deploy Resources');
}
deployResources() {
console.log('Deploy Resources');
}
afterDeployFunctions() {
console.log('After Deploy Functions');
}
}
module.exports = Deploy;
```
### Nesting Commands
You can also nest commands, e.g. if you want to provide a command `serverless deploy single`. Those nested commands have their own lifecycle events and do not inherit them from their parents.
```javascript
'use strict';
class MyPlugin {
constructor() {
this.commands = {
deploy: {
lifecycleEvents: [
'resources',
'functions'
],
commands: {
function: {
lifecycleEvents: [
'package',
'deploy'
],
},
},
},
}
}
}
module.exports = MyPlugin;
```
### Defining Options
Each (sub)command can have multiple Options.
Options are passed in with a double dash (`--`) like this: `serverless function deploy --function functionName`.
Option Shortcuts are passed in with a single dash (`-`) like this: `serverless function deploy -f functionName`.
The `options` object will be passed in as the second parameter to the constructor of your plugin.
In it, you can optionally add a `shortcut` property, as well as a `required` property. The Framework will return an error if a `required` Option is not included.
**Note:** At this time, the Serverless Framework does not use parameters.
```javascript
'use strict';
class Deploy {
constructor(serverless, options) {
this.serverless = serverless;
this.options = options;
this.commands = {
deploy: {
lifecycleEvents: [
'functions'
],
options: {
function: {
usage: 'Specify the function you want to deploy (e.g. "--function myFunction")',
shortcut: 'f',
required: true
}
}
},
};
this.hooks = {
'deploy:functions': this.deployFunction.bind(this)
}
}
deployFunction() {
console.log('Deploying function: ', this.options.function);
}
}
module.exports = Deploy;
```
### Provider Specific Plugins
Plugins can be provider specific which means that they are bound to a provider.
**Note:** Binding a plugin to a provider is optional. Serverless will always consider your plugin if you don't specify a `provider`.
The provider definition should be added inside the plugins constructor:
```javascript
'use strict';
class ProviderDeploy {
constructor(serverless, options) {
this.serverless = serverless;
this.options = options;
// set the providers name here
this.provider = this.serverless.getProvider('providerName');
this.commands = {
deploy: {
lifecycleEvents: [
'functions'
],
options: {
function: {
usage: 'Specify the function you want to deploy (e.g. "--function myFunction")',
required: true
}
}
},
};
this.hooks = {
'deploy:functions': this.deployFunction.bind(this)
}
}
deployFunction() {
console.log('Deploying function: ', this.options.function);
}
}
module.exports = ProviderDeploy;
```
The Plugin's functionality will now only be executed when the Serverless Service's provider matches the provider name which is defined inside the plugins constructor.
### Serverless Instance
The `serverless` instance which enables access to global service config during runtime is passed in as the first parameter to the plugin constructor.
```javascript
'use strict';
class MyPlugin {
constructor(serverless, options) {
this.serverless = serverless;
this.options = options;
this.commands = {
log: {
lifecycleEvents: [
'serverless'
],
},
};
this.hooks = {
'log:serverless': this.logServerless.bind(this)
}
}
logServerless() {
console.log('Serverless instance: ', this.serverless);
}
}
module.exports = MyPlugin;
```
### Command Naming
Command names need to be unique. If we load two commands and both want to specify the same command (e.g. we have an integrated command `deploy` and an external command also wants to use `deploy`) the Serverless CLI will print an error and exit. If you want to have your own `deploy` command you need to name it something different like `myCompanyDeploy` so they don't clash with existing plugins.

View File

@ -0,0 +1,65 @@
<!--
title: Serverless Framework - Apache OpenWhisk Guide - Serverless.yml Reference
menuText: Serverless.yml
menuOrder: 15
description: A list of all available properties on serverless.yml for Apache OpenWhisk
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/serverless.yml)
<!-- DOCS-SITE-LINK:END -->
# Serverless.yml Reference
Here is a list of all available properties in `serverless.yml` when the provider is set to `openwhisk`.
```yml
# serverless.yml
service: myService
frameworkVersion: ">=1.0.0 <2.0.0"
provider:
name: openwhisk
runtime: nodejs:default
memory: 256 # Overwrite default memory size. Default is 512.
timeout: 10 # The default is 60
overwrite: true # Can we overwrite deployed functions? default is true
namespace: 'custom' # use custom namespace, defaults to '_'
functions:
usersCreate: # A Function
handler: users.create # The file and module for this specific function.
sequence: # Use sequences rather than handler to handle events. handler and sequence properties are mutually exclusive.
- function_a
- function_b
- function_c
memory: 256 # memorySize for this specific function.
timeout: 10 # Timeout for this specific function. Overrides the default set above.
runtime: nodejs:6
overwrite: false # Can we overwrite deployed function?
namespace: 'custom' # use custom namespace, defaults to '_'
events: # The Events that trigger this Function
# This creates an API Gateway HTTP endpoint which can be used to trigger this function. Learn more in "events/apigateway"
- http: METHOD /path/to/url
- trigger: my_trigger # bind function to trigger event
- trigger:
name: my_trigger
rule: rule_name
# The "Resources" your "Functions" use. This can be used to define custom Triggers and Rules which are bound to your Actions.
resources:
triggers:
my_trigger: # trigger with default parameter bound.
parameters:
hello: world
alarm_trigger: # trigger connected to event feed
parameters:
hello: world
feed: /whisk.system/alarms/alarm
feed_parameters:
cron: '*/8 * * * * *'
```

View File

@ -0,0 +1,172 @@
<!--
title: Serverless Framework - Apache OpenWhisk Guide - Services
menuText: Services
menuOrder: 4
description: How to manage and configure serverless services, which contain your Apache OpenWhisk functions, their events and resources.
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/services)
<!-- DOCS-SITE-LINK:END -->
# Services
A `service` is like a project. It's where you define your Apache OpenWhisk Functions, the `events` that trigger them and any `resources` they require, all in a file called `serverless.yml`.
To get started building your first Serverless Framework project, create a `service`.
## Organization
In the beginning of an application, many people use a single Service to define all of the Functions, Events and Resources for that project. This is what we recommend in the beginning.
```bash
myService/
serverless.yml # Contains all functions and infrastructure resources
```
However, as your application grows, you can break it out into multiple services. A lot of people organize their services by workflows or data models, and group the functions related to those workflows and data models together in the service.
```bash
users/
serverless.yml # Contains 4 functions that do Users CRUD operations and the Users database
posts/
serverless.yml # Contains 4 functions that do Posts CRUD operations and the Posts database
comments/
serverless.yml # Contains 4 functions that do Comments CRUD operations and the Comments database
```
This makes sense since related functions usually use common infrastructure resources, and you want to keep those functions and resources together as a single unit of deployment, for better organization and separation of concerns.
## Creation
To create a service, use the `create` command. You must also pass in a runtime (e.g., node.js, python etc.) you would like to write the service in. You can also pass in a path to create a directory and auto-name your service:
```bash
# Create service with nodeJS template in the folder ./myService
serverless create --template openwhisk-nodejs --path myService
```
Here are the available runtimes for Apache OpenWhisk:
* openwhisk-nodejs
Check out the [create command docs](../cli-reference/create) for all the details and options.
## Contents
You'll see the following files in your working directory:
- `serverless.yml`
- `handler.js`
### serverless.yml
Each `service` configuration is managed in the `serverless.yml` file. The main responsibilities of this file are:
- Declare a Serverless service
- Define one or more functions in the service
- Define the provider the service will be deployed to (and the runtime if provided)
- Define any custom plugins to be used
- Define events that trigger each function to execute (e.g. HTTP requests)
- Allow events listed in the `events` section to automatically create the resources required for the event upon deployment
- Allow flexible configuration using Serverless Variables
You can see the name of the service, the provider configuration and the first function inside the `functions` definition which points to the `handler.js` file. Any further service configuration will be done in this file.
```yml
# serverless.yml
service: users
provider:
name: openwhisk
runtime: nodejs:6
memory: 512 # Overwrite the default memory size. Default is 256
functions:
usersCreate: # A Function
handler: users.create
events: # The Events that trigger this Function
- http: post /users/create
usersDelete: # A Function
handler: users.delete
events: # The Events that trigger this Function
- http: delete /users/delete
```
### handler.js
The `handler.js` file contains your function code. The function definition in `serverless.yml` will point to this `handler.js` file and the function exported here.
### event.json
**Note:** This file is not created by default
Create this file and add event data so you can invoke your function with the data via `serverless invoke -p event.json`
## Deployment
When you deploy a Service, all of the Functions, Events and Resources in your `serverless.yml` are translated into calls to the platform API to dynamically define those resources.
To deploy a service, use the `deploy` command:
```bash
serverless deploy
```
Check out the [deployment guide](https://serverless.com/framework/docs/providers/openwhisk/guide/deploying/) to learn more about deployments and how they work. Or, check out the [deploy command docs](../cli-reference/deploy) for all the details and options.
## Removal
To easily remove your Service from your Apache OpenWhisk account, you can use the `remove` command.
Run `serverless remove -v` to trigger the removal process. As in the deploy step we're also running in the `verbose` mode so you can see all details of the remove process.
Serverless will start the removal and informs you about it's process on the console. A success message is printed once the whole service is removed.
The removal process will only remove the service on your provider's infrastructure. The service directory will still remain on your local machine so you can still modify and (re)deploy it to another stage, region or provider later on.
## Version Pinning
The Serverless framework is usually installed globally via `npm install -g serverless`. This way you have the Serverless CLI available for all your services.
Installing tools globally has the downside that the version can't be pinned inside package.json. This can lead to issues if you upgrade Serverless, but your colleagues or CI system don't. You can now use a new feature in your serverless.yml which is available only in the latest version without worrying that your CI system will deploy with an old version of Serverless.
### Pinning a Version
To configure version pinning define a `frameworkVersion` property in your serverless.yaml. Whenever you run a Serverless command from the CLI it checks if your current Serverless version is matching the `frameworkVersion` range. The CLI uses [Semantic Versioning](http://semver.org/) so you can pin it to an exact version or provide a range. In general we recommend to pin to an exact version to ensure everybody in your team has the exact same setup and no unexpected problems happen.
### Examples
#### Exact Version
```yml
# serverless.yml
frameworkVersion: "=1.0.3"
service: users
provider:
name: openwhisk
runtime: nodejs
memorySize: 512
```
#### Version Range
```yml
# serverless.yml
frameworkVersion: ">=1.0.0 <2.0.0"
service: users
provider:
name: openwhisk
runtime: nodejs
memorySize: 512
```

View File

@ -0,0 +1,108 @@
<!--
title: Serverless Framework - Apache OpenWhisk Guide - Testing
menuText: Testing
menuOrder: 9
description: Recommendations and best practices for testing Apache OpenWhisk Functions with the Serverless Framework
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/testing)
<!-- DOCS-SITE-LINK:END -->
# Testing
While the Serverless Architecture introduces a lot of simplicity when it comes to serving business logic, some of its characteristics present challenges for testing. They are:
* The Serverless Architecture is an integration of separate, distributed services, which must be tested both independently, and together.
* The Serverless Architecture is dependent on internet/cloud services, which are hard to emulate locally.
* The Serverless Architecture can feature event-driven, asynchronous workflows, which are hard to emulate entirely.
To get through these challenges, and to keep the [test pyramid](http://martinfowler.com/bliki/TestPyramid.html) in mind, keep the following principles in mind:
* Write your business logic so that it is separate from your FaaS provider (e.g., Apache OpenWhisk), to keep it provider-independent, reusable and more easily testable.
* When your business logic is written separately from the FaaS provider, you can write traditional Unit Tests to ensure it is working properly.
* Write Integration Tests to verify integrations with other services are working correctly.
## A Poor Example
Here is an example in Node.js of how to follow the practices above. The job this Function should perform is to save a user in a database and then send a welcome email:
```javascript
const db = require('db').connect();
const mailer = require('mailer');
module.exports.saveUser = (params) => {
return Promise((resolve, reject) => {
const user = {
email: params.email,
created_at: Date.now()
}
db.saveUser(user, function (err) {
if (err) {
reject(err);
} else {
mailer.sendWelcomeEmail(event.email);
resolve();
}
});
})
};
```
There are two main problems with this function:
* The business logic is not separate from the FaaS Provider. It's bounded to how Apache OpenWhisk passes incoming data (`params` object).
* Testing this function will rely on separate services. Specifically, running a database instance and a mail server.
## Writing Testable Apache OpenWhisk Functions
Let's refactor the above example to separate the business logic from the FaaS Provider.
```javascript
class Users {
constructor(db, mailer) {
this.db = db;
this.mailer = mailer;
}
save(email, callback) {
return new Promise((resolve, reject) => {
const user = {
email: email,
created_at: Date.now()
}
this.db.saveUser(user, function (err) {
if (err) {
reject(err);
} else {
this.mailer.sendWelcomeEmail(email);
resolve();
}
});
})
}
}
module.exports = Users;
```
```javascript
const db = require('db').connect();
const mailer = require('mailer');
const Users = require('users');
let users = new Users(db, mailer);
module.exports.saveUser = (params) => {
return users.save(params.email);
};
```
Now, the above class keeps business logic separate. Further, the code responsible for setting up dependencies, injecting them, calling business logic functions and interacting with Apache OpenWhisk is in its own file, which will be changed less often. This way, the business logic is not provider dependent, easier to re-use, and easier to test.
Further, this code doesn't require running any external services. Instead of a real `db` and `mailer` services, we can pass mocks and assert if `saveUser` and `sendWelcomeEmail` has been called with proper arguments.
Unit Tests can easily be written to cover the above class. An integration test can be added by invoking the function (`serverless invoke`) with fixture email address, check if user is actually saved to DB and check if email was received to see if everything is working together.

View File

@ -0,0 +1,211 @@
<!--
title: Serverless Variables
menuText: Variables
menuOrder: 10
description: How to use Serverless Variables to insert dynamic configuration info into your serverless.yml
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/variables)
<!-- DOCS-SITE-LINK:END -->
# Variables
The Serverless framework provides a powerful variable system which allows you to add dynamic data into your `serverless.yml`. With Serverless Variables, you'll be able to do the following:
- Reference & load variables from environment variables
- Reference & load variables from CLI options
- Recursively reference properties of any type from the same `serverless.yml` file
- Recursively reference properties of any type from other YAML/JSON files
- Recursively nest variable references within each other for ultimate flexibility
- Combine multiple variable references to overwrite each other
**Note:** You can only use variables in `serverless.yml` property **values**, not property keys. So you can't use variables to generate dynamic logical IDs in the custom resources section for example.
## Reference Properties In serverless.yml
To self-reference properties in `serverless.yml`, use the `${self:someProperty}` syntax in your `serverless.yml`. This functionality is recursive, so you can go as deep in the object tree as you want.
```yml
service: new-service
provider: openwhisk
custom:
globalSchedule: cron(0 * * * *)
functions:
hello:
handler: handler.hello
events:
- schedule: ${self:custom.globalSchedule}
world:
handler: handler.world
events:
- schedule: ${self:custom.globalSchedule}
```
In the above example you're setting a global schedule for all functions by referencing the `globalSchedule` property in the same `serverless.yml` file. This way, you can easily change the schedule for all functions whenever you like.
## Referencing Environment Variables
To reference environment variables, use the `${env:SOME_VAR}` syntax in your `serverless.yml` configuration file.
```yml
service: new-service
provider: openwhisk
functions:
hello:
name: ${env:FUNC_PREFIX}-hello
handler: handler.hello
world:
name: ${env:FUNC_PREFIX}-world
handler: handler.world
```
In the above example you're dynamically adding a prefix to the function names by referencing the `FUNC_PREFIX` env var. So you can easily change that prefix for all functions by changing the `FUNC_PREFIX` env var.
## Referencing CLI Options
To reference CLI options that you passed, use the `${opt:some_option}` syntax in your `serverless.yml` configuration file.
```yml
service: new-service
provider: openwhisk
functions:
hello:
name: ${opt:stage}-hello
handler: handler.hello
world:
name: ${opt:stage}-world
handler: handler.world
```
In the above example, you're dynamically adding a prefix to the function names by referencing the `stage` option that you pass in the CLI when you run `serverless deploy --stage dev`. So when you deploy, the function name will always include the stage you're deploying to.
## Reference Variables in Other Files
To reference variables in other YAML or JSON files, use the `${file(./myFile.yml):someProperty}` syntax in your `serverless.yml` configuration file. This functionality is recursive, so you can go as deep in that file as you want. Here's an example:
```yml
# myCustomFile.yml
globalSchedule: cron(0 * * * *)
```
```yml
# serverless.yml
service: new-service
provider: openwhisk
custom: ${file(./myCustomFile.yml)} # You can reference the entire file
functions:
hello:
handler: handler.hello
events:
- schedule: ${file(./myCustomFile.yml):globalSchedule} # Or you can reference a specific property
world:
handler: handler.world
events:
- schedule: ${self:custom.globalSchedule} # This would also work in this case
```
In the above example, you're referencing the entire `myCustomFile.yml` file in the `custom` property. You need to pass the path relative to your service directory. You can also request specific properties in that file as shown in the `schedule` property. It's completely recursive and you can go as deep as you want.
## Reference Variables in Javascript Files
To add dynamic data into your variables, reference javascript files by putting `${file(./myFile.js):someModule}` syntax in your `serverless.yml`. Here's an example:
```js
// myCustomFile.js
module.exports.hello = () => {
// Code that generates dynamic data
return 'cron(0 * * * *)';
}
```
```yml
# serverless.yml
service: new-service
provider: openwhisk
functions:
hello:
handler: handler.hello
events:
- schedule: ${file(./myCustomFile.js):hello} # Reference a specific module
```
You can also return an object and reference a specific property. Just make sure you are returning a valid object and referencing a valid property:
```yml
# serverless.yml
service: new-service
provider: openwhisk
functions:
scheduledFunction:
handler: handler.scheduledFunction
events:
- schedule: ${file(./myCustomFile.js):schedule.hour}
```
```js
// myCustomFile.js
module.exports.schedule = () => {
// Code that generates dynamic data
return {
hour: 'cron(0 * * * *)'
};
}
```
## Multiple Configuration Files
Adding many custom resources to your `serverless.yml` file could bloat the whole file, so you can use the Serverless Variable syntax to split this up.
```yml
resources:
Resources: ${file(openwhisk-resources.json)}
```
The corresponding resources which are defined inside the `openwhisk-resources.json` file will be resolved and loaded into the `Resources` section.
## Nesting Variable References
The Serverless variable system allows you to nest variable references within each other for ultimate flexibility. So you can reference certain variables based on other variables. Here's an example:
```yml
service: new-service
provider: openwhisk
custom:
myFlexibleArn: ${env:${opt:stage}_arn}
functions:
hello:
handler: handler.hello
```
In the above example, if you pass `dev` as a stage option, the framework will look for the `dev_arn` environment variable. If you pass `production`, the framework will look for `production_arn`, and so on. This allows you to creatively use multiple variables by using a certain naming pattern without having to update the values of these variables constantly. You can go as deep as you want in your nesting, and can reference variables at any level of nesting from any source (env, opt, self or file).
## Overwriting Variables
The Serverless framework gives you an intuitive way to reference multiple variables as a fallback strategy in case one of the variables is missing. This way you'll be able to use a default value from a certain source, if the variable from another source is missing.
For example, if you want to reference the stage you're deploying to, but you don't want to keep on providing the `stage` option in the CLI. What you can do in `serverless.yml` is:
```yml
service: new-service
provider:
name: openwhisk
stage: dev
custom:
myStage: ${opt:stage, self:provider.stage}
functions:
hello:
handler: handler.hello
```
What this says is to use the `stage` CLI option if it exists, if not, use the default stage (which lives in `provider.stage`). So during development you can safely deploy with `serverless deploy`, but during production you can do `serverless deploy --stage production` and the stage will be picked up for you without having to make any changes to `serverless.yml`.
You can have as many variable references as you want, from any source you want, and each of them can be of different type and different name.
## Migrating serverless.env.yml
Previously we used the `serverless.env.yml` file to track Serverless Variables. It was a completely different system with different concepts. To migrate your variables from `serverless.env.yml`, you'll need to decide where you want to store your variables.
**Using a config file:** You can still use `serverless.env.yml`, but the difference now is that you can structure the file however you want, and you'll need to reference each variable/property correctly in `serverless.yml`. For more info, you can check the file reference section above.
**Using the same `serverless.yml` file:** You can store your variables in `serverless.yml` if they don't contain sensitive data, and then reference them elsewhere in the file using `self:someProperty`. For more info, you can check the self reference section above.
**Using environment variables:** You can instead store your variables in environment variables and reference them with `env.someEnvVar`. For more info, you can check the environment variable reference section above.
Now you don't need `serverless.env.yml` at all, but you can still use it if you want. It's just not required anymore. Migrating to the new variable system is easy and you just need to know how the new system works and make small adjustments to how you store & reference your variables.

View File

@ -0,0 +1,68 @@
<!--
title: Serverless Framework Guide - Apache OpenWhisk - Workflow
menuText: Workflow
menuOrder: 14
description: A guide and cheatsheet containing CLI commands and workflow recommendations.
layout: Doc
-->
<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/openwhisk/guide/workflow)
<!-- DOCS-SITE-LINK:END -->
# Workflow
Intro. Quick recommendations and tips for various processes.
### Development Workflow
1. Write your functions
2. Use `serverless deploy` only when you've made changes to `serverless.yml` and in CI/CD systems.
3. Use `serverless deploy function -f myFunction` to rapidly deploy changes when you are working on a specific Apache OpenWhisk Function.
4. Use `serverless invoke -f myFunction -l` to test your Apache OpenWhisk Functions.
5. Open up a separate tab in your console and stream logs in there via `serverless logs -f myFunction -t`.
6. Write tests to run locally.
### Larger Projects
* Break your application/project into multiple Serverless Services.
* Model your Serverless Services around Data Models or Workflows.
* Keep the Functions and Resources in your Serverless Services to a minimum.
## Cheat Sheet
A handy list of commands to use when developing with the Serverless Framework.
##### Create A Service:
Creates a new Service
```
serverless create -p [SERVICE NAME] -t openwhisk-nodejs
```
##### Install A Service
This is a convenience method to install a pre-made Serverless Service locally by downloading the Github repo and unzipping it.
```
serverless install -u [GITHUB URL OF SERVICE]
```
##### Deploy All
Use this when you have made changes to your Functions, Events or Resources in `serverless.yml` or you simply want to deploy all changes within your Service at the same time.
```
serverless deploy
```
##### Deploy Function
Use this to quickly overwrite your OpenWhisk Actions, allowing you to develop faster.
```
serverless deploy function -f [FUNCTION NAME]
```
##### Invoke Function
Invokes an OpenWhisk Action and returns logs.
```
serverless invoke function -f [FUNCTION NAME] -l
```
##### Streaming Logs
Open up a separate tab in your console and stream all logs for a specific Function using this command.
```
serverless logs -f [FUNCTION NAME]
```

View File

@ -12,7 +12,7 @@ const PluginManager = require('./classes/PluginManager');
const Utils = require('./classes/Utils');
const Service = require('./classes/Service');
const Variables = require('./classes/Variables');
const SError = require('./classes/Error').SError;
const ServerlessError = require('./classes/Error').ServerlessError;
const Version = require('./../package.json').version;
class Serverless {
@ -42,7 +42,7 @@ class Serverless {
this.classes.Utils = Utils;
this.classes.Service = Service;
this.classes.Variables = Variables;
this.classes.Error = SError;
this.classes.Error = ServerlessError;
this.serverlessDirPath = path.join(os.homedir(), '.serverless');
}

View File

@ -13,7 +13,7 @@ const PluginManager = require('../lib/classes/PluginManager');
const Utils = require('../lib/classes/Utils');
const Service = require('../lib/classes/Service');
const CLI = require('../lib/classes/CLI');
const Error = require('../lib/classes/Error').SError;
const ServerlessError = require('../lib/classes/Error').ServerlessError;
const testUtils = require('../tests/utils');
describe('Serverless', () => {
@ -105,7 +105,7 @@ describe('Serverless', () => {
});
it('should store the Error class inside the classes object', () => {
expect(serverless.classes.Error).to.deep.equal(Error);
expect(serverless.classes.Error).to.deep.equal(ServerlessError);
});
});

View File

@ -21,7 +21,7 @@ describe('CLI', () => {
serverless = new Serverless({});
});
describe('#construtor()', () => {
describe('#constructor()', () => {
it('should set the serverless instance', () => {
cli = new CLI(serverless);
expect(cli.serverless).to.deep.equal(serverless);

View File

@ -36,7 +36,7 @@ const writeMessage = (messageType, message) => {
consoleLog(' ');
};
module.exports.SError = class ServerlessError extends Error {
module.exports.ServerlessError = class ServerlessError extends Error {
constructor(message, statusCode) {
super(message);
this.name = this.constructor.name;
@ -46,6 +46,9 @@ module.exports.SError = class ServerlessError extends Error {
}
};
// Deprecated - use ServerlessError instead
module.exports.SError = module.exports.ServerlessError;
module.exports.logError = (e) => {
try {
const errorType = e.name.replace(/([A-Z])/g, ' $1');

149
lib/classes/Error.test.js Normal file
View File

@ -0,0 +1,149 @@
'use strict';
/* eslint-disable no-console */
const expect = require('chai').expect;
const ServerlessError = require('../../lib/classes/Error').ServerlessError;
const logError = require('../../lib/classes/Error').logError;
describe('ServerlessError', () => {
describe('#constructor()', () => {
it('should store message', () => {
const error = new ServerlessError('a message', 'a status code');
expect(error.message).to.be.equal('a message');
});
it('should store name', () => {
const error = new ServerlessError('a message', 'a status code');
expect(error.name).to.be.equal('ServerlessError');
});
it('should store status code', () => {
const error = new ServerlessError('a message', 'a status code');
expect(error.statusCode).to.be.equal('a status code');
});
it('should have stack trace', () => {
let expectedError;
function testStackFrame() {
expectedError = new ServerlessError('a message', 'a status code');
throw expectedError;
}
let thrownError;
try {
testStackFrame();
} catch (e) {
thrownError = e;
}
expect(thrownError).to.exist; // eslint-disable-line no-unused-expressions
expect(thrownError).to.deep.equal(expectedError);
expect(thrownError.stack).to.exist; // eslint-disable-line no-unused-expressions
expect(thrownError.stack).to.have.string('testStackFrame');
expect(thrownError.stack).to.not.have.string('new ServerlessError');
expect(thrownError.stack).to.not.have.string('Error.js');
});
});
});
describe('Error', () => {
describe('#logError()', () => {
beforeEach(() => {
this.cbProcessExit = null;
this.processExitCodes = [];
this.processExit = process.exit;
process.exit = (code) => {
this.processExitCodes.push(code);
if (this.cbProcessExit) {
this.cbProcessExit();
}
};
this.consoleLogMessages = [];
this.consoleLog = console.log;
console.log = (msg) => {
this.consoleLogMessages.push(msg);
};
});
afterEach(() => {
process.exit = this.processExit;
console.log = this.consoleLog;
delete process.env.SLS_DEBUG;
});
it('should log error and exit', () => {
const error = new ServerlessError('a message', 'a status code');
logError(error);
console.log = this.consoleLog; // For mocha to echo status of the test
expect(this.processExitCodes.length).to.be.equal(1);
expect(this.processExitCodes).gt(0);
const message = this.consoleLogMessages.join('\n');
expect(message).to.have.string('Serverless Error');
expect(message).to.have.string('a message');
});
it('should shorten long messages', () => {
const error = new ServerlessError(
'a message which is way to long so it gets shortened automatically to fit');
logError(error);
console.log = this.consoleLog;
const message = this.consoleLogMessages.join('\n');
expect(message).to.have.string('Serverless Error');
expect(message).to.have.string('a message which is way to long so it gets shortened');
expect(message).to.not.have.string(
'a message which is way to long so it gets shortened automatically to fit');
});
it('should notify about SLS_DEBUG and ask report for unexpected errors', () => {
const error = new Error('an unexpected error');
logError(error);
console.log = this.consoleLog;
const message = this.consoleLogMessages.join('\n');
expect(message).to.have.string('SLS_DEBUG=*');
expect(message).to.have.string('Please report this error');
});
it('should print stack trace with SLS_DEBUG', () => {
process.env.SLS_DEBUG = 1;
const error = new ServerlessError('a message');
logError(error);
console.log = this.consoleLog;
const message = this.consoleLogMessages.join('\n');
expect(message).to.have.string('Stack Trace');
expect(message).to.have.string(error.stack);
});
it('should not print stack trace without SLS_DEBUG', () => {
const error = new ServerlessError('a message');
logError(error);
console.log = this.consoleLog;
const message = this.consoleLogMessages.join('\n');
expect(message).to.not.have.string('Stack Trace');
expect(message).to.not.have.string(error.stack);
});
it('should re-throw error when handling raises an exception itself', () => {
const error = new ServerlessError('a message');
const handlingError = new Error('an unexpected error');
this.cbProcessExit = () => { throw handlingError; };
let thrownError = null;
try {
logError(error);
} catch (e) {
thrownError = e;
}
console.log = this.consoleLog;
expect(thrownError).to.deep.equal(handlingError);
});
});
});

View File

@ -1,6 +1,6 @@
'use strict';
const SError = require('./Error').SError;
const ServerlessError = require('./Error').ServerlessError;
const path = require('path');
const _ = require('lodash');
const BbPromise = require('bluebird');
@ -13,8 +13,7 @@ class Service {
// Default properties
this.service = null;
this.provider = {};
this.defaults = {
this.provider = {
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}',
@ -60,13 +59,13 @@ class Service {
`The Serverless version (${version}) does not satisfy the`,
` "frameworkVersion" (${ymlVersion}) in serverless.yml`,
].join('');
throw new SError(errorMessage);
throw new ServerlessError(errorMessage);
}
if (!serverlessFile.service) {
throw new SError('"service" property is missing in serverless.yml');
throw new ServerlessError('"service" property is missing in serverless.yml');
}
if (!serverlessFile.provider) {
throw new SError('"provider" property is missing in serverless.yml');
throw new ServerlessError('"provider" property is missing in serverless.yml');
}
if (typeof serverlessFile.provider !== 'object') {
@ -83,7 +82,7 @@ class Service {
` Valid values for provider are: ${providers.join(', ')}.`,
' Please provide one of those values to the "provider" property in serverless.yml.',
].join('');
throw new SError(errorMessage);
throw new ServerlessError(errorMessage);
}
if (Array.isArray(serverlessFile.resources)) {
@ -93,12 +92,15 @@ class Service {
}
that.service = serverlessFile.service;
that.provider = serverlessFile.provider;
that.custom = serverlessFile.custom;
that.plugins = serverlessFile.plugins;
that.resources = serverlessFile.resources;
that.functions = serverlessFile.functions || {};
// merge so that the default settings are still in place and
// won't be overwritten
that.provider = _.merge(that.provider, serverlessFile.provider);
if (serverlessFile.package) {
that.package.individually = serverlessFile.package.individually;
that.package.artifact = serverlessFile.package.artifact;
@ -106,53 +108,6 @@ class Service {
that.package.include = serverlessFile.package.include;
}
if (serverlessFile.defaults && serverlessFile.defaults.stage) {
this.defaults.stage = serverlessFile.defaults.stage;
}
if (serverlessFile.defaults && serverlessFile.defaults.region) {
this.defaults.region = serverlessFile.defaults.region;
}
if (serverlessFile.defaults && serverlessFile.defaults.variableSyntax) {
this.defaults.variableSyntax = serverlessFile.defaults.variableSyntax;
}
// load defaults property for backward compatibility
if (serverlessFile.defaults) {
const warningMessage = [
'Deprecation Notice: the "defaults" property in serverless.yml',
' is deprecated. The "stage", "region" & "variableSyntax" properties',
' has been moved to the "provider" property instead. Please update',
' your serverless.yml file asap. For more info, you can check our docs.',
].join('');
this.serverless.cli.log(warningMessage);
if (serverlessFile.defaults.stage) {
this.defaults.stage = serverlessFile.defaults.stage;
}
if (serverlessFile.defaults.region) {
this.defaults.region = serverlessFile.defaults.region;
}
if (serverlessFile.defaults.variableSyntax) {
this.defaults.variableSyntax = serverlessFile.defaults.variableSyntax;
}
}
// if exists, move provider to defaults for backward compatibility
if (serverlessFile.provider.stage) {
this.defaults.stage = serverlessFile.provider.stage;
}
if (serverlessFile.provider.region) {
this.defaults.region = serverlessFile.provider.region;
}
if (serverlessFile.provider.variableSyntax) {
this.defaults.variableSyntax = serverlessFile.provider.variableSyntax;
}
// make sure provider obj is in sync with default for backward compatibility
this.provider.stage = this.defaults.stage;
this.provider.region = this.defaults.region;
this.provider.variableSyntax = this.defaults.variableSyntax;
// setup function.name property
const stageNameForFunction = options.stage || this.provider.stage;
_.forEach(that.functions, (functionObj, functionName) => {
@ -173,7 +128,7 @@ class Service {
validate() {
_.forEach(this.functions, (functionObj, functionName) => {
if (!_.isArray(functionObj.events)) {
throw new SError(`Events for "${functionName}" must be an array,` +
throw new ServerlessError(`Events for "${functionName}" must be an array,` +
` not an ${typeof functionObj.events}`);
}
});
@ -193,14 +148,14 @@ class Service {
if (functionName in this.functions) {
return this.functions[functionName];
}
throw new SError(`Function "${functionName}" doesn't exist in this Service`);
throw new ServerlessError(`Function "${functionName}" doesn't exist in this Service`);
}
getEventInFunction(eventName, functionName) {
if (eventName in this.getFunction(functionName).events) {
return this.getFunction(functionName).events[eventName];
}
throw new SError(`Event "${eventName}" doesn't exist in function "${functionName}"`);
throw new ServerlessError(`Event "${eventName}" doesn't exist in function "${functionName}"`);
}
getAllEventsInFunction(functionName) {

View File

@ -22,8 +22,7 @@ describe('Service', () => {
const serviceInstance = new Service(serverless);
expect(serviceInstance.service).to.be.equal(null);
expect(serviceInstance.provider).to.deep.equal({});
expect(serviceInstance.defaults).to.deep.equal({
expect(serviceInstance.provider).to.deep.equal({
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}',
@ -121,8 +120,8 @@ describe('Service', () => {
const SUtils = new Utils();
const serverlessYml = {
service: 'new-service',
provider: 'aws',
defaults: {
provider: {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${{([\\s\\S]+?)}}',
@ -156,7 +155,7 @@ describe('Service', () => {
return serviceInstance.load().then(() => {
expect(serviceInstance.service).to.be.equal('new-service');
expect(serviceInstance.provider.name).to.deep.equal('aws');
expect(serviceInstance.defaults.variableSyntax).to.equal('\\${{([\\s\\S]+?)}}');
expect(serviceInstance.provider.variableSyntax).to.equal('\\${{([\\s\\S]+?)}}');
expect(serviceInstance.plugins).to.deep.equal(['testPlugin']);
expect(serviceInstance.resources.aws).to.deep.equal({ resourcesProp: 'value' });
expect(serviceInstance.resources.azure).to.deep.equal({});
@ -204,8 +203,8 @@ describe('Service', () => {
const SUtils = new Utils();
const serverlessYml = {
service: 'new-service',
provider: 'aws',
defaults: {
provider: {
name: 'aws',
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${{([\\s\\S]+?)}}',

View File

@ -282,12 +282,6 @@ class Utils {
let hasCustomVariableSyntaxDefined = false;
const defaultVariableSyntax = '\\${([ :a-zA-Z0-9._,\\-\\/\\(\\)]+?)}';
// check if the variableSyntax in the defaults section is defined
if (serverless.service.defaults &&
serverless.service.defaults.variableSyntax &&
serverless.service.defaults.variableSyntax !== defaultVariableSyntax) {
hasCustomVariableSyntaxDefined = true;
}
// check if the variableSyntax in the provider section is defined
if (serverless.service.provider &&

View File

@ -396,8 +396,6 @@ describe('Utils', () => {
provider: {
name: 'aws',
runtime: 'nodejs4.3',
},
defaults: {
stage: 'dev',
region: 'us-east-1',
variableSyntax: '\\${foo}',

View File

@ -20,7 +20,7 @@ class Variables {
}
loadVariableSyntax() {
this.variableSyntax = RegExp(this.service.defaults.variableSyntax, 'g');
this.variableSyntax = RegExp(this.service.provider.variableSyntax, 'g');
}
populateService(processedOptions) {
@ -29,10 +29,9 @@ class Variables {
this.loadVariableSyntax();
const variableSyntaxProperty = this.service.defaults.variableSyntax;
const variableSyntaxProperty = this.service.provider.variableSyntax;
// temporally remove variable syntax from service otherwise it'll match
this.service.defaults.variableSyntax = true;
this.service.provider.variableSyntax = true;
/*
@ -49,7 +48,6 @@ class Variables {
}
});
this.service.defaults.variableSyntax = variableSyntaxProperty;
this.service.provider.variableSyntax = variableSyntaxProperty;
return this.service;
}

View File

@ -28,7 +28,7 @@ describe('Variables', () => {
it('should set variableSyntax', () => {
const serverless = new Serverless();
serverless.service.defaults.variableSyntax = '\\${{([\\s\\S]+?)}}';
serverless.service.provider.variableSyntax = '\\${{([\\s\\S]+?)}}';
serverless.variables.loadVariableSyntax();
expect(serverless.variables.variableSyntax).to.be.a('RegExp');
@ -55,7 +55,6 @@ describe('Variables', () => {
const fooValue = '${clientId()}';
const barValue = 'test';
serverless.service.defaults.variableSyntax = variableSyntax;
serverless.service.provider.variableSyntax = variableSyntax;
serverless.service.custom = {
@ -68,7 +67,7 @@ describe('Variables', () => {
};
serverless.variables.populateService();
expect(serverless.service.defaults.variableSyntax).to.equal(variableSyntax);
expect(serverless.service.provider.variableSyntax).to.equal(variableSyntax);
expect(serverless.service.resources.foo).to.equal(fooValue);
expect(serverless.service.resources.bar).to.equal(barValue);
});
@ -367,14 +366,13 @@ describe('Variables', () => {
const serverless = new Serverless();
serverless.variables.service = {
service: 'testService',
provider: 'testProvider',
defaults: serverless.service.defaults,
provider: serverless.service.provider,
};
serverless.variables.loadVariableSyntax();
const valueToPopulate = serverless.variables.getValueFromSelf('self:provider');
expect(valueToPopulate).to.be.equal('testProvider');
const valueToPopulate = serverless.variables.getValueFromSelf('self:service');
expect(valueToPopulate).to.be.equal('testService');
});
it('should handle self-references to the root of the serverless.yml file', () => {
const serverless = new Serverless();
@ -582,7 +580,7 @@ describe('Variables', () => {
},
anotherVar: '${self:custom.var}',
},
defaults: serverless.service.defaults,
provider: serverless.service.provider,
};
serverless.variables.loadVariableSyntax();

View File

@ -32,14 +32,13 @@ module.exports = {
throw new this.serverless.classes.Error('artifactFilePath was not supplied');
}
const body = fs.readFileSync(artifactFilePath);
const fileName = artifactFilePath.split(path.sep).pop();
const params = {
Bucket: this.bucketName,
Key: `${this.serverless.service.package.artifactDirectoryName}/${fileName}`,
Body: body,
Body: fs.createReadStream(artifactFilePath),
ContentType: 'application/zip',
};

View File

@ -71,10 +71,6 @@ describe('uploadArtifacts', () => {
const artifactFilePath = path.join(tmpDirPath, 'artifact.zip');
serverless.utils.writeFileSync(artifactFilePath, 'artifact.zip file content');
const artifactFileBuffer = new Buffer(
serverless.utils.readFileSync(artifactFilePath), 'binary'
);
const putObjectStub = sinon
.stub(awsDeploy.provider, 'request').returns(BbPromise.resolve());
@ -86,7 +82,7 @@ describe('uploadArtifacts', () => {
{
Bucket: awsDeploy.bucketName,
Key: `${awsDeploy.serverless.service.package.artifactDirectoryName}/artifact.zip`,
Body: artifactFileBuffer,
Body: sinon.match.object.and(sinon.match.has('path', artifactFilePath)),
ContentType: 'application/zip',
},
awsDeploy.options.stage,

View File

@ -10,10 +10,10 @@ module.exports = {
}
this.options.stage = this.options.stage
|| (this.serverless.service.defaults && this.serverless.service.defaults.stage)
|| (this.serverless.service.provider && this.serverless.service.provider.stage)
|| 'dev';
this.options.region = this.options.region
|| (this.serverless.service.defaults && this.serverless.service.defaults.region)
|| (this.serverless.service.provider && this.serverless.service.provider.region)
|| 'us-east-1';
return BbPromise.resolve();

View File

@ -39,9 +39,9 @@ describe('#validate', () => {
});
});
it('should use the service.defaults stage if present', () => {
it('should use the service.provider stage if present', () => {
awsPlugin.options.stage = false;
awsPlugin.serverless.service.defaults = {
awsPlugin.serverless.service.provider = {
stage: 'some-stage',
};
@ -57,9 +57,9 @@ describe('#validate', () => {
});
});
it('should use the service.defaults region if present', () => {
it('should use the service.provider region if present', () => {
awsPlugin.options.region = false;
awsPlugin.serverless.service.defaults = {
awsPlugin.serverless.service.provider = {
region: 'some-region',
};

2
npm-shrinkwrap.json generated
View File

@ -1,6 +1,6 @@
{
"name": "serverless",
"version": "1.5.1",
"version": "1.6.1",
"dependencies": {
"agent-base": {
"version": "2.0.1",

View File

@ -1,10 +1,11 @@
{
"name": "serverless",
"version": "1.5.1",
"version": "1.6.1",
"engines": {
"node": ">=4.0"
},
"preferGlobal": true,
"homepage": "https://github.com/serverless/serverless#readme",
"description": "Serverless Framework - Build web, mobile and IoT applications with serverless architectures using AWS Lambda, Azure Functions, Google CloudFunctions & more",
"author": "serverless.com",
"license": "MIT",